Mercurial > hg > truffle
diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java @ 19757:e8d2f3f95dcd
Truffle-DSL: implemented duplication check for specializations with @Cached to avoid duplicates for multithreaded AST execution.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 10 Mar 2015 19:28:26 +0100 |
parents | d03352ba2efb |
children | e773cc48d3e8 |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Tue Mar 10 13:47:46 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Tue Mar 10 19:28:26 2015 +0100 @@ -447,6 +447,7 @@ clazz.addOptional(createSpecializationCreateMethod(specialization, constructor)); clazz.addOptional(createMergeMethod(specialization)); clazz.addOptional(createIsSameMethod(specialization)); + clazz.addOptional(createIsIdenticalMethod(specialization)); TypeData returnType = specialization.getReturnType().getTypeSystemType(); int signatureSize = specialization.getSignatureSize(); @@ -493,6 +494,36 @@ return executable; } + private Element createIsIdenticalMethod(SpecializationData specialization) { + boolean cacheBoundGuard = specialization.hasMultipleInstances(); + if (!cacheBoundGuard) { + return null; + } + + LocalContext currentLocals = LocalContext.load(this, node.getSignatureSize(), varArgsThreshold); + currentLocals.loadFastPathState(specialization); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isIdentical"); + method.addParameter(new CodeVariableElement(getType(SpecializationNode.class), "other")); + currentLocals.addParametersTo(method, FRAME_VALUE); + method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); + final CodeTreeBuilder builder = method.createBuilder(); + + SpecializationGroup group = SpecializationGroup.create(specialization); + SpecializationBody executionFactory = new SpecializationBody(true, false) { + @Override + public CodeTree createBody(SpecializationData s, LocalContext values) { + return builder.create().returnTrue().build(); + } + }; + + builder.startIf().string("isSame(other)").end().startBlock(); + builder.tree(createGuardAndCast(group, typeSystem.getGenericTypeData(), currentLocals, executionFactory)); + builder.end(); + builder.returnFalse(); + return method; + } + private CodeExecutableElement createIsSameMethod(SpecializationData specialization) { if (!specialization.isSpecialized() || !options.implicitCastOptimization().isDuplicateTail()) { return null; @@ -532,18 +563,29 @@ } private Element createMergeMethod(SpecializationData specialization) { - boolean cacheBoundGuard = specialization.hasMultipleInstances(); - if (specialization.getExcludedBy().isEmpty() && !specialization.isPolymorphic() && !cacheBoundGuard) { + if (specialization.getExcludedBy().isEmpty() && !specialization.isPolymorphic()) { return null; } TypeMirror specializationNodeType = getType(SpecializationNode.class); + LocalContext currentLocals = LocalContext.load(this, node.getSignatureSize(), varArgsThreshold); + CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), specializationNodeType, "merge"); executable.addParameter(new CodeVariableElement(specializationNodeType, "newNode")); + currentLocals.addParametersTo(executable, FRAME_VALUE); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = executable.createBuilder(); if (specialization.isPolymorphic()) { - builder.statement("return polymorphicMerge(newNode)"); + builder.startReturn(); + builder.startCall("polymorphicMerge"); + builder.string("newNode"); + builder.startCall("super", "merge"); + builder.string("newNode"); + currentLocals.addReferencesTo(builder, FRAME_VALUE); + builder.end(); + builder.end(); + builder.end(); + } else { boolean elseIf = false; for (SpecializationData containedSpecialization : specialization.getExcludedBy()) { @@ -554,11 +596,12 @@ builder.statement("removeSame(\"Contained by " + containedSpecialization.createReferenceName() + "\")"); builder.end(); } - if (cacheBoundGuard) { - builder.statement("return super.mergeNoSame(newNode)"); - } else { - builder.statement("return super.merge(newNode)"); - } + builder.startReturn(); + builder.startCall("super", "merge"); + builder.string("newNode"); + currentLocals.addReferencesTo(builder, FRAME_VALUE); + builder.end(); + builder.end(); } return executable; @@ -638,18 +681,15 @@ CodeTreeBuilder builder = method.createBuilder(); SpecializationGroup group = createSpecializationGroups(); - CodeTree execution = createGuardAndCast(group, genericType, locals, new SpecializationExecution() { - public CodeTree createExecute(SpecializationData specialization, LocalContext values) { + CodeTree execution = createGuardAndCast(group, genericType, locals, new SpecializationBody(false, false) { + @Override + public CodeTree createBody(SpecializationData specialization, LocalContext values) { CodeTypeElement generatedType = specializationClasses.get(specialization); if (generatedType == null) { throw new AssertionError("No generated type for " + specialization); } return createSlowPathExecute(specialization, values); } - - public boolean isFastPath() { - return false; - } }); builder.tree(execution); @@ -1525,14 +1565,11 @@ } else { final TypeData finalType = type; SpecializationGroup group = SpecializationGroup.create(specialization); - SpecializationExecution executionFactory = new SpecializationExecution() { - public CodeTree createExecute(SpecializationData s, LocalContext values) { + SpecializationBody executionFactory = new SpecializationBody(true, true) { + @Override + public CodeTree createBody(SpecializationData s, LocalContext values) { return createFastPathExecute(builder, finalType, s, values); } - - public boolean isFastPath() { - return true; - } }; builder.tree(createGuardAndCast(group, type, currentLocals, executionFactory)); if (hasFallthrough(group, type, originalValues, true, null) || group.getSpecialization().isFallback()) { @@ -1621,11 +1658,11 @@ return builder.build(); } - private CodeTree createGuardAndCast(SpecializationGroup group, TypeData forType, LocalContext currentValues, SpecializationExecution execution) { + private CodeTree createGuardAndCast(SpecializationGroup group, TypeData forType, LocalContext currentValues, SpecializationBody execution) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); Set<TypeGuard> castGuards; - if (execution.isFastPath()) { + if (execution.needsCastedValues()) { castGuards = null; // cast all } else { castGuards = new HashSet<>(); @@ -1679,7 +1716,7 @@ builder.tree(createGuardAndCast(child, forType, currentValues.copy(), execution)); } if (specialization != null) { - builder.tree(execution.createExecute(specialization, currentValues)); + builder.tree(execution.createBody(specialization, currentValues)); } } builder.end(ifCount); @@ -2207,7 +2244,7 @@ } private CodeTree[] createTypeCheckAndLocals(SpecializationData specialization, List<TypeGuard> typeGuards, Set<TypeGuard> castGuards, LocalContext currentValues, - SpecializationExecution specializationExecution) { + SpecializationBody specializationExecution) { CodeTreeBuilder checksBuilder = CodeTreeBuilder.createBuilder(); CodeTreeBuilder localsBuilder = CodeTreeBuilder.createBuilder(); for (TypeGuard typeGuard : typeGuards) { @@ -2635,11 +2672,25 @@ } - private interface SpecializationExecution { - - boolean isFastPath(); - - CodeTree createExecute(SpecializationData specialization, LocalContext currentValues); + private abstract class SpecializationBody { + + private final boolean fastPath; + private final boolean needsCastedValues; + + public SpecializationBody(boolean fastPath, boolean needsCastedValues) { + this.fastPath = fastPath; + this.needsCastedValues = needsCastedValues; + } + + public final boolean isFastPath() { + return fastPath; + } + + public final boolean needsCastedValues() { + return needsCastedValues; + } + + public abstract CodeTree createBody(SpecializationData specialization, LocalContext currentValues); }