Mercurial > hg > truffle
diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java @ 20938:18c0f02fa4d2
Truffle-DSL: make type systems optional.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 14 Apr 2015 15:12:48 +0200 |
parents | 1671d9111c47 |
children | 476374f3fe9a |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Tue Apr 14 22:12:03 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Tue Apr 14 15:12:48 2015 +0200 @@ -61,16 +61,19 @@ private final ProcessorContext context; private final NodeData node; private final TypeSystemData typeSystem; - private final TypeData genericType; + private final TypeMirror genericType; + private final TypeMirror voidType; private final DSLOptions options; private final boolean singleSpecializable; private final int varArgsThreshold; + private final Set<TypeMirror> expectedTypes = new HashSet<>(); public NodeGenFactory(ProcessorContext context, NodeData node) { this.context = context; this.node = node; this.typeSystem = node.getTypeSystem(); - this.genericType = typeSystem.getGenericTypeData(); + this.genericType = context.getType(Object.class); + this.voidType = context.getType(void.class); this.options = typeSystem.getOptions(); this.singleSpecializable = isSingleSpecializableImpl(); this.varArgsThreshold = calculateVarArgsThreshold(); @@ -139,8 +142,8 @@ return "exclude" + specialization.getId() + NAME_SUFFIX; } - private static String executeChildMethodName(NodeExecutionData execution, TypeData type) { - return "execute" + ElementUtils.firstLetterUpperCase(execution.getName()) + (type.isGeneric() ? "" : getTypeId(type.getBoxedType())) + NAME_SUFFIX; + private static String executeChildMethodName(NodeExecutionData execution, TypeMirror type) { + return "execute" + ElementUtils.firstLetterUpperCase(execution.getName()) + (ElementUtils.isObject(type) ? "" : getTypeId(type)) + NAME_SUFFIX; } private CodeTree accessParent(String name) { @@ -186,7 +189,9 @@ } for (NodeExecutionData execution : node.getChildExecutions()) { - clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class)); + if (execution.getChild() != null) { + clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class)); + } } for (NodeExecutionData execution : node.getChildExecutions()) { @@ -201,7 +206,7 @@ } } - Collection<TypeData> specializedTypes = node.findSpecializedReturnTypes(); + Collection<TypeMirror> specializedTypes = node.findSpecializedReturnTypes(); List<ExecutableTypeData> implementedExecutables = new ArrayList<>(); for (ExecutableTypeData execType : node.getExecutableTypes()) { if (shouldImplementExecutableType(specializedTypes, execType)) { @@ -235,6 +240,12 @@ } } + for (TypeMirror type : ElementUtils.uniqueSortedTypes(expectedTypes)) { + if (!typeSystem.hasType(type)) { + clazz.addOptional(TypeSystemCodeGenerator.createExpectMethod(PRIVATE, typeSystem, context.getType(Object.class), type)); + } + } + return clazz; } @@ -295,7 +306,7 @@ CodeTree nameTree = CodeTreeBuilder.singleString(name); CodeTreeBuilder callBuilder = builder.create(); callBuilder.string(name).string(" != null ? "); - callBuilder.tree(callTemplateMethod(null, createCast, nameTree)); + callBuilder.tree(callMethod(null, createCast.getMethod(), nameTree)); callBuilder.string(" : null"); name += "_"; builder.declaration(child.getNodeType(), name, callBuilder.build()); @@ -305,6 +316,9 @@ } for (NodeExecutionData execution : node.getChildExecutions()) { + if (execution.getChild() == null) { + continue; + } CreateCastData createCast = node.findCast(execution.getChild().getName()); builder.startStatement(); @@ -315,18 +329,18 @@ accessorBuilder.string(name); if (execution.isIndexed()) { - accessorBuilder.string("[").string(String.valueOf(execution.getIndex())).string("]"); + accessorBuilder.string("[").string(String.valueOf(execution.getChildIndex())).string("]"); } CodeTree accessor = accessorBuilder.build(); if (createCast != null && execution.getChild().getCardinality().isOne()) { - accessor = callTemplateMethod(null, createCast, accessor); + accessor = callMethod(null, createCast.getMethod(), accessor); } if (execution.isIndexed()) { CodeTreeBuilder nullCheck = builder.create(); - nullCheck.string(name).string(" != null && ").string(String.valueOf(execution.getIndex())).string(" < ").string(name).string(".length").string(" ? "); + nullCheck.string(name).string(" != null && ").string(String.valueOf(execution.getChildIndex())).string(" < ").string(name).string(".length").string(" ? "); nullCheck.tree(accessor); nullCheck.string(" : null"); accessor = nullCheck.build(); @@ -378,8 +392,8 @@ SpecializationData specialization = reachableSpecializations.get(0); for (Parameter parameter : specialization.getSignatureParameters()) { - TypeData type = parameter.getTypeSystemType(); - if (type != null && type.hasImplicitSourceTypes()) { + TypeMirror type = parameter.getType(); + if (type != null && typeSystem.hasImplicitSourceTypes(type)) { return true; } } @@ -410,9 +424,9 @@ } for (NodeExecutionData execution : node.getChildExecutions()) { - Collection<TypeData> specializedTypes = node.findSpecializedTypes(execution); + Collection<TypeMirror> specializedTypes = node.findSpecializedTypes(execution); specializedTypes.add(genericType); - for (TypeData specializedType : specializedTypes) { + for (TypeMirror specializedType : specializedTypes) { if (isExecuteChildShared(execution, specializedType)) { clazz.add(createExecuteChildMethod(execution, specializedType)); } @@ -428,10 +442,10 @@ CodeExecutableElement constructor = clazz.addOptional(createSpecializationConstructor(clazz, specialization, null)); for (Parameter p : specialization.getSignatureParameters()) { - TypeData targetType = p.getTypeSystemType(); - if (targetType.hasImplicitSourceTypes()) { + TypeMirror targetType = p.getType(); + if (typeSystem.hasImplicitSourceTypes(targetType)) { NodeExecutionData execution = p.getSpecification().getExecution(); - CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getTypeSystemType()); + CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getType()); if (implicitProfile != null) { implicitProfile.getModifiers().add(PRIVATE); implicitProfile.getModifiers().add(FINAL); @@ -449,21 +463,21 @@ clazz.addOptional(createIsSameMethod(specialization)); clazz.addOptional(createIsIdenticalMethod(specialization)); - TypeData returnType = specialization.getReturnType().getTypeSystemType(); + TypeMirror returnType = specialization.getReturnType().getType(); int signatureSize = specialization.getSignatureSize(); clazz.add(createFastPathExecuteMethod(specialization, null, signatureSize)); if (isTypeBoxingEliminated(specialization)) { - clazz.add(createFastPathExecuteMethod(specialization, returnType, 0)); - - if (signatureSize > 0 && !returnType.isGeneric()) { - clazz.add(createFastPathWrapExecuteMethod(genericType, returnType)); - } - - ExecutableTypeData voidExecutableType = node.findExecutableType(typeSystem.getVoidType(), 0); - if (voidExecutableType != null && isTypeBoxingOptimized(options.voidBoxingOptimization(), returnType)) { - clazz.add(createFastPathWrapVoidMethod(returnType)); + if (node.getMinimalEvaluatedParameters() == 0 || signatureSize == 0) { + clazz.add(createFastPathExecuteMethod(specialization, returnType, 0)); + if (signatureSize > 0 && !isObject(returnType)) { + clazz.add(createFastPathWrapExecuteMethod(genericType, returnType)); + } + ExecutableTypeData voidExecutableType = node.findExecutableType(voidType, 0); + if (voidExecutableType != null && isTypeBoxingOptimized(options.voidBoxingOptimization(), returnType)) { + clazz.add(createFastPathWrapVoidMethod(returnType)); + } } } @@ -517,7 +531,7 @@ } }; - builder.tree(createGuardAndCast(group, typeSystem.getGenericTypeData(), currentLocals, executionFactory)); + builder.tree(createGuardAndCast(group, genericType, currentLocals, executionFactory)); builder.returnFalse(); return method; } @@ -533,7 +547,7 @@ if (execution == null) { continue; } - CodeVariableElement var = createImplicitProfileParameter(execution, parameter.getTypeSystemType()); + CodeVariableElement var = createImplicitProfileParameter(execution, parameter.getType()); if (var != null) { profiles.add(var); } @@ -605,8 +619,9 @@ return executable; } - private Element createFastPathWrapVoidMethod(TypeData wrap) { - CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), typeSystem.getVoidType().getPrimitiveType(), TypeSystemNodeFactory.executeName(typeSystem.getVoidType())); + private Element createFastPathWrapVoidMethod(TypeMirror wrap) { + + CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), voidType, TypeSystemNodeFactory.executeName(voidType)); executable.addParameter(new CodeVariableElement(getType(Frame.class), FRAME_VALUE)); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = executable.createBuilder(); @@ -619,8 +634,8 @@ return executable; } - private Element createFastPathWrapExecuteMethod(TypeData override, TypeData wrap) { - CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), override.getPrimitiveType(), TypeSystemNodeFactory.executeName(override)); + private Element createFastPathWrapExecuteMethod(TypeMirror override, TypeMirror wrap) { + CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), override, TypeSystemNodeFactory.executeName(override)); executable.addParameter(new CodeVariableElement(getType(Frame.class), FRAME_VALUE)); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = executable.createBuilder(); @@ -758,11 +773,11 @@ } TypeBoxingOptimization optimization = options.monomorphicTypeBoxingOptimization(); - if (isTypeBoxingOptimized(optimization, specialization.getReturnType().getTypeSystemType())) { + if (isTypeBoxingOptimized(optimization, specialization.getReturnType().getType())) { return true; } for (Parameter p : specialization.getSignatureParameters()) { - if (isTypeBoxingOptimized(optimization, p.getTypeSystemType())) { + if (isTypeBoxingOptimized(optimization, p.getType())) { return true; } } @@ -772,7 +787,7 @@ private Set<Integer> getEvaluatedCounts() { Set<Integer> evaluatedCount = new TreeSet<>(); - Collection<TypeData> returnSpecializedTypes = node.findSpecializedReturnTypes(); + Collection<TypeMirror> returnSpecializedTypes = node.findSpecializedReturnTypes(); for (ExecutableTypeData execType : node.getExecutableTypes()) { if (shouldImplementExecutableType(returnSpecializedTypes, execType)) { evaluatedCount.add(execType.getEvaluatedCount()); @@ -788,7 +803,7 @@ } LocalContext locals = LocalContext.load(this); - CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType.getPrimitiveType(), "unsupported", FRAME_VALUE); + CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType, "unsupported", FRAME_VALUE); method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = method.createBuilder(); @@ -808,8 +823,8 @@ SpecializationData specialization = reachableSpecializations.get(0); for (Parameter parameter : specialization.getSignatureParameters()) { - TypeData type = parameter.getTypeSystemType(); - if (type != null && type.hasImplicitSourceTypes()) { + TypeMirror type = parameter.getType(); + if (type != null && typeSystem.hasImplicitSourceTypes(type)) { return false; } } @@ -853,22 +868,23 @@ private CodeExecutableElement createExecutableTypeOverride(List<ExecutableTypeData> implementedExecutables, ExecutableTypeData execType) { final String varArgsName = "args"; - final TypeData returnType = execType.getType(); - final TypeData executedType = execType.getEvaluatedCount() > 0 ? null : returnType; - - CodeExecutableElement method = cloneExecutableTypeOverride(execType, varArgsName); - LocalContext locals = LocalContext.load(this, execType.getSignatureSize(), Integer.MAX_VALUE); + final TypeMirror returnType = execType.getReturnType(); + final TypeMirror executedType = execType.getEvaluatedCount() > 0 ? null : returnType; + + LocalContext locals = LocalContext.load(this, execType.getEvaluatedCount(), Integer.MAX_VALUE); + CodeExecutableElement method = cloneExecutableTypeOverride(locals, execType, varArgsName); // rename varargs parameter int signatureIndex = 0; - for (Parameter parameter : execType.getSignatureParameters()) { - LocalVariable var = locals.get(parameter, signatureIndex); + for (TypeMirror parameter : execType.getEvaluatedParameters()) { + LocalVariable var = locals.getValue(signatureIndex); if (var != null) { - if (parameter.isTypeVarArgs()) { - var = var.accessWith(CodeTreeBuilder.singleString(varArgsName + "[" + parameter.getTypeVarArgsIndex() + "]")); + int varArgsIndex = execType.getVarArgsIndex(execType.getParameterIndex(signatureIndex)); + if (varArgsIndex >= 0) { + var = var.accessWith(CodeTreeBuilder.singleString(varArgsName + "[" + varArgsIndex + "]")); } - if (!parameter.getTypeSystemType().isGeneric()) { - var = var.newType(parameter.getTypeSystemType()); + if (!isObject(parameter)) { + var = var.newType(parameter); } locals.setValue(node.getChildExecutions().get(signatureIndex), var); } @@ -876,12 +892,12 @@ signatureIndex++; } - Parameter frame = execType.getFrame(); + TypeMirror frame = execType.getFrameParameter(); CodeTreeBuilder builder = method.createBuilder(); if (singleSpecializable) { LocalVariable frameVar = null; if (frame != null) { - frameVar = locals.get(FRAME_VALUE).newType(frame.getType()); + frameVar = locals.get(FRAME_VALUE).newType(frame); } method.getThrownTypes().clear(); locals.set(FRAME_VALUE, frameVar); @@ -889,9 +905,9 @@ SpecializationData specialization = getReachableSpecializations().iterator().next(); ExecutableTypeData wrappedExecutableType = findWrappedExecutable(specialization, implementedExecutables, execType); if (wrappedExecutableType != null) { - builder.startReturn().tree(callTemplateMethod(null, wrappedExecutableType, locals)).end(); + builder.startReturn().tree(callExecuteMethod(null, wrappedExecutableType, locals)).end(); } else { - builder.tree(createFastPath(builder, specialization, execType.getType(), locals)); + builder.tree(createFastPath(builder, specialization, execType.getReturnType(), locals)); } } else { // create acceptAndExecute @@ -900,23 +916,23 @@ if (frame == null) { executeBuilder.nullLiteral(); } else { - executeBuilder.string(frame.getLocalName()); + executeBuilder.string(locals.get(FRAME_VALUE).getName()); } locals.addReferencesTo(executeBuilder); executeBuilder.end(); - boolean hasExecutedUnexpected = executedType != null && !executedType.isGeneric() && !executedType.isVoid(); + boolean hasExecutedUnexpected = executedType != null && !isObject(executedType) && !isVoid(executedType); CodeTreeBuilder contentBuilder = builder.create(); contentBuilder.startReturn(); if (!hasExecutedUnexpected && !execType.hasUnexpectedValue(context)) { - if (executedType == null || executedType.needsCastTo(returnType)) { - contentBuilder.cast(returnType.getPrimitiveType(), executeBuilder.build()); + if (executedType == null || needsCastTo(executedType, returnType)) { + contentBuilder.cast(returnType, executeBuilder.build()); } else { contentBuilder.tree(executeBuilder.build()); } } else { - contentBuilder.tree(TypeSystemCodeGenerator.expect(executedType, returnType, executeBuilder.build())); + contentBuilder.tree(expect(executedType, returnType, executeBuilder.build())); } contentBuilder.end(); // try catch assert if unexpected value is not expected @@ -940,12 +956,12 @@ } private static ExecutableTypeData findWrappedExecutable(SpecializationData specialization, List<ExecutableTypeData> implementedExecutables, ExecutableTypeData executedType) { - if (specialization.getReturnType().getTypeSystemType() == executedType.getType()) { + if (specialization.getReturnType().getType() == executedType.getReturnType()) { return null; } for (ExecutableTypeData otherType : implementedExecutables) { if (otherType != executedType && // - otherType.getType() == specialization.getReturnType().getTypeSystemType() && // + otherType.getReturnType() == specialization.getReturnType().getType() && // otherType.getEvaluatedCount() == executedType.getEvaluatedCount()) { return otherType; } @@ -953,43 +969,50 @@ return null; } - private CodeExecutableElement cloneExecutableTypeOverride(ExecutableTypeData execType, final String varArgsName) throws AssertionError { + private CodeExecutableElement cloneExecutableTypeOverride(LocalContext locals, ExecutableTypeData execType, final String varArgsName) throws AssertionError { CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), execType.getMethod()); method.getAnnotationMirrors().clear(); method.getModifiers().remove(Modifier.ABSTRACT); - if (!execType.getMethod().isVarArgs() && execType.getParameters().size() != method.getParameters().size()) { - throw new AssertionError("Should be verified in the parser"); + // align argument names + int parameterIndex = 0; + if (execType.getFrameParameter() != null) { + CodeVariableElement frameParameter = (CodeVariableElement) method.getParameters().get(0); + frameParameter.setName(FRAME_VALUE); + frameParameter.getAnnotationMirrors().clear(); + parameterIndex++; } - // align argument names - int index = 0; - for (Parameter parameter : execType.getParameters()) { - CodeVariableElement var = (CodeVariableElement) method.getParameters().get(index); - if (parameter.isTypeVarArgs()) { + for (int signatureIndex = 0; signatureIndex < execType.getEvaluatedCount(); signatureIndex++) { + CodeVariableElement var = (CodeVariableElement) method.getParameters().get(parameterIndex); + if (signatureIndex < node.getSignatureSize()) { + if (execType.getVarArgsIndex(parameterIndex) >= 0) { + var.getAnnotationMirrors().clear(); + var.setName(varArgsName); + break; + } + var.setName(locals.getValue(signatureIndex).getName()); var.getAnnotationMirrors().clear(); - var.setName(varArgsName); - break; + } else { + var.setName("other" + signatureIndex); } - var.setName(LocalVariable.fromParameter(parameter).createParameter().getName()); - var.getAnnotationMirrors().clear(); - index++; + parameterIndex++; } return method; } - private boolean shouldImplementExecutableType(Collection<TypeData> specializedTypes, ExecutableTypeData execType) { - TypeData type = execType.getType(); + private boolean shouldImplementExecutableType(Collection<TypeMirror> specializedTypes, ExecutableTypeData execType) { + TypeMirror type = execType.getReturnType(); Set<Modifier> modifiers = execType.getMethod().getModifiers(); if (modifiers.contains(FINAL) || modifiers.contains(STATIC) || modifiers.contains(PRIVATE)) { return false; } else if (execType.isAbstract()) { return true; - } else if (type.isGeneric()) { + } else if (ElementUtils.isObject(type)) { return true; - } else if (type.isVoid()) { - for (TypeData specializedType : specializedTypes) { + } else if (ElementUtils.isVoid(type)) { + for (TypeMirror specializedType : specializedTypes) { if (isTypeBoxingOptimized(options.voidBoxingOptimization(), specializedType)) { return true; } @@ -1021,7 +1044,7 @@ return childField; } - private static List<ExecutableTypeData> resolveSpecializedExecutables(NodeExecutionData execution, Collection<TypeData> types, TypeBoxingOptimization optimization) { + private static List<ExecutableTypeData> resolveSpecializedExecutables(NodeExecutionData execution, Collection<TypeMirror> types, TypeBoxingOptimization optimization) { if (optimization == TypeBoxingOptimization.NONE) { return Collections.emptyList(); } else if (types.isEmpty()) { @@ -1029,10 +1052,13 @@ } List<ExecutableTypeData> executables = new ArrayList<>(); - for (TypeData type : types) { + for (TypeMirror type : types) { if (!isTypeBoxingOptimized(optimization, type)) { continue; } + if (execution.getChild() == null) { + continue; + } ExecutableTypeData foundType = execution.getChild().getNodeData().findExecutableType(type, execution.getChild().getExecuteWith().size()); if (foundType != null) { executables.add(foundType); @@ -1041,15 +1067,15 @@ return executables; } - private static CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, CodeTree... boundValues) { + private static CodeTree callMethod(CodeTree receiver, ExecutableElement method, CodeTree... boundValues) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - if (method.getMethod().getModifiers().contains(STATIC)) { - builder.startStaticCall(method.getMethod().getEnclosingElement().asType(), method.getMethodName()); + if (method.getModifiers().contains(STATIC)) { + builder.startStaticCall(method.getEnclosingElement().asType(), method.getSimpleName().toString()); } else { - builder.startCall(receiver, method.getMethodName()); + builder.startCall(receiver, method.getSimpleName().toString()); } int index = -1; - for (Parameter parameter : method.getParameters()) { + for (VariableElement parameter : method.getParameters()) { index++; if (index < boundValues.length) { CodeTree tree = boundValues[index]; @@ -1059,13 +1085,39 @@ } } - builder.defaultValue(parameter.getType()); + builder.defaultValue(parameter.asType()); } builder.end(); return builder.build(); } - private static CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, LocalContext currentValues) { + private CodeTree callExecuteMethod(NodeExecutionData execution, ExecutableTypeData method, LocalContext currentValues) { + CodeTree receiver = execution != null ? accessParent(nodeFieldName(execution)) : null; + List<NodeExecutionData> executeWith = execution != null ? execution.getChild().getExecuteWith() : null; + + List<CodeTree> values = new ArrayList<>(); + if (method.getFrameParameter() != null) { + LocalVariable frameLocal = currentValues.get(FRAME_VALUE); + if (frameLocal == null) { + values.add(CodeTreeBuilder.singleString("null")); + } else { + values.add(createTypeSafeReference(frameLocal, method.getFrameParameter())); + } + } + for (int parameterIndex = 0; parameterIndex < method.getEvaluatedCount(); parameterIndex++) { + TypeMirror targetParameter = method.getEvaluatedParameters().get(parameterIndex); + LocalVariable variable; + if (executeWith != null && parameterIndex < executeWith.size()) { + variable = currentValues.getValue(executeWith.get(parameterIndex)); + } else { + variable = currentValues.getValue(parameterIndex); + } + values.add(createTypeSafeReference(variable, targetParameter)); + } + return callMethod(receiver, method.getMethod(), values.toArray(new CodeTree[values.size()])); + } + + private CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, LocalContext currentValues) { CodeTree[] bindings = new CodeTree[method.getParameters().size()]; int signatureIndex = 0; @@ -1078,20 +1130,28 @@ } if (var != null) { - CodeTree valueReference = var.createReference(); - if (parameter.getTypeSystemType() != null && var.getType() != null && var.getType().needsCastTo(parameter.getTypeSystemType())) { - valueReference = TypeSystemCodeGenerator.cast(parameter.getTypeSystemType(), valueReference); - } else if (ElementUtils.needsCastTo(var.getTypeMirror(), parameter.getType())) { - valueReference = CodeTreeBuilder.createBuilder().cast(parameter.getType(), valueReference).build(); - } - bindings[i] = valueReference; + bindings[i] = createTypeSafeReference(var, parameter.getType()); } if (parameter.getSpecification().isSignature()) { signatureIndex++; } } - return callTemplateMethod(receiver, method, bindings); + return callMethod(receiver, method.getMethod(), bindings); + } + + private CodeTree createTypeSafeReference(LocalVariable var, TypeMirror targetType) { + CodeTree valueReference = var.createReference(); + TypeMirror sourceType = var.getTypeMirror(); + if (targetType == null || sourceType == null) { + return valueReference; + } + if (needsCastTo(sourceType, targetType)) { + valueReference = TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference); + } else if (ElementUtils.needsCastTo(sourceType, targetType)) { + valueReference = CodeTreeBuilder.createBuilder().cast(targetType, valueReference).build(); + } + return valueReference; } private SpecializationGroup createSpecializationGroups() { @@ -1125,7 +1185,7 @@ String varName = name + specialization.getIndex(); TypeMirror type = assumption.getExpression().getResolvedType(); builder.declaration(type, varName, assumptions); - currentValues.set(name, new LocalVariable(null, type, varName, null, null)); + currentValues.set(name, new LocalVariable(type, varName, null, null)); } builder.startIf(); @@ -1189,14 +1249,14 @@ return builder.build(); } - private boolean hasFallthrough(SpecializationGroup group, TypeData forType, LocalContext currentValues, boolean fastPath, List<GuardExpression> ignoreGuards) { + private boolean hasFallthrough(SpecializationGroup group, TypeMirror forType, LocalContext currentValues, boolean fastPath, List<GuardExpression> ignoreGuards) { for (TypeGuard guard : group.getTypeGuards()) { if (currentValues.getValue(guard.getSignatureIndex()) == null) { // not evaluated return true; } LocalVariable value = currentValues.getValue(guard.getSignatureIndex()); - if (value.getType().needsCastTo(guard.getType())) { + if (needsCastTo(value.getTypeMirror(), guard.getType())) { return true; } } @@ -1265,7 +1325,11 @@ if (execution.isShortCircuit()) { builder.nullLiteral(); } - builder.tree(accessParent(nodeFieldName(execution))); + if (execution.getChild() == null) { + builder.nullLiteral(); + } else { + builder.tree(accessParent(nodeFieldName(execution))); + } } builder.end(); return builder.build(); @@ -1289,7 +1353,7 @@ } if (currentValues != null) { for (Parameter p : specialization.getSignatureParameters()) { - CodeVariableElement var = createImplicitProfileParameter(p.getSpecification().getExecution(), p.getTypeSystemType()); + CodeVariableElement var = createImplicitProfileParameter(p.getSpecification().getExecution(), p.getType()); if (var != null) { LocalVariable variable = currentValues.get(p.getLocalName()); if (variable == null) { @@ -1370,19 +1434,19 @@ for (Parameter p : specialization.getSignatureParameters()) { NodeExecutionData execution = p.getSpecification().getExecution(); - CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getTypeSystemType()); + CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getType()); if (implicitProfile != null) { - LocalVariable var = LocalVariable.fromParameter(p).makeGeneric(); + LocalVariable var = LocalVariable.fromParameter(p).makeGeneric(context); String implicitFieldName = implicitProfile.getName(); if (options.implicitCastOptimization().isDuplicateTail()) { constructor.addParameter(var.createParameter()); - CodeTree implicitType = TypeSystemCodeGenerator.implicitType(p.getTypeSystemType(), var.createReference()); + CodeTree implicitType = TypeSystemCodeGenerator.implicitType(typeSystem, p.getType(), var.createReference()); builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(implicitType).end(); } else if (options.implicitCastOptimization().isMergeCasts()) { // use node that supports polymorphism constructor.addParameter(var.createParameter()); - builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(ImplicitCastNodeFactory.create(p.getTypeSystemType(), var.createReference())).end(); + builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(ImplicitCastNodeFactory.create(typeSystem, p.getType(), var.createReference())).end(); } else { throw new AssertionError(); } @@ -1443,7 +1507,7 @@ return builder.build(); } - private CodeTree createCallNext(TypeData forType, LocalContext currentValues) { + private CodeTree createCallNext(TypeMirror forType, LocalContext currentValues) { if (singleSpecializable) { return createThrowUnsupported(currentValues); } @@ -1451,10 +1515,10 @@ callBuilder.startCall("next", TypeSystemNodeFactory.executeName(null)); currentValues.addReferencesTo(callBuilder, FRAME_VALUE); callBuilder.end(); - return CodeTreeBuilder.createBuilder().startReturn().tree(TypeSystemCodeGenerator.expect(genericType, forType, callBuilder.build())).end().build(); + return CodeTreeBuilder.createBuilder().startReturn().tree(expect(genericType, forType, callBuilder.build())).end().build(); } - private CodeTree createCallRemove(String reason, TypeData forType, LocalContext currentValues) { + private CodeTree createCallRemove(String reason, TypeMirror forType, LocalContext currentValues) { if (singleSpecializable) { return createThrowUnsupported(currentValues); } @@ -1467,12 +1531,12 @@ builder = builder.create(); builder.startReturn(); - builder.tree(TypeSystemCodeGenerator.expect(genericType, forType, call)); + builder.tree(expect(genericType, forType, call)); builder.end(); return builder.build(); } - private static CodeTree createCallDelegate(String methodName, String reason, TypeData forType, LocalContext currentValues) { + private CodeTree createCallDelegate(String methodName, String reason, TypeMirror forType, LocalContext currentValues) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); builder.startCall(methodName); if (reason != null) { @@ -1481,21 +1545,28 @@ currentValues.addReferencesTo(builder, FRAME_VALUE); builder.end(); - TypeData executedType = forType.getTypeSystem().getGenericTypeData(); - return TypeSystemCodeGenerator.expect(executedType, forType, builder.build()); + return expect(genericType, forType, builder.build()); } - private Set<ExecutableTypeData> findSpecializedExecutableTypes(NodeExecutionData execution, TypeData type) { + private CodeTree expect(TypeMirror sourceType, TypeMirror forType, CodeTree tree) { + expectedTypes.add(forType); + return TypeSystemCodeGenerator.expect(typeSystem, sourceType, forType, tree); + } + + private Set<ExecutableTypeData> findSpecializedExecutableTypes(NodeExecutionData execution, TypeMirror type) { + if (execution.getChild() == null) { + return Collections.emptySet(); + } ExecutableTypeData executableType = resolveExecutableType(execution.getChild(), type); Set<ExecutableTypeData> executedTypes = new HashSet<>(); executedTypes.add(executableType); - if (type.hasImplicitSourceTypes()) { - executedTypes.addAll(resolveSpecializedExecutables(execution, type.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization())); + if (typeSystem.hasImplicitSourceTypes(type)) { + executedTypes.addAll(resolveSpecializedExecutables(execution, typeSystem.lookupSourceTypes(type), options.implicitTypeBoxingOptimization())); } return executedTypes; } - private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeData type) { + private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeMirror type) { int executeWithCount = child.getExecuteWith().size(); ExecutableTypeData executableType = child.getNodeData().findExecutableType(type, executeWithCount); if (executableType == null) { @@ -1504,27 +1575,27 @@ return executableType; } - private boolean hasUnexpectedResult(NodeExecutionData execution, TypeData type) { + private boolean hasUnexpectedResult(NodeExecutionData execution, TypeMirror type) { for (ExecutableTypeData executableType : findSpecializedExecutableTypes(execution, type)) { - if (executableType != null && (executableType.hasUnexpectedValue(context) || executableType.getType().needsCastTo(type))) { + if (executableType != null && (executableType.hasUnexpectedValue(context) || needsCastTo(executableType.getReturnType(), type))) { return true; } } return false; } - private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeData forType, int evaluatedArguments) { - TypeData type = forType == null ? genericType : forType; + private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeMirror forType, int evaluatedArguments) { + TypeMirror type = forType == null ? genericType : forType; LocalContext currentLocals = LocalContext.load(this, evaluatedArguments, varArgsThreshold); if (specialization != null) { currentLocals.loadFastPathState(specialization); } - CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemNodeFactory.executeName(forType), FRAME_VALUE); + CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type, TypeSystemNodeFactory.executeName(forType), FRAME_VALUE); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); - if (!type.isGeneric()) { + if (!isObject(type)) { executable.getThrownTypes().add(getType(UnexpectedResultException.class)); } @@ -1534,17 +1605,17 @@ return executable; } - private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, TypeData type, LocalContext currentLocals) { + private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, TypeMirror type, LocalContext currentLocals) { final CodeTreeBuilder builder = parent.create(); for (NodeExecutionData execution : node.getChildExecutions()) { LocalVariable var = currentLocals.getValue(execution); if (var == null) { - TypeData targetType; + TypeMirror targetType; if (specialization == null) { targetType = genericType; } else { - targetType = specialization.findParameterOrDie(execution).getTypeSystemType(); + targetType = specialization.findParameterOrDie(execution).getType(); } LocalVariable shortCircuit = resolveShortCircuit(specialization, execution, currentLocals); LocalVariable value = currentLocals.createValue(execution, targetType).nextName(); @@ -1561,7 +1632,7 @@ } else if (specialization.isUninitialized()) { builder.startReturn().tree(createCallDelegate("uninitialized", null, type, currentLocals)).end(); } else { - final TypeData finalType = type; + final TypeMirror finalType = type; SpecializationGroup group = SpecializationGroup.create(specialization); SpecializationBody executionFactory = new SpecializationBody(true, true) { @Override @@ -1605,7 +1676,7 @@ return shortCircuitIndex; } - private CodeTree createFastPathExecute(CodeTreeBuilder parent, final TypeData forType, SpecializationData specialization, LocalContext currentValues) { + private CodeTree createFastPathExecute(CodeTreeBuilder parent, final TypeMirror forType, SpecializationData specialization, LocalContext currentValues) { CodeTreeBuilder builder = parent.create(); int ifCount = 0; if (specialization.isFallback()) { @@ -1642,21 +1713,37 @@ builder.end(); } - execute.startReturn(); if (specialization.getMethod() == null) { + execute.startReturn(); execute.startCall("unsupported"); currentValues.addReferencesTo(execute, FRAME_VALUE); execute.end(); + execute.end(); } else { + boolean doReturn = !isVoid(specialization.getMethod().getReturnType()); + if (doReturn) { + execute.startReturn(); + } else { + execute.startStatement(); + } execute.tree(callTemplateMethod(accessParent(null), specialization, currentValues)); + execute.end(); + if (!doReturn) { + if (isVoid(forType)) { + execute.returnStatement(); + } else { + execute.startReturn(); + execute.defaultValue(forType); + execute.end(); + } + } } - execute.end(); builder.tree(createFastPathTryCatchRewriteException(specialization, forType, currentValues, execute.build())); builder.end(ifCount); return builder.build(); } - private CodeTree createGuardAndCast(SpecializationGroup group, TypeData forType, LocalContext currentValues, SpecializationBody execution) { + private CodeTree createGuardAndCast(SpecializationGroup group, TypeMirror forType, LocalContext currentValues, SpecializationBody execution) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); Set<TypeGuard> castGuards; @@ -1780,10 +1867,10 @@ return false; } - private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeData targetType) { + private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeMirror targetType) { LocalContext locals = LocalContext.load(this, 0, varArgsThreshold); - CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType.getPrimitiveType(), executeChildMethodName(execution, targetType), FRAME_VALUE); + CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType, executeChildMethodName(execution, targetType), FRAME_VALUE); if (hasUnexpectedResult(execution, targetType)) { method.getThrownTypes().add(getType(UnexpectedResultException.class)); } @@ -1810,30 +1897,30 @@ return method; } - private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeData targetType) { - if (targetType.hasImplicitSourceTypes()) { + private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeMirror targetType) { + if (typeSystem.hasImplicitSourceTypes(targetType)) { switch (options.implicitCastOptimization()) { case NONE: return null; case DUPLICATE_TAIL: return new CodeVariableElement(getType(Class.class), implicitClassFieldName(execution)); case MERGE_CASTS: - return new CodeVariableElement(ImplicitCastNodeFactory.type(targetType), implicitNodeFieldName(execution)); + return new CodeVariableElement(ImplicitCastNodeFactory.type(typeSystem, targetType), implicitNodeFieldName(execution)); } } return null; } - private boolean isExecuteChildShared(NodeExecutionData execution, TypeData targetType) { - if (targetType.isVoid()) { + private boolean isExecuteChildShared(NodeExecutionData execution, TypeMirror targetType) { + if (isVoid(targetType)) { return false; - } else if (targetType.isGeneric()) { + } else if (isObject(targetType)) { return resolvePolymorphicExecutables(execution).size() >= 1; } else { if (!isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), targetType)) { return false; } - if (!targetType.hasImplicitSourceTypes()) { + if (!typeSystem.hasImplicitSourceTypes(targetType)) { return false; } @@ -1841,25 +1928,25 @@ for (SpecializationData specialization : node.getSpecializations()) { List<Parameter> parameters = specialization.findByExecutionData(execution); for (Parameter parameter : parameters) { - if (targetType.equals(parameter.getTypeSystemType())) { + if (targetType.equals(parameter.getType())) { uses++; } } } if (uses > 1) { - return resolveSpecializedExecutables(execution, targetType.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization()).size() > 1; + return resolveSpecializedExecutables(execution, typeSystem.lookupSourceTypes(targetType), options.implicitTypeBoxingOptimization()).size() > 1; } else { return false; } } } - private CodeTree createAssignExecuteChild(NodeExecutionData execution, TypeData returnType, LocalVariable targetValue, LocalVariable shortCircuit, LocalContext currentValues) { + private CodeTree createAssignExecuteChild(NodeExecutionData execution, TypeMirror returnType, LocalVariable targetValue, LocalVariable shortCircuit, LocalContext currentValues) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - boolean hasUnexpected = hasUnexpectedResult(execution, targetValue.getType()); + boolean hasUnexpected = hasUnexpectedResult(execution, targetValue.getTypeMirror()); CodeTree executeChild; - if (isExecuteChildShared(execution, targetValue.getType())) { + if (isExecuteChildShared(execution, targetValue.getTypeMirror())) { executeChild = createCallSharedExecuteChild(execution, targetValue, currentValues); } else { executeChild = createExecuteChild(execution, targetValue, currentValues, false); @@ -1876,7 +1963,7 @@ builder.startCatchBlock(getType(UnexpectedResultException.class), "ex"); LocalContext slowPathValues = currentValues.copy(); - slowPathValues.setValue(execution, targetValue.makeGeneric().accessWith(CodeTreeBuilder.singleString("ex.getResult()"))); + slowPathValues.setValue(execution, targetValue.makeGeneric(context).accessWith(CodeTreeBuilder.singleString("ex.getResult()"))); boolean found = false; for (NodeExecutionData otherExecution : node.getChildExecutions()) { if (found) { @@ -1945,16 +2032,16 @@ } private CodeTree createCallSharedExecuteChild(NodeExecutionData execution, LocalVariable targetValue, LocalContext currentValues) { - if (!isExecuteChildShared(execution, targetValue.getType())) { + if (!isExecuteChildShared(execution, targetValue.getTypeMirror())) { throw new AssertionError("Execute child not shared with method but called."); } CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); builder.tree(targetValue.createReference()).string(" = "); - builder.startCall(executeChildMethodName(execution, targetValue.getType())); + builder.startCall(executeChildMethodName(execution, targetValue.getTypeMirror())); builder.string(FRAME_VALUE); - CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetValue.getType()); + CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetValue.getTypeMirror()); if (implicitProfile != null) { builder.string(implicitProfile.getName()); } @@ -1970,12 +2057,12 @@ CodeTree assignment = createAssignmentStart(target, shared); - final Set<ExecutableTypeData> executableTypes = findSpecializedExecutableTypes(execution, target.getType()); + final Set<ExecutableTypeData> executableTypes = findSpecializedExecutableTypes(execution, target.getTypeMirror()); if (executableTypes.isEmpty()) { throw new AssertionError(); // cannot execute child - } else if (executableTypes.size() == 1 && !target.getType().hasImplicitSourceTypes()) { + } else if (executableTypes.size() == 1 && !typeSystem.hasImplicitSourceTypes(target.getTypeMirror())) { ExecutableTypeData executableType = executableTypes.iterator().next(); - if (target.getType().isGeneric() && executableType.getEvaluatedCount() == 0) { + if (isObject(target.getTypeMirror()) && executableType.getEvaluatedCount() == 0) { return createPolymorphicExecuteChild(execution, target, currentValues, shared); } else { builder.tree(assignment); @@ -1997,9 +2084,8 @@ } private CodeTree createSingleExecute(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, ExecutableTypeData executableType) { - CodeTree accessChild = accessParent(nodeFieldName(execution)); - CodeTree execute = callTemplateMethod(accessChild, executableType, currentValues); - return TypeSystemCodeGenerator.expect(executableType.getType(), target.getType(), execute); + CodeTree execute = callExecuteMethod(execution, executableType, currentValues); + return expect(executableType.getReturnType(), target.getTypeMirror(), execute); } private CodeTree createPolymorphicExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) throws AssertionError { @@ -2011,7 +2097,7 @@ List<ExecutableTypeData> specializedExecutables = resolvePolymorphicExecutables(execution); Collections.sort(specializedExecutables, new Comparator<ExecutableTypeData>() { public int compare(ExecutableTypeData o1, ExecutableTypeData o2) { - return o1.getType().compareTo(o2.getType()); + return compareType(o1.getReturnType(), o2.getReturnType()); } }); @@ -2034,7 +2120,7 @@ for (ExecutableTypeData executableType : specializedExecutables) { hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes); polyChainBuilder.string(profileField); - polyChainBuilder.string(" == ").typeLiteral(executableType.getType().getPrimitiveType()); + polyChainBuilder.string(" == ").typeLiteral(executableType.getReturnType()); polyChainBuilder.end(); polyChainBuilder.startBlock(); polyChainBuilder.startStatement(); @@ -2048,20 +2134,20 @@ polyChainBuilder.startElseIf().string(profileField).string(" == null").end(); polyChainBuilder.startBlock(); polyChainBuilder.tree(createTransferToInterpreterAndInvalidate()); - polyChainBuilder.declaration(genericExecutableType.getType().getPrimitiveType(), valueFieldName, executeGeneric); + polyChainBuilder.declaration(genericExecutableType.getReturnType(), valueFieldName, executeGeneric); hasSpecializedTypes = false; for (ExecutableTypeData executableType : specializedExecutables) { hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes); - polyChainBuilder.tree(TypeSystemCodeGenerator.check(executableType.getType(), CodeTreeBuilder.singleString(valueFieldName))); + polyChainBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, executableType.getReturnType(), CodeTreeBuilder.singleString(valueFieldName))); polyChainBuilder.end(); polyChainBuilder.startBlock(); - polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(executableType.getType().getPrimitiveType()).end(); + polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(executableType.getReturnType()).end(); polyChainBuilder.end(); } polyChainBuilder.startElseBlock(); - polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType.getPrimitiveType()).end(); + polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType).end(); polyChainBuilder.end(); polyChainBuilder.startReturn().string(valueFieldName).end(); polyChainBuilder.end(); @@ -2077,7 +2163,7 @@ builder.tree(executePolymorphic); builder.end(); builder.startCatchBlock(getType(UnexpectedResultException.class), "ex"); - builder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType.getPrimitiveType()).end(); + builder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType).end(); builder.startReturn().string("ex.getResult()").end(); builder.end(); } else { @@ -2091,9 +2177,9 @@ if (singleSpecializable) { return Collections.emptyList(); } - Set<TypeData> specializedTypes = new HashSet<>(); - for (TypeData type : node.findSpecializedTypes(execution)) { - specializedTypes.addAll(type.getImplicitSourceTypes()); + Set<TypeMirror> specializedTypes = new HashSet<>(); + for (TypeMirror type : node.findSpecializedTypes(execution)) { + specializedTypes.addAll(typeSystem.lookupSourceTypes(type)); } return resolveSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination()); } @@ -2110,23 +2196,22 @@ private CodeTree createExecuteChildDuplicateTail(CodeTreeBuilder parent, NodeExecutionData execution, CodeTree assignment, LocalVariable target, LocalContext currentValues) { CodeTreeBuilder builder = parent.create(); - List<TypeData> sourceTypes = target.getType().getImplicitSourceTypes(); + List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(target.getTypeMirror()); String implicitClassFieldName = implicitClassFieldName(execution); - String nodeFieldName = nodeFieldName(execution); List<ExecutableTypeData> executableTypes = resolveSpecializedExecutables(execution, sourceTypes, options.implicitTypeBoxingOptimization()); boolean elseIf = false; for (ExecutableTypeData executableType : executableTypes) { elseIf = builder.startIf(elseIf); - builder.string(implicitClassFieldName).string(" == ").typeLiteral(executableType.getType().getPrimitiveType()); + builder.string(implicitClassFieldName).string(" == ").typeLiteral(executableType.getReturnType()); builder.end(); builder.startBlock(); builder.startStatement().tree(assignment); - CodeTree execute = callTemplateMethod(accessParent(nodeFieldName), executableType, currentValues); - ImplicitCastData cast = typeSystem.lookupCast(executableType.getType(), target.getType()); + CodeTree execute = callExecuteMethod(execution, executableType, currentValues); + ImplicitCastData cast = typeSystem.lookupCast(executableType.getReturnType(), target.getTypeMirror()); if (cast != null) { - execute = callTemplateMethod(null, cast, execute); + execute = callMethod(null, cast.getMethod(), execute); } builder.tree(execute); builder.end(); @@ -2137,13 +2222,13 @@ builder.startElseBlock(); } - LocalVariable genericValue = target.makeGeneric().nextName(); - builder.tree(createAssignExecuteChild(execution, genericValue.getType(), genericValue, null, currentValues)); + LocalVariable genericValue = target.makeGeneric(context).nextName(); + builder.tree(createAssignExecuteChild(execution, genericValue.getTypeMirror(), genericValue, null, currentValues)); if (executableTypes.size() == sourceTypes.size()) { builder.startThrow().startNew(getType(UnexpectedResultException.class)).tree(genericValue.createReference()).end().end(); } else { builder.startStatement().tree(assignment); - builder.tree(TypeSystemCodeGenerator.implicitExpect(target.getType(), genericValue.createReference(), implicitClassFieldName)); + builder.tree(TypeSystemCodeGenerator.implicitExpect(typeSystem, target.getTypeMirror(), genericValue.createReference(), implicitClassFieldName)); builder.end(); } @@ -2153,7 +2238,7 @@ return builder.build(); } - private CodeTree createFastPathTryCatchRewriteException(SpecializationData specialization, TypeData forType, LocalContext currentValues, CodeTree execution) { + private CodeTree createFastPathTryCatchRewriteException(SpecializationData specialization, TypeMirror forType, LocalContext currentValues, CodeTree execution) { if (specialization.getExceptions().isEmpty()) { return execution; } @@ -2248,8 +2333,8 @@ for (TypeGuard typeGuard : typeGuards) { int signatureIndex = typeGuard.getSignatureIndex(); LocalVariable value = currentValues.getValue(signatureIndex); - TypeData targetType = typeGuard.getType(); - if (!value.getType().needsCastTo(targetType)) { + TypeMirror targetType = typeGuard.getType(); + if (!ElementUtils.needsCastTo(value.getTypeMirror(), targetType)) { continue; } NodeExecutionData execution = node.getChildExecutions().get(signatureIndex); @@ -2264,7 +2349,7 @@ if (shortCircuit != null) { checkBuilder.string("("); CodeTreeBuilder referenceBuilder = checkBuilder.create(); - if (!shortCircuit.getType().isPrimitive()) { + if (!ElementUtils.isPrimitive(shortCircuit.getTypeMirror())) { referenceBuilder.string("(boolean) "); } referenceBuilder.tree(shortCircuit.createReference()); @@ -2276,15 +2361,15 @@ List<ImplicitCastData> sourceTypes = typeSystem.lookupByTargetType(targetType); CodeTree valueReference = value.createReference(); if (sourceTypes.isEmpty()) { - checkBuilder.tree(TypeSystemCodeGenerator.check(targetType, value.createReference())); - castBuilder.tree(TypeSystemCodeGenerator.cast(targetType, valueReference)); + checkBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, targetType, value.createReference())); + castBuilder.tree(TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference)); } else { ImplicitCastOptimization opt = options.implicitCastOptimization(); if (specializationExecution.isFastPath() && !opt.isNone()) { if (opt.isDuplicateTail()) { String typeHintField = implicitClassFieldName(execution); - checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(targetType, valueReference, typeHintField)); - castBuilder.tree(TypeSystemCodeGenerator.implicitCast(targetType, valueReference, typeHintField)); + checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(typeSystem, targetType, valueReference, typeHintField)); + castBuilder.tree(TypeSystemCodeGenerator.implicitCast(typeSystem, targetType, valueReference, typeHintField)); } else if (opt.isMergeCasts()) { checkBuilder.tree(ImplicitCastNodeFactory.check(implicitNodeFieldName(execution), valueReference)); castBuilder.tree(ImplicitCastNodeFactory.cast(implicitNodeFieldName(execution), valueReference)); @@ -2292,14 +2377,14 @@ throw new AssertionError("implicit cast opt"); } } else { - checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(targetType, valueReference, null)); - castBuilder.tree(TypeSystemCodeGenerator.implicitCast(targetType, valueReference, null)); + checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(typeSystem, targetType, valueReference, null)); + castBuilder.tree(TypeSystemCodeGenerator.implicitCast(typeSystem, targetType, valueReference, null)); } } if (shortCircuit != null) { checkBuilder.string(")"); - castBuilder.string(" : ").defaultValue(targetType.getPrimitiveType()); + castBuilder.string(" : ").defaultValue(targetType); } if (castGuards == null || castGuards.contains(typeGuard)) { @@ -2329,7 +2414,7 @@ String varName = name + specialization.getIndex(); TypeMirror type = cache.getParameter().getType(); builder.declaration(type, varName, initializer); - currentValues.set(name, new LocalVariable(null, type, varName, null, null)); + currentValues.set(name, new LocalVariable(type, varName, null, null)); } public static final class LocalContext { @@ -2345,13 +2430,13 @@ for (CacheExpression cache : specialization.getCaches()) { Parameter cacheParameter = cache.getParameter(); String name = cacheParameter.getVariableElement().getSimpleName().toString(); - set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getTypeSystemType(), cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name), null)); + set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name), null)); } for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) { String name = assumptionName(assumption); TypeMirror type = assumption.getExpression().getResolvedType(); - set(name, new LocalVariable(null, type, name, CodeTreeBuilder.singleString("this." + name), null)); + set(name, new LocalVariable(type, name, CodeTreeBuilder.singleString("this." + name), null)); } } @@ -2382,12 +2467,12 @@ } @SuppressWarnings("static-method") - public LocalVariable createValue(NodeExecutionData execution, TypeData type) { - return new LocalVariable(type, type.getPrimitiveType(), valueName(execution), null, null); + public LocalVariable createValue(NodeExecutionData execution, TypeMirror type) { + return new LocalVariable(type, valueName(execution), null, null); } public LocalVariable createShortCircuitValue(NodeExecutionData execution) { - return new LocalVariable(factory.typeSystem.getBooleanType(), factory.getType(boolean.class), shortCircuitName(execution), null, null); + return new LocalVariable(factory.getType(boolean.class), shortCircuitName(execution), null, null); } private static String valueName(NodeExecutionData execution) { @@ -2424,7 +2509,12 @@ } public LocalVariable getValue(int signatureIndex) { - return getValue(factory.node.getChildExecutions().get(signatureIndex)); + List<NodeExecutionData> childExecutions = factory.node.getChildExecutions(); + if (signatureIndex < childExecutions.size()) { + return getValue(childExecutions.get(signatureIndex)); + } else { + return null; + } } public void removeValue(String id) { @@ -2458,11 +2548,11 @@ } private void loadValues(int evaluatedArguments, int varargsThreshold) { - values.put(FRAME_VALUE, new LocalVariable(null, factory.getType(Frame.class), FRAME_VALUE, null, null)); + values.put(FRAME_VALUE, new LocalVariable(factory.getType(Frame.class), FRAME_VALUE, null, null)); for (NodeFieldData field : factory.node.getFields()) { String fieldName = fieldValueName(field); - values.put(fieldName, new LocalVariable(null, field.getType(), fieldName, factory.accessParent(field.getName()), null)); + values.put(fieldName, new LocalVariable(field.getType(), fieldName, factory.accessParent(field.getName()), null)); } boolean varargs = needsVarargs(false, varargsThreshold); @@ -2473,7 +2563,7 @@ } NodeExecutionData execution = childExecutions.get(i); if (execution.isShortCircuit()) { - LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric(); + LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric(factory.context); if (varargs) { shortCircuit = shortCircuit.accessWith(createReadVarargs(i)); } @@ -2562,7 +2652,6 @@ public static final class LocalVariable { - private final TypeData type; private final TypeMirror typeMirror; private final CodeTree accessorTree; private final String name; @@ -2576,22 +2665,17 @@ } else { name = createName(execution); } - return new LocalVariable(parameter.getTypeSystemType(), parameter.getType(), name, null, null); + return new LocalVariable(parameter.getType(), name, null, null); } - private LocalVariable(TypeData type, TypeMirror typeMirror, String name, CodeTree accessorTree, LocalVariable previous) { + private LocalVariable(TypeMirror typeMirror, String name, CodeTree accessorTree, LocalVariable previous) { Objects.requireNonNull(typeMirror); this.typeMirror = typeMirror; this.accessorTree = accessorTree; - this.type = type; this.name = name; this.previous = previous; } - public TypeData getType() { - return type; - } - public String getShortCircuitName() { return "has" + ElementUtils.firstLetterUpperCase(getName()); } @@ -2631,24 +2715,20 @@ } } - public LocalVariable newType(TypeData newType) { - return new LocalVariable(newType, newType.getPrimitiveType(), name, accessorTree, this); - } - public LocalVariable newType(TypeMirror newType) { - return new LocalVariable(type, newType, name, accessorTree, this); + return new LocalVariable(newType, name, accessorTree, this); } public LocalVariable accessWith(CodeTree tree) { - return new LocalVariable(type, typeMirror, name, tree, this); + return new LocalVariable(typeMirror, name, tree, this); } public LocalVariable nextName() { - return new LocalVariable(type, typeMirror, createNextName(name), accessorTree, this); + return new LocalVariable(typeMirror, createNextName(name), accessorTree, this); } public LocalVariable makeOriginal() { - return new LocalVariable(type, typeMirror, name, accessorTree, null); + return new LocalVariable(typeMirror, name, accessorTree, null); } public LocalVariable original() { @@ -2659,8 +2739,8 @@ return variable; } - public LocalVariable makeGeneric() { - return newType(type.getTypeSystem().getGenericTypeData()); + public LocalVariable makeGeneric(ProcessorContext context) { + return newType(context.getType(Object.class)); } @Override