# HG changeset patch # User Christian Humer # Date 1429032213 -7200 # Node ID 824ef485081f4468dcb1522a7577a91a750486f4 # Parent 56eb34a5aa224e541d19af4712aa9093fa726624 Truffle-DSL: performance optimization for types * specialization complexity in shouldOverrideExecutableType. diff -r 56eb34a5aa22 -r 824ef485081f graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Tue Apr 14 19:23:33 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Tue Apr 14 19:23:33 2015 +0200 @@ -67,6 +67,8 @@ private final int varArgsThreshold; private final Set expectedTypes = new HashSet<>(); private boolean nextUsed; + private List usedTypes; + private List reachableSpecializations; public NodeGenFactory(ProcessorContext context, NodeData node) { this.context = context; @@ -74,8 +76,10 @@ this.typeSystem = node.getTypeSystem(); this.genericType = context.getType(Object.class); this.options = typeSystem.getOptions(); + this.varArgsThreshold = calculateVarArgsThreshold(); + this.reachableSpecializations = calculateReachableSpecializations(); this.singleSpecializable = isSingleSpecializableImpl(); - this.varArgsThreshold = calculateVarArgsThreshold(); + this.usedTypes = filterBaseExecutableTypes(node.getExecutableTypes(), reachableSpecializations); } private int calculateVarArgsThreshold() { @@ -205,7 +209,6 @@ } } - List usedTypes = filterBaseExecutableTypes(node.getExecutableTypes(), getReachableSpecializations()); for (ExecutableTypeData execType : usedTypes) { if (execType.getMethod() == null) { continue; @@ -356,8 +359,6 @@ } private SpecializationData createSpecializations(CodeTypeElement clazz) { - List reachableSpecializations = getReachableSpecializations(); - CodeTypeElement baseSpecialization = clazz.add(createBaseSpecialization()); TypeMirror baseSpecializationType = baseSpecialization.asType(); @@ -384,7 +385,6 @@ } private boolean needsPolymorphic() { - List reachableSpecializations = getReachableSpecializations(); if (reachableSpecializations.size() != 1) { return true; } @@ -416,7 +416,6 @@ clazz.add(createGetNext(clazz)); clazz.add(createAcceptAndExecute()); - List usedTypes = filterBaseExecutableTypes(node.getExecutableTypes(), getReachableSpecializations()); for (ExecutableTypeData type : usedTypes) { clazz.add(createFastPathExecuteMethod(null, type, usedTypes)); } @@ -460,12 +459,12 @@ return true; } - if (!isSubtypeBoxed(context, specialization.getReturnType().getType(), executableType.getReturnType())) { + // specializations with more parameters are just ignored + if (executableType.getEvaluatedCount() > node.getSignatureSize()) { return false; } - // specializations with more parameters are just ignored - if (executableType.getEvaluatedCount() > node.getSignatureSize()) { + if (!isSubtypeBoxed(context, specialization.getReturnType().getType(), executableType.getReturnType())) { return false; } @@ -529,11 +528,33 @@ } private List filterBaseExecutableTypes(List executableTypes, List specializations) { - Set usedTypes = new HashSet<>(); - type: for (ExecutableTypeData type : executableTypes) { + Set returnTypes = new HashSet<>(); + for (SpecializationData specialization : node.getSpecializations()) { + returnTypes.add(specialization.getReturnType().getType()); + } + + List prefilteredTypes = new ArrayList<>(); + for (ExecutableTypeData type : executableTypes) { + if (type.getDelegatedTo() == null || shouldAlwaysImplementExecutableType(type)) { + prefilteredTypes.add(type); + } else { + boolean foundSubtype = false; + for (TypeMirror returnType : returnTypes) { + if (isSubtypeBoxed(context, returnType, type.getReturnType())) { + foundSubtype = true; + } + } + if (foundSubtype) { + prefilteredTypes.add(type); + } + } + } + + Set types = new HashSet<>(); + type: for (ExecutableTypeData type : prefilteredTypes) { for (SpecializationData specialization : specializations) { - if (shouldImplementExecutableType(specialization, type) || type.isAbstract() || !(type.hasUnexpectedValue(context) && type.getMethod() != null)) { - usedTypes.add(type); + if (shouldImplementExecutableType(specialization, type) || shouldAlwaysImplementExecutableType(type)) { + types.add(type); continue type; } } @@ -541,19 +562,23 @@ Set delegatesToAdd = new HashSet<>(); do { delegatesToAdd.clear(); - for (ExecutableTypeData type : usedTypes) { + for (ExecutableTypeData type : types) { ExecutableTypeData delegate = type.getDelegatedTo(); - if (delegate != null && !usedTypes.contains(delegate)) { + if (delegate != null && !types.contains(delegate)) { delegatesToAdd.add(delegate); } } - usedTypes.addAll(delegatesToAdd); + types.addAll(delegatesToAdd); } while (!delegatesToAdd.isEmpty()); - List newUsedTypes = new ArrayList<>(usedTypes); + List newUsedTypes = new ArrayList<>(types); Collections.sort(newUsedTypes); return newUsedTypes; } + private boolean shouldAlwaysImplementExecutableType(ExecutableTypeData type) { + return type.isAbstract() || !(type.hasUnexpectedValue(context) && type.getMethod() != null); + } + private CodeTypeElement createSpecialization(SpecializationData specialization, TypeMirror baseType) { CodeTypeElement clazz = createClass(node, specialization, modifiers(PRIVATE, STATIC, FINAL), specializationTypeName(specialization), baseType); @@ -876,7 +901,6 @@ } private boolean isSingleSpecializableImpl() { - List reachableSpecializations = getReachableSpecializations(); if (reachableSpecializations.size() != 1) { return false; } @@ -902,7 +926,7 @@ return true; } - private List getReachableSpecializations() { + private List calculateReachableSpecializations() { List specializations = new ArrayList<>(); for (SpecializationData specialization : node.getSpecializations()) { if (specialization.isReachable() && // @@ -933,7 +957,7 @@ CodeTreeBuilder builder = method.createBuilder(); if (singleSpecializable) { - SpecializationData specialization = getReachableSpecializations().iterator().next(); + SpecializationData specialization = reachableSpecializations.iterator().next(); builder.tree(createFastPath(builder, specialization, execType, usedExecutables, locals)); } else { // create acceptAndExecute @@ -1076,7 +1100,7 @@ } private SpecializationGroup createSpecializationGroups() { - return SpecializationGroup.create(getReachableSpecializations()); + return SpecializationGroup.create(reachableSpecializations); } private CodeTree createSlowPathExecute(SpecializationData specialization, LocalContext currentValues) { @@ -1609,9 +1633,11 @@ } } else { executable = currentLocals.createMethod(modifiers(PUBLIC), returnType, methodName, FRAME_VALUE); - if (executedType.hasUnexpectedValue(context)) { - executable.getThrownTypes().add(context.getDeclaredType(UnexpectedResultException.class)); - } + } + executable.getThrownTypes().clear(); + + if (executedType.hasUnexpectedValue(context)) { + executable.getThrownTypes().add(context.getDeclaredType(UnexpectedResultException.class)); } return executable;