diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java @ 18776:c0fb70634640

Truffle-DSL: support for frame types Frame, MaterializedFrame. Added validation for frame type consistency. Some refactorings along the way.
author Christian Humer <christian.humer@gmail.com>
date Mon, 05 Jan 2015 01:31:08 +0100
parents 674c8a6d5e6c
children 76cbf5f33f82
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Mon Jan 05 01:31:08 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Mon Jan 05 01:31:08 2015 +0100
@@ -169,7 +169,7 @@
         }
 
         for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (findSpecializedExecutables(execution, node.findSpecializedTypes(execution), options.polymorphicTypeBoxingElimination()).isEmpty()) {
+            if (resolveSpecializedExecutables(execution, node.findSpecializedTypes(execution), options.polymorphicTypeBoxingElimination()).isEmpty()) {
                 continue;
             }
             clazz.add(createNodeField(PRIVATE, getType(Class.class), polymorphicTypeProfileFieldName(execution), CompilationFinal.class));
@@ -225,7 +225,7 @@
                     CodeTree nameTree = CodeTreeBuilder.singleString(name);
                     CodeTreeBuilder callBuilder = builder.create();
                     callBuilder.string(name).string(" != null ? ");
-                    callBuilder.tree(callTemplateMethod(builder, null, createCast, nameTree));
+                    callBuilder.tree(callTemplateMethod(null, createCast, nameTree));
                     callBuilder.string(" : null");
                     name += "_";
                     builder.declaration(child.getNodeType(), name, callBuilder.build());
@@ -251,7 +251,7 @@
             CodeTree accessor = accessorBuilder.build();
 
             if (createCast != null && execution.getChild().getCardinality().isOne()) {
-                accessor = callTemplateMethod(builder, null, createCast, accessor);
+                accessor = callTemplateMethod(null, createCast, accessor);
             }
 
             if (execution.isIndexed()) {
@@ -282,7 +282,7 @@
             clazz.add(createSingleSpecialization(single));
             return single;
         } else {
-            CodeTypeElement baseSpecialization = clazz.add(createBaseSpecialization(clazz));
+            CodeTypeElement baseSpecialization = clazz.add(createBaseSpecialization());
             TypeMirror baseSpecializationType = baseSpecialization.asType();
 
             Map<SpecializationData, CodeTypeElement> generated = new LinkedHashMap<>();
@@ -308,7 +308,7 @@
 
     // create specialization
 
-    private CodeTypeElement createBaseSpecialization(CodeTypeElement parentClass) {
+    private CodeTypeElement createBaseSpecialization() {
         CodeTypeElement clazz = createClass(node, null, modifiers(PRIVATE, ABSTRACT, STATIC), "BaseNode_", TypeSystemNodeFactory.nodeType(typeSystem));
 
         clazz.addOptional(createSpecializationConstructor(clazz, null, null));
@@ -330,11 +330,7 @@
             specializedTypes.add(genericType);
             for (TypeData specializedType : specializedTypes) {
                 if (isExecuteChildShared(execution, specializedType)) {
-                    if (specializedType.isGeneric()) {
-                        parentClass.add(createExecuteChildMethod(execution, specializedType));
-                    } else {
-                        clazz.add(createExecuteChildMethod(execution, specializedType));
-                    }
+                    clazz.add(createExecuteChildMethod(execution, specializedType));
                 }
             }
         }
@@ -495,7 +491,7 @@
 
     private Element createFastPathWrapVoidMethod(TypeData wrap) {
         CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), typeSystem.getVoidType().getPrimitiveType(), TypeSystemNodeFactory.executeName(typeSystem.getVoidType()));
-        executable.addParameter(new CodeVariableElement(getType(VirtualFrame.class), FRAME_VALUE));
+        executable.addParameter(new CodeVariableElement(getType(Frame.class), FRAME_VALUE));
         executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
         CodeTreeBuilder builder = executable.createBuilder();
         builder.startStatement();
@@ -509,7 +505,7 @@
 
     private Element createFastPathWrapExecuteMethod(TypeData override, TypeData wrap) {
         CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), override.getPrimitiveType(), TypeSystemNodeFactory.executeName(override));
-        executable.addParameter(new CodeVariableElement(getType(VirtualFrame.class), FRAME_VALUE));
+        executable.addParameter(new CodeVariableElement(getType(Frame.class), FRAME_VALUE));
         executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
         CodeTreeBuilder builder = executable.createBuilder();
         if (wrap != null) {
@@ -605,7 +601,7 @@
     }
 
     private CodeExecutableElement createFallbackGuardMethod() {
-        boolean frameUsed = node.isFrameUsedByAnyGuard(context);
+        boolean frameUsed = node.isFrameUsedByAnyGuard();
         LocalContext locals = LocalContext.load(this);
 
         if (!frameUsed) {
@@ -701,7 +697,7 @@
 
         CodeTreeBuilder builder = method.createBuilder();
         builder.startReturn();
-        builder.tree(callTemplateMethod(builder, accessParent(null), fallback, locals));
+        builder.tree(callTemplateMethod(accessParent(null), fallback, locals));
         builder.end();
 
         return method;
@@ -860,9 +856,11 @@
         return childField;
     }
 
-    private static List<ExecutableTypeData> findSpecializedExecutables(NodeExecutionData execution, Collection<TypeData> types, TypeBoxingOptimization optimization) {
+    private static List<ExecutableTypeData> resolveSpecializedExecutables(NodeExecutionData execution, Collection<TypeData> types, TypeBoxingOptimization optimization) {
         if (optimization == TypeBoxingOptimization.NONE) {
             return Collections.emptyList();
+        } else if (types.isEmpty()) {
+            return Collections.emptyList();
         }
 
         List<ExecutableTypeData> executables = new ArrayList<>();
@@ -878,8 +876,8 @@
         return executables;
     }
 
-    private static CodeTree callTemplateMethod(CodeTreeBuilder parent, CodeTree receiver, TemplateMethod method, CodeTree... boundValues) {
-        CodeTreeBuilder builder = parent.create();
+    private static CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, CodeTree... boundValues) {
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         if (method.getMethod().getModifiers().contains(STATIC)) {
             builder.startStaticCall(method.getMethod().getEnclosingElement().asType(), method.getMethodName());
         } else {
@@ -901,25 +899,33 @@
         return builder.build();
     }
 
-    private static CodeTree callTemplateMethod(CodeTreeBuilder parent, CodeTree receiver, TemplateMethod method, LocalContext currentValues) {
+    private static CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, LocalContext currentValues) {
         CodeTree[] bindings = new CodeTree[method.getParameters().size()];
 
         int signatureIndex = 0;
         for (int i = 0; i < bindings.length; i++) {
             Parameter parameter = method.getParameters().get(i);
+
             LocalVariable var = currentValues.get(parameter, signatureIndex);
+            if (var == null) {
+                var = currentValues.get(parameter.getLocalName());
+            }
+
             if (var != null) {
-                CodeTree valueReference = bindings[i] = var.createReference();
+                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;
             }
+
             if (parameter.getSpecification().isSignature()) {
                 signatureIndex++;
             }
         }
-        return callTemplateMethod(parent, receiver, method, bindings);
+        return callTemplateMethod(receiver, method, bindings);
     }
 
     private SpecializationGroup createSpecializationGroups() {
@@ -931,7 +937,7 @@
         if (specialization.isFallback()) {
             return builder.returnNull().build();
         }
-        if (node.isFrameUsedByAnyGuard(context)) {
+        if (node.isFrameUsedByAnyGuard()) {
             builder.tree(createTransferToInterpreterAndInvalidate());
         }
         for (SpecializationData otherSpeciailzation : node.getSpecializations()) {
@@ -1154,24 +1160,27 @@
         return TypeSystemCodeGenerator.expect(executedType, forType, builder.build());
     }
 
-    private static ExecutableTypeData findSpecializedExecutableType(NodeExecutionData execution, TypeData type) {
-        NodeChildData child = execution.getChild();
+    private Set<ExecutableTypeData> findSpecializedExecutableTypes(NodeExecutionData execution, TypeData type) {
+        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()));
+        }
+        return executedTypes;
+    }
+
+    private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeData type) {
         int executeWithCount = child.getExecuteWith().size();
-        return child.getNodeData().findExecutableType(type, executeWithCount);
+        ExecutableTypeData executableType = child.getNodeData().findExecutableType(type, executeWithCount);
+        if (executableType == null) {
+            executableType = child.getNodeData().findAnyGenericExecutableType(context, executeWithCount);
+        }
+        return executableType;
     }
 
     private boolean hasUnexpectedResult(NodeExecutionData execution, TypeData type) {
-        if (type.isGeneric() || type.isVoid()) {
-            return false;
-        }
-        List<ExecutableTypeData> executableTypes = new ArrayList<>();
-        executableTypes.add(findSpecializedExecutableType(execution, type));
-
-        if (!options.implicitCastOptimization().isNone()) {
-            executableTypes.addAll(findSpecializedExecutables(execution, type.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization()));
-        }
-
-        for (ExecutableTypeData executableType : executableTypes) {
+        for (ExecutableTypeData executableType : findSpecializedExecutableTypes(execution, type)) {
             if (executableType != null && executableType.hasUnexpectedValue(context)) {
                 return true;
             }
@@ -1245,7 +1254,7 @@
 
         if (execution.isShortCircuit()) {
             ShortCircuitData shortCircuitData = resolvedSpecialization.getShortCircuits().get(calculateShortCircuitIndex(execution));
-            CodeTree access = callTemplateMethod(CodeTreeBuilder.createBuilder(), accessParent(null), shortCircuitData, currentLocals);
+            CodeTree access = callTemplateMethod(accessParent(null), shortCircuitData, currentLocals);
             shortCircuit = currentLocals.createShortCircuitValue(execution).accessWith(access);
         }
         return shortCircuit;
@@ -1269,7 +1278,7 @@
         int ifCount = 0;
         if (specialization.isFallback()) {
             builder.startIf().startCall("guardFallback");
-            if (node.isFrameUsedByAnyGuard(context)) {
+            if (node.isFrameUsedByAnyGuard()) {
                 builder.string(FRAME_VALUE);
             }
             currentValues.addReferencesTo(builder);
@@ -1286,7 +1295,7 @@
             currentValues.addReferencesTo(execute, FRAME_VALUE);
             execute.end();
         } else {
-            execute.tree(callTemplateMethod(execute, accessParent(null), specialization, currentValues));
+            execute.tree(callTemplateMethod(accessParent(null), specialization, currentValues));
         }
         execute.end();
         builder.tree(createFastPathTryCatchRewriteException(specialization, forType, currentValues, execute.build()));
@@ -1454,7 +1463,7 @@
         }
 
         CodeTreeBuilder builder = method.createBuilder();
-        CodeTree executeChild = createExecuteChild(execution, targetType, locals.createValue(execution, targetType), locals, true);
+        CodeTree executeChild = createExecuteChild(execution, locals.createValue(execution, targetType), locals, true);
         if (executeChild.isSingleLine()) {
             builder.statement(executeChild);
         } else {
@@ -1484,7 +1493,7 @@
             if (isSingleSpecializable(getReachableSpecializations())) {
                 return false;
             }
-            return findSpecializedExecutables(execution, node.findSpecializedTypes(execution), options.polymorphicTypeBoxingElimination()).size() >= 1;
+            return resolveSpecializedExecutables(execution, node.findSpecializedTypes(execution), options.polymorphicTypeBoxingElimination()).size() >= 1;
         } else {
             if (!isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), targetType)) {
                 return false;
@@ -1503,7 +1512,7 @@
                 }
             }
             if (uses > 1) {
-                return findSpecializedExecutables(execution, targetType.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization()).size() > 1;
+                return resolveSpecializedExecutables(execution, targetType.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization()).size() > 1;
             } else {
                 return false;
             }
@@ -1518,7 +1527,7 @@
         if (isExecuteChildShared(execution, targetValue.getType())) {
             executeChild = createCallSharedExecuteChild(execution, targetValue, currentValues);
         } else {
-            executeChild = createExecuteChild(execution, targetValue.getType(), targetValue, currentValues, false);
+            executeChild = createExecuteChild(execution, targetValue, currentValues, false);
         }
 
         builder.tree(createTryExecuteChild(targetValue, executeChild, shortCircuit == null, hasUnexpected));
@@ -1605,11 +1614,7 @@
 
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         builder.tree(targetValue.createReference()).string(" = ");
-        if (targetValue.getType().isGeneric()) {
-            builder.startCall("root", executeChildMethodName(execution, targetValue.getType()));
-        } else {
-            builder.startCall(executeChildMethodName(execution, targetValue.getType()));
-        }
+        builder.startCall(executeChildMethodName(execution, targetValue.getType()));
         builder.string(FRAME_VALUE);
 
         CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetValue.getType());
@@ -1623,171 +1628,149 @@
         return builder.build();
     }
 
-    private CodeTree createExecuteChild(NodeExecutionData execution, TypeData returnType, LocalVariable target, LocalContext currentValues, boolean shared) {
+    private CodeTree createExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) {
         final CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        final ExecutableTypeData executableType = findSpecializedExecutableType(execution, target.getType());
 
-        CodeTree assignment = createAssignmentStart(target, shared, false);
+        CodeTree assignment = createAssignmentStart(target, shared);
 
-        if (executableType == null) {
-            if (target.getType().isGeneric()) {
-                throw new AssertionError("Should be caught by the parser.");
-            }
-            CodeTree genericExecute = createExecuteChild(execution, returnType, target.makeGeneric(), currentValues, shared);
-            builder.tree(genericExecute);
-        } else {
+        final Set<ExecutableTypeData> executableTypes = findSpecializedExecutableTypes(execution, target.getType());
+        if (executableTypes.isEmpty()) {
+            throw new AssertionError(); // cannot execute child
+        } else if (executableTypes.size() == 1) {
+            ExecutableTypeData executableType = executableTypes.iterator().next();
             if (target.getType().isGeneric() && executableType.getEvaluatedCount() == 0) {
                 return createPolymorphicExecuteChild(execution, target, currentValues, shared);
-            } else if (target.getType().hasImplicitSourceTypes()) {
-                if (options.implicitCastOptimization().isNone()) {
-                    CodeTree execute = createCallSharedExecuteChild(execution, target.makeGeneric(), currentValues);
-                    return TypeSystemCodeGenerator.implicitExpect(target.getType(), execute, null);
-                } else if (options.implicitCastOptimization().isDuplicateTail()) {
-                    builder.tree(createExecuteChildDuplicateTail(builder, execution, assignment, target, currentValues));
-                } else if (options.implicitCastOptimization().isMergeCasts()) {
-                    // TODO
-                } else {
-                    throw new AssertionError();
-                }
             } else {
                 builder.tree(assignment);
-
-                CodeTree accessChild;
-                if (shared && target.getType().isGeneric()) {
-                    accessChild = CodeTreeBuilder.singleString(nodeFieldName(execution));
-                } else {
-                    accessChild = accessParent(nodeFieldName(execution));
-                }
-
-                CodeTree execute = callTemplateMethod(builder, accessChild, executableType, currentValues);
-                CodeTree expect = TypeSystemCodeGenerator.expect(executableType.getType(), returnType, execute);
-                builder.tree(expect);
+                builder.tree(createSingleExecute(execution, target, currentValues, executableType));
+            }
+        } else {
+            if (options.implicitCastOptimization().isNone()) {
+                throw new AssertionError("findSpecializedExecutableTypes is always 1 if implicit cast opt is disabled");
+            } else if (options.implicitCastOptimization().isDuplicateTail()) {
+                builder.tree(createExecuteChildDuplicateTail(builder, execution, assignment, target, currentValues));
+            } else if (options.implicitCastOptimization().isMergeCasts()) {
+                // TODO
+                throw new UnsupportedOperationException();
+            } else {
+                throw new AssertionError();
             }
         }
         return builder.build();
     }
 
+    private static 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);
+    }
+
     private CodeTree createPolymorphicExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) throws AssertionError {
         ExecutableTypeData genericExecutableType = execution.getChild().getNodeData().findAnyGenericExecutableType(context, execution.getChild().getExecuteWith().size());
         if (genericExecutableType == null) {
-            throw new AssertionError("error should be caught by the parser");
+            throw new AssertionError("At least one generic executable method must be available.");
         }
 
-        CodeTree assignment = createAssignmentStart(target, shared, true);
-
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        CodeTreeBuilder polyChainBuilder = builder.create();
-        boolean hasUnexpectedResult = false;
-
         Set<TypeData> specializedTypes = new HashSet<>();
         for (TypeData type : node.findSpecializedTypes(execution)) {
             specializedTypes.addAll(type.getImplicitSourceTypes());
         }
 
-        List<ExecutableTypeData> specializedExecutables = findSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination());
-
+        List<ExecutableTypeData> specializedExecutables = resolveSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination());
         Collections.sort(specializedExecutables, new Comparator<ExecutableTypeData>() {
             public int compare(ExecutableTypeData o1, ExecutableTypeData o2) {
                 return o1.getType().compareTo(o2.getType());
             }
         });
 
