public ValueEmitter assertIs(ValueType type) { if (!pe.hierarchy.isSuperType(type, this.type, true)) { throw new EmitException("Value type " + this.type + " is not subtype of " + type); } return this; }
private boolean calculateDestSubsetOfSrc() { if (source.typeFilter == null) { return true; } if (destination.typeFilter == null) { return false; } ValueType sourceType = source.typeFilter; ValueType destType = destination.typeFilter; ClassHierarchy hierarchy = source.dependencyAnalyzer.getClassHierarchy(); return hierarchy.isSuperType(sourceType, destType, false); } }
public boolean isSuperType(ValueType superType, ValueType subType, boolean defaultValue) { if (superType.equals(subType)) { return true; } if (superType instanceof ValueType.Primitive || subType instanceof ValueType.Primitive) { return false; } if (superType.isObject("java.lang.Object")) { return true; } if (superType instanceof ValueType.Object && subType instanceof ValueType.Object) { return isSuperType(((ValueType.Object) superType).getClassName(), ((ValueType.Object) subType).getClassName(), defaultValue); } else if (superType instanceof ValueType.Array & subType instanceof ValueType.Array) { return isSuperType(((ValueType.Array) superType).getItemType(), ((ValueType.Array) subType).getItemType(), defaultValue); } else { return false; } }
private boolean matchSignature(ClassHierarchy hierarchy, MethodReader functionMethod, MethodReader candidateMethod) { if (functionMethod.parameterCount() > candidateMethod.parameterCount()) { return false; } for (int i = 0; i < functionMethod.parameterCount(); ++i) { if (!hierarchy.isSuperType(functionMethod.parameterType(i), candidateMethod.parameterType(i), false)) { return false; } } return true; }
public void raise() { if (!pe.hierarchy.isSuperType(ValueType.object("java.lang.Throwable"), type, true)) { throw new EmitException("Can't throw non-exception value: " + type); } RaiseInstruction insn = new RaiseInstruction(); insn.setException(variable); pe.addInstruction(insn); }
candidate = method; } else { boolean moreSpecial = context.getHierarchy().isSuperType(candidate.getResultType(), method.getResultType(), false); if (moreSpecial) {
@Override public void consume(DependencyType type) { ClassHierarchy hierarchy = analyzer.getClassHierarchy(); for (int i = 0; i < exceptions.length; ++i) { if (exceptions[i] == null || hierarchy.isSuperType(exceptions[i].getName(), type.getName(), false)) { if (vars[i] != null) { vars[i].propagate(type); } return; } } method.getThrown().propagate(type); } }
private ValueEmitter boxPrimitive(ValueType type) { if (!(type instanceof ValueType.Object)) { throw new EmitException("Can't convert " + this.type + " to " + type); } String targetClass = ((ValueType.Object) type).getClassName(); PrimitiveType primitiveType = ((ValueType.Primitive) this.type).getKind(); String boxClassName = getPrimitiveClassName(primitiveType); ValueEmitter result = invokeValueOf(boxClassName); if (!pe.hierarchy.isSuperType(targetClass, boxClassName, false)) { throw new EmitException("Can't convert " + this.type + " to " + targetClass); } return result; }
private Program generateAfterProgram(MethodHolder method, ClassHierarchy hierarchy) { ProgramEmitter pe = ProgramEmitter.create(method, hierarchy); ValueEmitter testCaseVar = pe.getField(TestEntryPoint.class, "testCase", Object.class); List<ClassReader> classes = collectSuperClasses(pe.getClassSource(), testMethod.getClassName()); classes.stream() .flatMap(cls -> cls.getMethods().stream()) .filter(m -> m.getAnnotations().get(JUNIT4_AFTER) != null) .forEach(m -> testCaseVar.cast(ValueType.object(m.getOwnerName())).invokeVirtual(m.getReference())); if (hierarchy.isSuperType(JUNIT3_BASE_CLASS, testMethod.getClassName(), false)) { testCaseVar.cast(ValueType.object(JUNIT3_BASE_CLASS)).invokeVirtual(JUNIT3_AFTER); } pe.exit(); return pe.getProgram(); }
} else if (type.isObject(Class.class)) { return convertClass(value.getJavaClass()); } else if (hierarchy.isSuperType(ValueType.parse(Enum.class), type, false)) { FieldReference fieldRef = value.getEnumValue(); Class<?> enumClass = Class.forName(fieldRef.getClassName(), true, classLoader); return enumClass.getField(fieldRef.getFieldName()).get(null); } else if (hierarchy.isSuperType(ValueType.parse(Annotation.class), type, false)) { Class<?> annotType = convertClass(type); AnnotationProxy handler = new AnnotationProxy(classLoader, hierarchy, value.getAnnotation(), annotType);
private void propagateAlongCasts() { for (ValueCast cast : casts) { int fromNode = nodeMapping[packNodeAndDegree(cast.fromVariable, 0)]; if (!formerNodeChanged[fromNode] && !nodeChanged[fromNode]) { continue; } int toNode = nodeMapping[packNodeAndDegree(cast.toVariable, 0)]; IntHashSet targetTypes = getNodeTypes(toNode); for (IntCursor cursor : types[fromNode]) { if (targetTypes.contains(cursor.value)) { continue; } String className = typeList.get(cursor.value); ValueType type; if (className.startsWith("[")) { type = ValueType.parseIfPossible(className); if (type == null) { type = ValueType.arrayOf(ValueType.object("java.lang.Object")); } } else { type = ValueType.object(className); } if (hierarchy.isSuperType(cast.targetType, type, false)) { changed = true; nodeChanged[toNode] = true; targetTypes.add(cursor.value); } } } }
private Program generateBeforeProgram(MethodHolder method, ClassHierarchy hierarchy) { ProgramEmitter pe = ProgramEmitter.create(method, hierarchy); ValueEmitter testCaseInitVar = pe.getField(TestEntryPoint.class, "testCase", Object.class); pe.when(testCaseInitVar.isNull()) .thenDo(() -> { pe.setField(TestEntryPoint.class, "testCase", pe.construct(testClassName).cast(Object.class)); }); ValueEmitter testCaseVar = pe.getField(TestEntryPoint.class, "testCase", Object.class); if (hierarchy.isSuperType(JUNIT3_BASE_CLASS, testMethod.getClassName(), false)) { testCaseVar.cast(ValueType.object(JUNIT3_BASE_CLASS)).invokeVirtual(JUNIT3_BEFORE); } List<ClassReader> classes = collectSuperClasses(pe.getClassSource(), testMethod.getClassName()); Collections.reverse(classes); classes.stream() .flatMap(cls -> cls.getMethods().stream()) .filter(m -> m.getAnnotations().get(JUNIT4_BEFORE) != null) .forEach(m -> testCaseVar.cast(ValueType.object(m.getOwnerName())).invokeVirtual(m.getReference())); pe.exit(); return pe.getProgram(); }
@Override public void methodReached(DependencyAgent agent, MethodDependency method) { switch (method.getReference().getName()) { case "invoke": case "instantiate": case "function": if (reachedFunctorMethods.add(method.getReference()) && !method.isMissing()) { for (int i = 0; i < method.getReference().parameterCount(); ++i) { DependencyNode node = method.getVariable(i); if (functorParamNodes.add(node)) { node.addConsumer(type -> { if (agent.getClassHierarchy().isSuperType(method.getMethod().getOwnerName(), type.getName(), false)) { reachFunctorMethods(agent, type.getName()); } }); } } } break; case "unwrapString": method.getResult().propagate(agent.getType("java.lang.String")); break; } }
private void propagateException(String thrownTypeName, BasicBlock block) { for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { String expectedType = tryCatch.getExceptionType(); if (expectedType == null || hierarchy.isSuperType(expectedType, thrownTypeName, false)) { if (tryCatch.getHandler().getExceptionVariable() == null) { break; } int exceptionNode = packNodeAndDegree(tryCatch.getHandler().getExceptionVariable().getIndex(), 0); exceptionNode = nodeMapping[exceptionNode]; int thrownType = getTypeByName(thrownTypeName); if (getNodeTypes(exceptionNode).add(thrownType)) { nodeChanged[exceptionNode] = true; changed = true; } break; } } }
@Override public void consume(DependencyType type) { if (!agent.getClassHierarchy().isSuperType(superMethod.getClassName(), type.getName(), false)) { return; } MethodReader method = agent.getClassSource().resolveImplementation(new MethodReference( type.getName(), superMethod.getDescriptor())); if (method == null) { return; } virtualMethods.add(method.getReference()); MethodDependency methodDep = agent.linkMethod(method.getReference()); methodDep.use(); for (int i = 0; i < methodDep.getParameterCount(); ++i) { allClassesNode.connect(methodDep.getVariable(i)); allClassesNode.connect(methodDep.getVariable(i).getArrayItem()); } } }
if (!hierarchy.isSuperType(method.parameterType(i), arguments[i].getType(), false)) { throw new EmitException("Argument " + i + " of type " + arguments[i].getType() + " is " + "not compatible with method " + method); if (!hierarchy.isSuperType(method.getClassName(), ((ValueType.Object) type).getClassName(), true)) { throw new EmitException("Can't call " + method + " on non-compatible class " + type);
if (hierarchy.isSuperType(Resource.class.getName(), owningClass, false)) { if (method.getReturnType().isObject(String.class)) { Variable var = program.createVariable();
public ValueEmitter invoke(MethodReference method, ValueEmitter... arguments) { for (int i = 0; i < method.parameterCount(); ++i) { if (!hierarchy.isSuperType(method.parameterType(i), arguments[i].getType(), true)) { throw new EmitException("Argument " + i + " of type " + arguments[i].getType() + " is " + "not compatible with method " + method); } } Variable result = null; if (method.getReturnType() != ValueType.VOID) { result = program.createVariable(); } InvokeInstruction insn = new InvokeInstruction(); insn.setType(InvocationType.SPECIAL); insn.setMethod(method); insn.setReceiver(result); Variable[] insnArguments = new Variable[arguments.length]; for (int i = 0; i < insnArguments.length; ++i) { insnArguments[i] = arguments[i].variable; } insn.setArguments(insnArguments); addInstruction(insn); return result != null ? var(result, method.getReturnType()) : null; }
@Override public void methodReached(DependencyAgent agent, MethodDependency method) { MethodReference ref = method.getReference(); MethodReference asyncRef = getAsyncReference(ref); MethodDependency asyncMethod = agent.linkMethod(asyncRef); method.addLocationListener(asyncMethod::addLocation); int paramCount = ref.parameterCount(); for (int i = 0; i <= paramCount; ++i) { method.getVariable(i).connect(asyncMethod.getVariable(i)); } asyncMethod.getVariable(paramCount + 1).propagate(agent.getType(AsyncCallbackWrapper.class.getName())); MethodDependency completeMethod = agent.linkMethod( new MethodReference(AsyncCallbackWrapper.class, "complete", Object.class, void.class)); if (method.getResult() != null) { completeMethod.getVariable(1).connect(method.getResult(), type -> agent.getClassHierarchy() .isSuperType(ref.getReturnType(), ValueType.object(type.getName()), false)); } completeMethod.use(); MethodDependency errorMethod = agent.linkMethod(new MethodReference(AsyncCallbackWrapper.class, "error", Throwable.class, void.class)); errorMethod.getVariable(1).connect(method.getThrown()); errorMethod.use(); agent.linkMethod(new MethodReference(AsyncCallbackWrapper.class, "create", AsyncCallback.class, AsyncCallbackWrapper.class)).use(); asyncMethod.use(); }
method.getVariable(i).connect(allClassesNode); method.getVariable(i).addConsumer(type -> { if (agent.getClassHierarchy().isSuperType("java.lang.Enum", type.getName(), false)) { MethodReference toStringMethod = new MethodReference(type.getName(), "toString", ValueType.parse(String.class));