private static AstNode getExpression(MethodReference method, AstNode statement) { if (method.getReturnType() == ValueType.VOID) { if (statement instanceof ExpressionStatement) { return ((ExpressionStatement) statement).getExpression(); } } else { if (statement instanceof ReturnStatement) { return ((ReturnStatement) statement).getReturnValue(); } } return null; }
@Override public void invoke(VariableReader receiver, VariableReader instance, MethodReference method, List<? extends VariableReader> arguments, InvocationType type) { if (receiver != null) { types[receiver.getIndex()] = convert(method.getReturnType()); } }
@Override DependencyNode createResultNode(MethodReference method) { DependencyNode node = createNode(method.getReturnType()); node.method = method; if (shouldTag) { node.setTag(method + ":RESULT"); } return node; }
public static <T> Value<T> lazy(Computation<T> computation) { Fragment fragment = (Fragment) computation; return lazyFragment(fragment.method.getReturnType(), () -> emit(computation)); }
private void emitSingleUsage(MethodModel model, ProgramEmitter pe, ValueEmitter[] paramVars) { MethodReference usage = model.getUsages().values().stream().findFirst().orElse(null); ValueEmitter result = pe.invoke(usage, paramVars); if (usage.getReturnType() == ValueType.VOID) { pe.exit(); } else { assert result != null : "Expected non-null result at " + model.getMethod(); result.returnValue(); } }
private Method asJvmMethod(MethodReference method) { Class<?> cls; try { cls = Class.forName(method.getClassName(), false, classLoader); } catch (ClassNotFoundException e) { throw new RuntimeException("Can't find class " + method.getClassName()); } Class<?>[] jvmParameters = new Class[method.parameterCount()]; for (int i = 0; i < method.parameterCount(); ++i) { jvmParameters[i] = asJvmClass(method.parameterType(i)); } Class<?> jvmReturnType = asJvmClass(method.getReturnType()); for (Method jvmMethod : cls.getDeclaredMethods()) { if (Arrays.equals(jvmMethod.getParameterTypes(), jvmParameters) && jvmReturnType.equals(jvmMethod.getReturnType())) { return jvmMethod; } } throw new RuntimeException("Method not found: " + method); }
private void calculateLayout(ResourceTypeDescriptor typeDescriptor, Map<MethodReference, PropertyDescriptor> layout) { Map<String, Integer> propertyIndexes = new HashMap<>(); List<String> propertyNames = new ArrayList<>(typeDescriptor.getPropertyTypes().keySet()); for (int i = 0; i < propertyNames.size(); ++i) { propertyIndexes.put(propertyNames.get(i), i); } Method[] methods = new Method[typeDescriptor.getPropertyTypes().size()]; for (Method method : typeDescriptor.getMethods().keySet()) { ResourceMethodDescriptor methodDescriptor = typeDescriptor.getMethods().get(method); if (methodDescriptor.getType() == ResourceAccessorType.SETTER) { continue; } String propertyName = methodDescriptor.getPropertyName(); int index = propertyIndexes.get(propertyName); methods[index] = method; } int currentOffset = 0; for (Method method : methods) { MethodReference methodRef = MethodReference.parse(method); ValueType propertyType = methodRef.getReturnType(); int size = WasmClassGenerator.getTypeSize(propertyType); currentOffset = BinaryWriter.align(currentOffset, size); PropertyDescriptor propertyDescriptor = new PropertyDescriptor(); propertyDescriptor.offset = currentOffset; propertyDescriptor.type = propertyType; layout.put(methodRef, propertyDescriptor); currentOffset += size; } }
@Override public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) { WasmExpression selector = manager.generate(invocation.getArguments().get(0)); WasmIndirectCall call = new WasmIndirectCall(selector); for (ValueType type : invocation.getMethod().getParameterTypes()) { call.getParameterTypes().add(WasmGeneratorUtil.mapType(type)); } if (invocation.getMethod().getReturnType() != ValueType.VOID) { call.setReturnType(WasmGeneratorUtil.mapType(invocation.getMethod().getReturnType())); } for (int i = 1; i < invocation.getArguments().size(); ++i) { call.getArguments().add(manager.generate(invocation.getArguments().get(i))); } return call; } }
@Override public void invoke(VariableReader receiver, VariableReader instance, MethodReference method, List<? extends VariableReader> arguments, InvocationType type) { ValueType[] paramTypes = method.getParameterTypes(); for (int i = 0; i < paramTypes.length; ++i) { if (!(paramTypes[i] instanceof ValueType.Primitive)) { escaping.add(arguments.get(i).getIndex()); } } if (instance != null) { escaping.add(instance.getIndex()); } if (receiver != null && !(method.getReturnType() instanceof ValueType.Primitive)) { escaping.add(receiver.getIndex()); } }
@Override public void invoke(VariableReader receiver, VariableReader instance, MethodReference method, List<? extends VariableReader> arguments, InvocationType type) { if (instance == null) { invokeSpecial(receiver, null, method, arguments); } else { switch (type) { case SPECIAL: invokeSpecial(receiver, instance, method, arguments); break; case VIRTUAL: invokeVirtual(receiver, instance, method, arguments); break; } if (method.getName().equals("getClass") && method.parameterCount() == 0 && method.getReturnType().isObject(Class.class) && receiver != null) { getNode(instance).connect(getNode(receiver).getClassValueNode()); } } }
public void generateMethodSignature(CodeWriter writer, MethodReference methodRef, boolean isStatic, boolean withNames) { writer.print("static "); writer.printType(methodRef.getReturnType()).print(" ").print(names.forMethod(methodRef)).print("("); generateMethodParameters(writer, methodRef.getDescriptor(), isStatic, withNames); writer.print(")"); }
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 apply(IntrinsicContext context, InvocationExpr invocation) { MethodReference method = invocation.getMethod(); if (method.getClassName().equals(Function.class.getName())) { generateGetFunction(context, invocation); return; } context.writer().print("(((").printType(method.getReturnType()).print(" (*)("); if (method.parameterCount() > 0) { context.writer().printType(method.parameterType(0)); for (int i = 1; i < method.parameterCount(); ++i) { context.writer().print(", ").printType(method.parameterType(i)); } } context.writer().print(")) "); context.emit(invocation.getArguments().get(0)); context.writer().print(")("); if (invocation.getArguments().size() > 1) { context.emit(invocation.getArguments().get(1)); for (int i = 2; i < invocation.getArguments().size(); ++i) { context.writer().print(", "); context.emit(invocation.getArguments().get(i)); } } context.writer().print("))"); }
public static <T> Value<T> emit(Computation<T> computation) { if (computation instanceof ValueImpl<?>) { @SuppressWarnings("unchecked") ValueImpl<T> valueImpl = (ValueImpl<T>) computation; Variable var = varContext.emitVariable(valueImpl, new CallLocation(templateMethod, generator.location)); return new ValueImpl<>(var, varContext, valueImpl.type); } else if (computation instanceof LazyValueImpl<?>) { LazyValueImpl<?> valueImpl = (LazyValueImpl<?>) computation; Variable var = generator.lazy(valueImpl); return var != null ? new ValueImpl<>(var, varContext, valueImpl.type) : null; } else { Fragment fragment = (Fragment) computation; MethodReader method = hierarchy.resolve(fragment.method); generator.addProgram(method.getProgram(), fragment.capturedValues); return new ValueImpl<>(generator.getResultVar(), varContext, fragment.method.getReturnType()); } }
private MethodReference buildMethodReference(String suffix) { if (model.getClassParameterIndex() < 0) { return new MethodReference(model.getMethod().getClassName() + "$PROXY$" + suffix, model.getMethod().getDescriptor()); } int i; ValueType[] signature = new ValueType[model.getMetaParameterCount() + 1]; for (i = 0; i < signature.length - 1; ++i) { signature[i] = model.getMetaParameterType(i); } signature[i] = model.getMethod().getReturnType(); return new MethodReference(model.getMethod().getClassName() + "$PROXY$" + suffix, model.getMethod().getName(), signature); }
if (method.getReturnType() != ValueType.VOID) { result = pe.getProgram().createVariable(); return result != null ? pe.var(result, method.getReturnType()) : null;
@Override public void completing(DependencyAgent agent) { for (MethodModel model : describer.getKnownMethods()) { ProgramEmitter pe = ProgramEmitter.create(model.getMethod().getDescriptor(), agent.getClassHierarchy()); ValueEmitter[] paramVars = new ValueEmitter[model.getMetaParameterCount()]; int offset = model.isStatic() ? 1 : 0; for (int i = 0; i < paramVars.length; ++i) { paramVars[i] = pe.var(i + offset, model.getMetaParameterType(i)); } if (model.getUsages().size() == 1) { emitSingleUsage(model, pe, paramVars); } else if (model.getUsages().isEmpty()) { if (model.getMethod().getReturnType() == ValueType.VOID) { pe.exit(); } else { pe.constantNull(Object.class).returnValue(); } } else { emitMultipleUsage(model, pe, agent, paramVars); } agent.submitMethod(model.getMethod(), new Optimizations().apply(pe.getProgram(), model.getMethod())); } }
public ValueEmitter invoke(InvocationType invokeType, String className, String name, ValueType resultType, ValueEmitter... arguments) { if (!(type instanceof ValueType.Object)) { throw new EmitException("Can't invoke method on non-object type: " + type); } Variable result = null; ValueType[] signature = new ValueType[arguments.length + 1]; for (int i = 0; i < arguments.length; ++i) { signature[i] = arguments[i].type; } signature[arguments.length] = resultType; MethodReference method = new MethodReference(className, name, signature); if (method.getReturnType() != ValueType.VOID) { result = pe.getProgram().createVariable(); } InvokeInstruction insn = new InvokeInstruction(); insn.setType(invokeType); insn.setMethod(method); insn.setInstance(variable); 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); pe.addInstruction(insn); return result != null ? pe.var(result, resultType) : null; }
String owningClass = method.getClassName(); if (hierarchy.isSuperType(Resource.class.getName(), owningClass, false)) { if (method.getReturnType().isObject(String.class)) { Variable var = program.createVariable(); InvokeInstruction amplifyInstruction = new InvokeInstruction();
@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(); }