-        if (isSingleSpecializable(getReachableSpecializations())) {
-            specializedExecutables = Collections.emptyList();
-        }
+        CodeTree assignment = createAssignmentStart(target, shared);
+        CodeTree executeGeneric = createSingleExecute(execution, target, currentValues, genericExecutableType);
 
-        boolean hasSpecializedTypes = false;
-        for (ExecutableTypeData executableType : specializedExecutables) {
-            hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes);
-            polyChainBuilder.tree(createAccessPolymorphicField(execution, shared));
-            polyChainBuilder.string(" == ").typeLiteral(executableType.getType().getPrimitiveType());
-            polyChainBuilder.end();
-            polyChainBuilder.startBlock();
-            polyChainBuilder.startStatement();
-            polyChainBuilder.tree(assignment);
-            polyChainBuilder.tree(callTemplateMethod(polyChainBuilder, CodeTreeBuilder.singleString(nodeFieldName(execution)), executableType, currentValues)).end();
-            polyChainBuilder.end();
-            hasUnexpectedResult |= executableType.hasUnexpectedValue(context);
-        }
-
-        CodeTree executeGeneric = callTemplateMethod(polyChainBuilder, CodeTreeBuilder.singleString(nodeFieldName(execution)), genericExecutableType, currentValues);
-
-        if (specializedExecutables.isEmpty()) {
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        if (specializedExecutables.isEmpty() || isSingleSpecializable(getReachableSpecializations())) {
             builder.tree(assignment);
             builder.tree(executeGeneric);
         } else {
-            CodeTree accessPolymorphicProfile = createAccessPolymorphicField(execution, shared);
-            polyChainBuilder.startElseIf().tree(accessPolymorphicProfile).string(" == null").end();
+            final CodeTreeBuilder polyChainBuilder = builder.create();
+            final String profileField = polymorphicTypeProfileFieldName(execution);
+            final String valueFieldName = "_value";
+
+            builder.declaration(getType(Class.class), profileField, accessParent(profileField));
+
+            boolean encounteredUnexpectedResult = false;
+            boolean hasSpecializedTypes = false;
+            for (ExecutableTypeData executableType : specializedExecutables) {
+                hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes);
+                polyChainBuilder.string(profileField);
+                polyChainBuilder.string(" == ").typeLiteral(executableType.getType().getPrimitiveType());
+                polyChainBuilder.end();
+                polyChainBuilder.startBlock();
+                polyChainBuilder.startStatement();
+                polyChainBuilder.tree(assignment);
+                polyChainBuilder.tree(createSingleExecute(execution, target, currentValues, executableType)).end();
+                polyChainBuilder.end();
+                encounteredUnexpectedResult |= executableType.hasUnexpectedValue(context);
+            }
+
+            // else if null -> specialize
+            polyChainBuilder.startElseIf().string(profileField).string(" == null").end();
             polyChainBuilder.startBlock();
             polyChainBuilder.tree(createTransferToInterpreterAndInvalidate());
-            polyChainBuilder.declaration(genericExecutableType.getType().getPrimitiveType(), "value_", executeGeneric);
+            polyChainBuilder.declaration(genericExecutableType.getType().getPrimitiveType(), valueFieldName, executeGeneric);
 
             hasSpecializedTypes = false;
             for (ExecutableTypeData executableType : specializedExecutables) {
                 hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes);
-                polyChainBuilder.tree(TypeSystemCodeGenerator.check(executableType.getType(), CodeTreeBuilder.singleString("value_")));
+                polyChainBuilder.tree(TypeSystemCodeGenerator.check(executableType.getType(), CodeTreeBuilder.singleString(valueFieldName)));
                 polyChainBuilder.end();
                 polyChainBuilder.startBlock();
-                polyChainBuilder.startStatement().tree(accessPolymorphicProfile).string(" = ").typeLiteral(executableType.getType().getPrimitiveType()).end();
+                polyChainBuilder.startStatement().string(profileField).string(" = ").typeLiteral(executableType.getType().getPrimitiveType()).end();
                 polyChainBuilder.end();
             }
 
             polyChainBuilder.startElseBlock();
