/** * Translates a debuggee Mirror to a wrapper object. * * @param o the Mirror object in the debuggee * @param v an additional argument used for the translation * @return translated object or <code>null</code> when the argument * is not possible to translate. */ public Object translate (Mirror o, Object v) { Object r = null; boolean verify = false; synchronized (cache) { WeakReference wr = cache.get (o); if (wr != null) r = wr.get (); if (r == null) { r = createTranslation (o, v); cache.put (o, new WeakReference<Object>(r)); } else { verify = true; } } if (verify) { verifyTranslation(r, o, v); } return r; }
/** * Translates a debuggee Mirror to a thread-specific wrapper object. * * @param thread the thread on which the object lives * @param o the Mirror object in the debuggee * @param v an additional argument used for the translation * @return translated object or <code>null</code> when the argument * is not possible to translate. */ public Object translateOnThread (JPDAThread thread, Mirror o, Object v) { Object r = null; boolean verify = false; synchronized (threadCache) { Map<Mirror, WeakReference<Object>> cache = threadCache.get(thread); if (cache == null) { cache = new WeakHashMap<>(); threadCache.put(thread, cache); } WeakReference wr = cache.get (o); if (wr != null) r = wr.get (); if (r == null) { r = createTranslation (o, v); cache.put (o, new WeakReference<Object>(r)); } else { verify = true; } } if (verify) { verifyTranslation(r, o, v); } return r; }
@Override public Mirror visitBlock(BlockTree arg0, EvaluationContext evaluationContext) { Mirror lastResult = null; try { evaluationContext.pushBlock(); for (StatementTree statementTree : arg0.getStatements()) { Mirror res = statementTree.accept(this, evaluationContext); if (res != null) { lastResult = res; } if (res instanceof CommandMirror) { break; } } } finally { evaluationContext.popBlock(); } return lastResult; }
@Override public Mirror visitDoWhileLoop(DoWhileLoopTree arg0, EvaluationContext evaluationContext) { ExpressionTree condition = arg0.getCondition(); Tree statement = arg0.getStatement(); Mirror result = null; do { try { evaluationContext.pushBlock(); Mirror res = statement.accept(this, evaluationContext); if (res instanceof Break) { break; } else if (res instanceof Continue) { continue; } if (res != null) { result = res; } } finally { evaluationContext.popBlock(); } } while (evaluateCondition(arg0, evaluationContext, condition)); return result; }
@Override public Mirror visitIf(IfTree arg0, EvaluationContext evaluationContext) { boolean evaluatedCondition = evaluateCondition(arg0, evaluationContext, arg0.getCondition()); StatementTree statement; if (evaluatedCondition) { statement = arg0.getThenStatement(); } else { statement = arg0.getElseStatement(); } if (statement != null) { try { evaluationContext.pushBlock(); return statement.accept(this, evaluationContext); } finally { evaluationContext.popBlock(); } } else { return null; } }
@Override public Mirror visitArrayAccess(ArrayAccessTree arg0, EvaluationContext evaluationContext) { Mirror array = arg0.getExpression().accept(this, evaluationContext); if (array == null) { Assert.error(arg0, "arrayIsNull", arg0.getExpression()); } Mirror index = arg0.getIndex().accept(this, evaluationContext); if (!(array instanceof ArrayReference)) { Assert.error(arg0, "notArrayType", arg0.getExpression()); } if (!(index instanceof PrimitiveValue)) { Assert.error(arg0, "arraySizeBadType", index); } int i = ((PrimitiveValue) index).intValue(); if (i < 0 || i >= ((ArrayReference) array).length()) { Assert.error(arg0, "arrayIndexOutOfBounds", array, i); } evaluationContext.putArrayAccess(arg0, (ArrayReference)array, i); return ((ArrayReference) array).getValue(i); }
@Override public Mirror visitReturn(ReturnTree arg0, EvaluationContext evaluationContext) { ExpressionTree exprTree = arg0.getExpression(); Mirror result; if (exprTree == null) { VirtualMachine vm = evaluationContext.getDebugger().getVirtualMachine(); if (vm == null) { return null; } // vm.mirrorOfVoid(); [TODO] result = null; } else { result = exprTree.accept(this, evaluationContext); } return new Return(result); }
@Override public Mirror visitArrayType(ArrayTypeTree arg0, EvaluationContext evaluationContext) { Mirror arrayType = arg0.getType().accept(this, evaluationContext); if (!(arrayType instanceof Type)) { return arrayType; } Type type = (Type) arrayType; String arrayClassName = type.name()+"[]"; ReferenceType aType = getOrLoadClass(type.virtualMachine(), arrayClassName, evaluationContext); if (aType != null) { return aType; } else { Assert.error(arg0, "unknownType", arrayClassName); return null; } }
@Override public Mirror visitInstanceOf(InstanceOfTree arg0, EvaluationContext evaluationContext) { Mirror expr = arg0.getExpression().accept(this, evaluationContext); VirtualMachine vm = evaluationContext.getDebugger().getVirtualMachine(); if (vm == null) { return null; } if (expr == null) { return mirrorOf(vm, false); } Assert.assertAssignable(expr, ObjectReference.class, arg0, "instanceOfLeftOperandNotAReference", expr); ReferenceType expressionType = ((ObjectReference) expr).referenceType(); Type type = (Type) arg0.getType().accept(this, evaluationContext); return mirrorOf(vm, instanceOf(expressionType, type)); }
@Override public Mirror visitWhileLoop(WhileLoopTree arg0, EvaluationContext evaluationContext) { ExpressionTree condition = arg0.getCondition(); Tree statement = arg0.getStatement(); Mirror result = null; while (evaluateCondition(arg0, evaluationContext, condition)) { try { evaluationContext.pushBlock(); Mirror res = statement.accept(this, evaluationContext); if (res instanceof Break) { break; } else if (res instanceof Continue) { continue; } if (res != null) { result = res; } } finally { evaluationContext.popBlock(); } } return result; }
/** * Translates a debuggee Mirror to a wrapper object. * * @param o the Mirror object in the debuggee * @return translated object or <code>null</code> when the argument * is not possible to translate. */ public Object translate (Mirror o) { Object r = null; synchronized (cache) { WeakReference wr = cache.get (o); if (wr != null) r = wr.get (); if (r == null) { r = createTranslation (o); cache.put (o, new WeakReference<Object>(r)); } } return r; }
/** * Gen an existing wrapper object translation of a debuggee Mirror. * * @param o the Mirror object in the debuggee * @return translated object or <code>null</code> when there is no existing * translation. */ public Object translateExisting(Mirror o) { Object r = null; synchronized (cache) { WeakReference wr = cache.get (o); if (wr != null) r = wr.get (); } return r; }
/** * Explicitly remove the translation of the mirror object. */ public void remove(Mirror o) { synchronized (cache) { cache.remove(o); } }
@Override public Mirror scan(Tree tree, EvaluationContext evaluationContext) { Mirror result = super.scan(tree, evaluationContext); if (result instanceof ArtificialMirror) { return ((ArtificialMirror) result).getVMMirror(); } return result; }
@Override public Mirror scan(TreePath path, EvaluationContext evaluationContext) { Mirror result = super.scan(path, evaluationContext); if (result instanceof ArtificialMirror) { return ((ArtificialMirror) result).getVMMirror(); } return result; }
@Override public Mirror scan(Iterable<? extends Tree> nodes, EvaluationContext evaluationContext) { Mirror result = super.scan(nodes, evaluationContext); if (result instanceof ArtificialMirror) { return ((ArtificialMirror) result).getVMMirror(); } return result; }
@Override public Mirror visitAssignment(AssignmentTree arg0, EvaluationContext evaluationContext) { Mirror var = arg0.getVariable().accept(this, evaluationContext); Mirror exp = arg0.getExpression().accept(this, evaluationContext); Value value = (Value) exp; return setToMirror(arg0.getVariable(), value, evaluationContext); }
@Override public Mirror visitBreak(BreakTree arg0, EvaluationContext evaluationContext) { Name label = arg0.getLabel(); if (label != null) { Assert.error(arg0, "unsupported"); return null; } return new Break(); }
@Override public Mirror visitConditionalExpression(ConditionalExpressionTree arg0, EvaluationContext evaluationContext) { boolean isTrue = evaluateCondition(arg0, evaluationContext, arg0.getCondition()); if (isTrue) { return arg0.getTrueExpression().accept(this, evaluationContext); } else { return arg0.getFalseExpression().accept(this, evaluationContext); } }
@Override public Mirror visitContinue(ContinueTree arg0, EvaluationContext evaluationContext) { Name label = arg0.getLabel(); if (label != null) { Assert.error(arg0, "unsupported"); return null; } return new Continue(); }
@Override public Mirror visitForLoop(ForLoopTree arg0, EvaluationContext evaluationContext) { try { evaluationContext.pushBlock(); for (StatementTree st : arg0.getInitializer()) { st.accept(this, evaluationContext); } Mirror result = null; ExpressionTree condition = arg0.getCondition(); List<? extends ExpressionStatementTree> updateList = arg0.getUpdate(); StatementTree statement = arg0.getStatement(); while (condition == null || evaluateCondition(arg0, evaluationContext, condition)) { Mirror value = null; try { evaluationContext.pushBlock(); value = statement.accept(this, evaluationContext); if (value instanceof Break) { break; } else if (value instanceof Continue) { continue; } if (value != null) { result = value; } } finally { evaluationContext.popBlock(); if ((value instanceof Continue) || !(value instanceof CommandMirror)) { for (Tree tree : updateList) { tree.accept(this, evaluationContext); } // for } // if } // finally } // while return result; } finally { evaluationContext.popBlock(); } }
private boolean evaluateCondition(Tree arg0, EvaluationContext evaluationContext, ExpressionTree condition) { Mirror conditionValue = condition.accept(this, evaluationContext); if (conditionValue instanceof ObjectReference) { conditionValue = unboxIfCan(arg0, (ObjectReference) conditionValue, evaluationContext); } if (!(conditionValue instanceof BooleanValue)) { String type = "N/A"; // NOI18N if (conditionValue instanceof Value) { type = ((Value) conditionValue).type().name(); } Assert.error(arg0, "notABoolean", condition.toString(), conditionValue, type); } return ((BooleanValue) conditionValue).value(); }
@Override public Mirror visitPrimitiveType(PrimitiveTypeTree arg0, EvaluationContext evaluationContext) { TypeKind type = arg0.getPrimitiveTypeKind(); VirtualMachine vm = evaluationContext.getDebugger().getVirtualMachine(); if (vm == null) { return null; } switch(type) { case BOOLEAN: return vm.mirrorOf(true).type(); case BYTE: return vm.mirrorOf((byte) 0).type(); case CHAR: return vm.mirrorOf('a').type(); case DOUBLE: return vm.mirrorOf(0.).type(); case FLOAT: return vm.mirrorOf(0f).type(); case INT: return vm.mirrorOf(0).type(); case LONG: return vm.mirrorOf(0l).type(); case SHORT: return vm.mirrorOf((short) 0).type(); case VOID: return vm.mirrorOfVoid().type(); default: throw new IllegalStateException("Tree = "+arg0); } }
@Override public Mirror visitUnionType(UnionTypeTree node, EvaluationContext p) { // union type expression in a multicatch var declaration // unsupported, since catch is unsupported Assert.error(node, "unsupported"); return null; }
@Override public Mirror visitIntersectionType(IntersectionTypeTree node, EvaluationContext p) { // intersection type in a cast expression List<? extends Tree> bounds = node.getBounds(); List<ReferenceType> typeList = new ArrayList<ReferenceType>(); for (Tree type : bounds) { Mirror typeMirror = type.accept(this, p); if (typeMirror instanceof ReferenceType) { typeList.add((ReferenceType) typeMirror); } } Type intersectionType = new IntersectionType(typeList.toArray(new ReferenceType[] {})); subExpressionTypes.put(node, intersectionType); return intersectionType; }
@Override public Mirror visitLambdaExpression(LambdaExpressionTree node, EvaluationContext p) { /** * A tree node for a lambda expression. * It creates a new class, which is unsupported. */ Assert.error(node, "noNewClassWithBody"); return super.visitLambdaExpression(node, p); }
@Override public Mirror visitMemberReference(MemberReferenceTree node, EvaluationContext p) { /** * A tree node for a member reference expression. * There are two kinds of member references: * method references (ReferenceMode.INVOKE) and * constructor references (ReferenceMode.NEW). * It creates a new class, which is unsupported. */ Assert.error(node, "noNewClassWithBody"); return super.visitMemberReference(node, p); }
private static void unboxMethodToBeCalled(Tree arg0, Mirror v, EvaluationContext evaluationContext) { if (!evaluationContext.canInvokeMethods()) { Assert.error(arg0, "canNotInvokeMethods"); } if (loggerMethod.isLoggable(Level.FINE)) { loggerMethod.log(Level.FINE, "STARTED : Unbox {0} in thread {1}", new Object[]{v, evaluationContext.getFrame().thread()}); } evaluationContext.methodToBeInvoked(); }
private String toString(Tree arg0, Mirror v, EvaluationContext evaluationContext) { if (v instanceof PrimitiveValue) { PrimitiveValue pv = (PrimitiveValue) v; PrimitiveType t = (PrimitiveType) pv.type(); if (t instanceof ByteType) { return Byte.toString(pv.byteValue()); } if (t instanceof BooleanType) { return Boolean.toString(pv.booleanValue()); } if (t instanceof CharType) { return Character.toString(pv.charValue()); } if (t instanceof ShortType) { return Short.toString(pv.shortValue()); } if (t instanceof IntegerType) { return Integer.toString(pv.intValue()); } if (t instanceof LongType) { return Long.toString(pv.longValue()); } if (t instanceof FloatType) { return Float.toString(pv.floatValue()); } if (t instanceof DoubleType) { return Double.toString(pv.doubleValue()); } throw new IllegalStateException("Unknown primitive type: "+t); } if (v == null) { return "" + null; } ObjectReference ov = (ObjectReference) v; if (ov instanceof ArrayReference) { return "#" + ov.uniqueID() + " " + ov.type().name() + "(length=" + ((ArrayReference) ov).length() + ")"; } if (ov instanceof StringReference) { return ((StringReference) ov).value(); } // Call toString() method: List<? extends TypeMirror> typeArguments = Collections.emptyList(); Method method; try { method = getConcreteMethod((ReferenceType) ov.type(), "toString", typeArguments); } catch (UnsuitableArgumentsException uaex) { throw new IllegalStateException(uaex); } ((ClassType) ov.type()).methodsByName("toString"); List<Value> argVals = Collections.emptyList(); Value sv = invokeMethod(arg0, method, false, null, ov, argVals, evaluationContext, false); if (sv instanceof StringReference) { return ((StringReference) sv).value(); } else if (sv == null) { return null; } else { return "Result of toString() call on "+ov+" is not a String, but: "+sv; // NOI18N - should not ever happen. } }
public boolean equals(Object obj) { if ((obj != null) && (obj instanceof Mirror)) { Mirror other = (Mirror)obj; return vm.equals(other.virtualMachine()); } else { return false; } }
/** * Throw NullPointerException on null mirrors. * Throw VMMismatchException on wrong VM. */ void validateMirrors(Collection<? extends Mirror> mirrors) { Iterator<? extends Mirror> iter = mirrors.iterator(); while (iter.hasNext()) { MirrorImpl mirror = (MirrorImpl)iter.next(); if (!vm.equals(mirror.vm)) { throw new VMMismatchException(mirror.toString()); } } }
/** * Allow null mirrors. * Throw VMMismatchException on wrong VM. */ void validateMirrorsOrNulls(Collection<? extends Mirror> mirrors) { Iterator<? extends Mirror> iter = mirrors.iterator(); while (iter.hasNext()) { MirrorImpl mirror = (MirrorImpl)iter.next(); if ((mirror != null) && !vm.equals(mirror.vm)) { throw new VMMismatchException(mirror.toString()); } } }
public F3Mirror(F3VirtualMachine f3vm, Mirror underlying) { if (underlying == null) { throw new NullPointerException("underlying Mirror object is null!"); } if (underlying instanceof F3Mirror) { throw new IllegalArgumentException("repeated wrapping!!"); } this.f3vm = f3vm; this.underlying = underlying; }
@Override public Mirror visitAnnotation(AnnotationTree arg0, EvaluationContext evaluationContext) { return null; }
@Override public Mirror visitAssert(AssertTree arg0, EvaluationContext evaluationContext) { Assert.error(arg0, "unsupported"); return null; }
@Override public Mirror visitCase(CaseTree arg0, EvaluationContext evaluationContext) { // case is handled within visitSwitch method Assert.error(arg0, "unsupported"); return null; }
@Override public Mirror visitCatch(CatchTree arg0, EvaluationContext evaluationContext) { Assert.error(arg0, "unsupported"); return null; }
@Override public Mirror visitClass(ClassTree arg0, EvaluationContext evaluationContext) { Assert.error(arg0, "unsupported"); return null; }
@Override public Mirror visitErroneous(ErroneousTree arg0, EvaluationContext evaluationContext) { Assert.error(arg0, "errorneous"); return null; }
@Override public Mirror visitExpressionStatement(ExpressionStatementTree arg0, EvaluationContext evaluationContext) { return arg0.getExpression().accept(this, evaluationContext); }