-            polyChainBuilder.startStatement().tree(accessPolymorphicProfile).string(" = ").typeLiteral(genericType.getPrimitiveType()).end();
+            polyChainBuilder.startStatement().string(profileField).string(" = ").typeLiteral(genericType.getPrimitiveType()).end();
+            polyChainBuilder.end();
+            polyChainBuilder.startReturn().string(valueFieldName).end();
             polyChainBuilder.end();
 
-            polyChainBuilder.startReturn().string("value_").end();
-
-            polyChainBuilder.end();
+            // else -> execute generic
             polyChainBuilder.startElseBlock();
             polyChainBuilder.startStatement().tree(assignment).tree(executeGeneric).end();
             polyChainBuilder.end();
 
-            if (hasUnexpectedResult) {
+            CodeTree executePolymorphic = polyChainBuilder.build();
+            if (encounteredUnexpectedResult) {
                 builder.startTryBlock();
-            }
-
-            builder.tree(polyChainBuilder.build());
-
-            if (hasUnexpectedResult) {
+                builder.tree(executePolymorphic);
                 builder.end();
                 builder.startCatchBlock(getType(UnexpectedResultException.class), "ex");
-                builder.startStatement().tree(accessPolymorphicProfile).string(" = ").typeLiteral(genericType.getPrimitiveType()).end();
+                builder.startStatement().string(profileField).string(" = ").typeLiteral(genericType.getPrimitiveType()).end();
                 builder.startReturn().string("ex.getResult()").end();
                 builder.end();
+            } else {
+                builder.tree(executePolymorphic);
             }
         }
         return builder.build();
     }
 
-    private static CodeTree createAssignmentStart(LocalVariable target, boolean shared, boolean accessParent) {
+    private static CodeTree createAssignmentStart(LocalVariable target, boolean shared) {
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         if (shared) {
             builder.string("return ");
         } else {
             builder.string(target.getName()).string(" = ");
-            if (accessParent) {
-                builder.tree(accessParent(null)).string(".");
-            }
         }
         return builder.build();
     }
 
-    private static CodeTree createAccessPolymorphicField(NodeExecutionData execution, boolean shared) {
-        String name = polymorphicTypeProfileFieldName(execution);
-        if (shared) {
-            return CodeTreeBuilder.singleString(name);
-        } else {
-            return accessParent(name);
-        }
-    }
-
     private CodeTree createExecuteChildDuplicateTail(CodeTreeBuilder parent, NodeExecutionData execution, CodeTree assignment, LocalVariable target, LocalContext currentValues) {
         CodeTreeBuilder builder = parent.create();
         List<TypeData> sourceTypes = target.getType().getImplicitSourceTypes();
         String implicitClassFieldName = implicitClassFieldName(execution);
         String nodeFieldName = nodeFieldName(execution);
-        List<ExecutableTypeData> executableTypes = findSpecializedExecutables(execution, sourceTypes, options.implicitTypeBoxingOptimization());
+        List<ExecutableTypeData> executableTypes = resolveSpecializedExecutables(execution, sourceTypes, options.implicitTypeBoxingOptimization());
 
         boolean elseIf = false;
         for (ExecutableTypeData executableType : executableTypes) {
@@ -1797,10 +1780,10 @@
             builder.startBlock();
             builder.startStatement().tree(assignment);
 
-            CodeTree execute = callTemplateMethod(builder, accessParent(nodeFieldName), executableType, currentValues);
+            CodeTree execute = callTemplateMethod(accessParent(nodeFieldName), executableType, currentValues);
             ImplicitCastData cast = typeSystem.lookupCast(executableType.getType(), target.getType());
             if (cast != null) {
-                execute = callTemplateMethod(builder, null, cast, execute);
+                execute = callTemplateMethod(null, cast, execute);
             }
             builder.tree(execute);
             builder.end();
@@ -1857,7 +1840,7 @@
             if (guard.isNegated()) {
                 builder.string("!");
             }
-            builder.tree(callTemplateMethod(builder, accessParent(null), guard.getResolvedGuard(), currentValues));
+            builder.tree(callTemplateMethod(accessParent(null), guard.getResolvedGuard(), currentValues));
             and = " && ";
         }
         return builder.build();
@@ -2039,7 +2022,7 @@
         }
 
         private void loadValues(int evaluatedArguments) {
-            values.put(FRAME_VALUE, new LocalVariable(null, factory.getType(VirtualFrame.class), FRAME_VALUE, null));
+            values.put(FRAME_VALUE, new LocalVariable(null, factory.getType(Frame.class), FRAME_VALUE, null));
 
             for (NodeFieldData field : factory.node.getFields()) {
                 String fieldName = fieldValueName(field);