diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart index fb4f1537c44..764341ce993 100644 --- a/pkg/compiler/lib/src/common/backend_api.dart +++ b/pkg/compiler/lib/src/common/backend_api.dart @@ -397,6 +397,7 @@ abstract class BackendClasses { ClassElement get numImplementation; ClassElement get stringImplementation; ClassElement get listImplementation; + ClassElement get mutableListImplementation; ClassElement get growableListImplementation; ClassElement get fixedListImplementation; ClassElement get constListImplementation; @@ -412,4 +413,8 @@ abstract class BackendClasses { ClassElement get syncStarIterableImplementation; ClassElement get asyncFutureImplementation; ClassElement get asyncStarStreamImplementation; + ClassElement get indexableImplementation; + ClassElement get mutableIndexableImplementation; + + bool isDefaultEqualityImplementation(Element element); } diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart index 7b913b0d259..ccc11554836 100644 --- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart +++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart @@ -751,6 +751,8 @@ abstract class InferrerVisitor> DiagnosticReporter get reporter => compiler.reporter; + ClosedWorld get closedWorld => compiler.closedWorld; + @override SemanticSendVisitor get sendVisitor => this; @@ -963,7 +965,6 @@ abstract class InferrerVisitor> T get thisType { if (_thisType != null) return _thisType; ClassElement cls = outermostElement.enclosingClass; - ClosedWorld closedWorld = compiler.closedWorld; if (closedWorld.isUsedAsMixin(cls)) { return _thisType = types.nonNullSubtype(cls); } else { diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart index f6cdaceffac..6295deda4d7 100644 --- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart +++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart @@ -180,7 +180,7 @@ abstract class InferrerEngine void forEachElementMatching( Selector selector, TypeMask mask, bool f(Element element)) { Iterable elements = - compiler.closedWorld.allFunctions.filter(selector, mask); + closedWorld.allFunctions.filter(selector, mask); for (Element e in elements) { if (!f(e.implementation)) return; } @@ -492,7 +492,7 @@ class SimpleTypeInferrerVisitor }); } if (analyzedElement.isGenerativeConstructor && cls.isAbstract) { - if (compiler.closedWorld.isInstantiated(cls)) { + if (closedWorld.isInstantiated(cls)) { returnType = types.nonNullSubclass(cls); } else { // TODO(johnniwinther): Avoid analyzing [analyzedElement] in this @@ -655,7 +655,7 @@ class SimpleTypeInferrerVisitor bool isInClassOrSubclass(Element element) { ClassElement cls = outermostElement.enclosingClass.declaration; ClassElement enclosing = element.enclosingClass.declaration; - return compiler.closedWorld.isSubclassOf(enclosing, cls); + return closedWorld.isSubclassOf(enclosing, cls); } void checkIfExposesThis(Selector selector, TypeMask mask) { @@ -1362,7 +1362,7 @@ class SimpleTypeInferrerVisitor (node.asSendSet() != null) && (node.asSendSet().receiver != null) && node.asSendSet().receiver.isThis()) { - Iterable targets = compiler.closedWorld.allFunctions.filter( + Iterable targets = closedWorld.allFunctions.filter( setterSelector, types.newTypedSelector(thisType, setterMask)); // We just recognized a field initialization of the form: // `this.foo = 42`. If there is only one target, we can update @@ -1635,7 +1635,7 @@ class SimpleTypeInferrerVisitor } else if (element != null && element.isField && Elements.isStaticOrTopLevelField(element) && - compiler.closedWorld.fieldNeverChanges(element)) { + closedWorld.fieldNeverChanges(element)) { FieldElement fieldElement = element; ConstantValue value = compiler.backend.constants.getConstantValue(fieldElement.constant); diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart index 16053883cf4..1d7f7d815c5 100644 --- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart +++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart @@ -252,8 +252,7 @@ class TypeInformationSystem extends TypeSystem { TypeInformation refineReceiver(Selector selector, TypeMask mask, TypeInformation receiver, bool isConditional) { if (receiver.type.isExact) return receiver; - TypeMask otherType = - compiler.closedWorld.allFunctions.receiverType(selector, mask); + TypeMask otherType = closedWorld.allFunctions.receiverType(selector, mask); // Conditional sends (a?.b) can still narrow the possible types of `a`, // however, we still need to consider that `a` may be null. if (isConditional) { @@ -916,8 +915,7 @@ class TypeGraphInferrerEngine if (!info.inLoop) return; if (info is StaticCallSiteTypeInformation) { compiler.inferenceWorld.addFunctionCalledInLoop(info.calledElement); - } else if (info.mask != null && - !info.mask.containsAll(compiler.closedWorld)) { + } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { // For instance methods, we only register a selector called in a // loop if it is a typed selector, to avoid marking too many // methods as being called from within a loop. This cuts down @@ -1189,7 +1187,7 @@ class TypeGraphInferrerEngine arguments, sideEffects, inLoop); } - compiler.closedWorld.allFunctions.filter(selector, mask).forEach((callee) { + closedWorld.allFunctions.filter(selector, mask).forEach((callee) { updateSideEffects(sideEffects, selector, callee); }); @@ -1414,11 +1412,11 @@ class TypeGraphInferrer implements TypesInferrer { TypeMask result = const TypeMask.nonNullEmpty(); Iterable elements = - compiler.closedWorld.allFunctions.filter(selector, mask); + inferrer.closedWorld.allFunctions.filter(selector, mask); for (Element element in elements) { TypeMask type = inferrer.typeOfElementWithSelector(element, selector).type; - result = result.union(type, compiler.closedWorld); + result = result.union(type, inferrer.closedWorld); } return result; } diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart index 7e3bbd6327a..ad31d89c54d 100644 --- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart +++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart @@ -522,13 +522,13 @@ class MemberTypeInformation extends ElementTypeInformation return mask; } if (element.isField) { - return _narrowType(compiler.closedWorld, mask, element.type); + return _narrowType(inferrer.closedWorld, mask, element.type); } assert( element.isFunction || element.isGetter || element.isFactoryConstructor); FunctionType type = element.type; - return _narrowType(compiler.closedWorld, mask, type.returnType); + return _narrowType(inferrer.closedWorld, mask, type.returnType); } TypeMask computeType(TypeGraphInferrerEngine inferrer) { @@ -669,7 +669,7 @@ class ParameterTypeInformation extends ElementTypeInformation { // ignore type annotations to ensure that the checks are actually inserted // into the function body and retained until runtime. assert(!compiler.options.enableTypeAssertions); - return _narrowType(compiler.closedWorld, mask, element.type); + return _narrowType(inferrer.closedWorld, mask, element.type); } TypeMask computeType(TypeGraphInferrerEngine inferrer) { @@ -818,8 +818,7 @@ class DynamicCallSiteTypeInformation extends CallSiteTypeInformation { void addToGraph(TypeGraphInferrerEngine inferrer) { assert(receiver != null); TypeMask typeMask = computeTypedSelector(inferrer); - targets = - inferrer.compiler.closedWorld.allFunctions.filter(selector, typeMask); + targets = inferrer.closedWorld.allFunctions.filter(selector, typeMask); receiver.addUser(this); if (arguments != null) { arguments.forEach((info) => info.addUser(this)); @@ -973,16 +972,16 @@ class DynamicCallSiteTypeInformation extends CallSiteTypeInformation { Compiler compiler = inferrer.compiler; JavaScriptBackend backend = compiler.backend; TypeMask maskToUse = - compiler.closedWorld.extendMaskIfReachesAll(selector, typeMask); + inferrer.closedWorld.extendMaskIfReachesAll(selector, typeMask); bool canReachAll = backend.hasInvokeOnSupport && (maskToUse != typeMask); // If this call could potentially reach all methods that satisfy // the untyped selector (through noSuchMethod's `Invocation` // and a call to `delegate`), we iterate over all these methods to // update their parameter types. - targets = compiler.closedWorld.allFunctions.filter(selector, maskToUse); + targets = inferrer.closedWorld.allFunctions.filter(selector, maskToUse); Iterable typedTargets = canReachAll - ? compiler.closedWorld.allFunctions.filter(selector, typeMask) + ? inferrer.closedWorld.allFunctions.filter(selector, typeMask) : targets; // Update the call graph if the targets could have changed. @@ -1078,8 +1077,7 @@ class DynamicCallSiteTypeInformation extends CallSiteTypeInformation { if (!abandonInferencing) { inferrer.updateSelectorInTree(caller, call, selector, mask); Iterable oldTargets = targets; - targets = - inferrer.compiler.closedWorld.allFunctions.filter(selector, mask); + targets = inferrer.closedWorld.allFunctions.filter(selector, mask); for (Element element in targets) { if (!oldTargets.contains(element)) { MemberTypeInformation callee = diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart index 5292a0854f8..e1e898d4894 100644 --- a/pkg/compiler/lib/src/js_backend/backend.dart +++ b/pkg/compiler/lib/src/js_backend/backend.dart @@ -337,74 +337,6 @@ class JavaScriptBackend extends Backend { static const bool TRACE_CALLS = TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; - TypeMask get stringType => compiler.closedWorld.commonMasks.stringType; - TypeMask get doubleType => compiler.closedWorld.commonMasks.doubleType; - TypeMask get intType => compiler.closedWorld.commonMasks.intType; - TypeMask get uint32Type => compiler.closedWorld.commonMasks.uint32Type; - TypeMask get uint31Type => compiler.closedWorld.commonMasks.uint31Type; - TypeMask get positiveIntType => - compiler.closedWorld.commonMasks.positiveIntType; - TypeMask get numType => compiler.closedWorld.commonMasks.numType; - TypeMask get boolType => compiler.closedWorld.commonMasks.boolType; - TypeMask get dynamicType => compiler.closedWorld.commonMasks.dynamicType; - TypeMask get nullType => compiler.closedWorld.commonMasks.nullType; - TypeMask get emptyType => const TypeMask.nonNullEmpty(); - TypeMask get nonNullType => compiler.closedWorld.commonMasks.nonNullType; - - TypeMask _indexablePrimitiveTypeCache; - TypeMask get indexablePrimitiveType { - if (_indexablePrimitiveTypeCache == null) { - _indexablePrimitiveTypeCache = new TypeMask.nonNullSubtype( - helpers.jsIndexableClass, compiler.closedWorld); - } - return _indexablePrimitiveTypeCache; - } - - TypeMask _readableArrayTypeCache; - TypeMask get readableArrayType { - if (_readableArrayTypeCache == null) { - _readableArrayTypeCache = new TypeMask.nonNullSubclass( - helpers.jsArrayClass, compiler.closedWorld); - } - return _readableArrayTypeCache; - } - - TypeMask _mutableArrayTypeCache; - TypeMask get mutableArrayType { - if (_mutableArrayTypeCache == null) { - _mutableArrayTypeCache = new TypeMask.nonNullSubclass( - helpers.jsMutableArrayClass, compiler.closedWorld); - } - return _mutableArrayTypeCache; - } - - TypeMask _fixedArrayTypeCache; - TypeMask get fixedArrayType { - if (_fixedArrayTypeCache == null) { - _fixedArrayTypeCache = new TypeMask.nonNullExact( - helpers.jsFixedArrayClass, compiler.closedWorld); - } - return _fixedArrayTypeCache; - } - - TypeMask _extendableArrayTypeCache; - TypeMask get extendableArrayType { - if (_extendableArrayTypeCache == null) { - _extendableArrayTypeCache = new TypeMask.nonNullExact( - helpers.jsExtendableArrayClass, compiler.closedWorld); - } - return _extendableArrayTypeCache; - } - - TypeMask _unmodifiableArrayTypeCache; - TypeMask get unmodifiableArrayType { - if (_unmodifiableArrayTypeCache == null) { - _unmodifiableArrayTypeCache = new TypeMask.nonNullExact( - helpers.jsUnmodifiableArrayClass, compiler.closedWorld); - } - return _fixedArrayTypeCache; - } - /// Maps special classes to their implementation (JSXxx) class. Map implementationClasses; @@ -1487,14 +1419,6 @@ class JavaScriptBackend extends Backend { bool isComplexNoSuchMethod(FunctionElement element) => noSuchMethodRegistry.isComplex(element); - bool isDefaultEqualityImplementation(Element element) { - assert(element.name == '=='); - ClassElement classElement = element.enclosingClass; - return classElement == coreClasses.objectClass || - classElement == helpers.jsInterceptorClass || - classElement == helpers.jsNullClass; - } - bool methodNeedsRti(FunctionElement function) { return rti.methodsNeedingRti.contains(function) || hasRuntimeTypeSupport; } @@ -2099,7 +2023,7 @@ class JavaScriptBackend extends Backend { * be visible by reflection unless some other interfaces makes them * accessible. */ - computeMembersNeededForReflection() { + void computeMembersNeededForReflection() { if (_membersNeededForReflection != null) return; if (compiler.commonElements.mirrorsLibrary == null) { _membersNeededForReflection = const ImmutableEmptySet(); @@ -3287,6 +3211,7 @@ class JavaScriptBackendClasses implements BackendClasses { ClassElement get numImplementation => helpers.jsNumberClass; ClassElement get stringImplementation => helpers.jsStringClass; ClassElement get listImplementation => helpers.jsArrayClass; + ClassElement get mutableListImplementation => helpers.jsMutableArrayClass; ClassElement get constListImplementation => helpers.jsUnmodifiableArrayClass; ClassElement get fixedListImplementation => helpers.jsFixedArrayClass; ClassElement get growableListImplementation => helpers.jsExtendableArrayClass; @@ -3299,4 +3224,15 @@ class JavaScriptBackendClasses implements BackendClasses { ClassElement get asyncFutureImplementation => helpers.futureImplementation; ClassElement get asyncStarStreamImplementation => helpers.controllerStream; ClassElement get functionImplementation => helpers.coreClasses.functionClass; + ClassElement get indexableImplementation => helpers.jsIndexableClass; + ClassElement get mutableIndexableImplementation => + helpers.jsMutableIndexableClass; + + bool isDefaultEqualityImplementation(Element element) { + assert(element.name == '=='); + ClassElement classElement = element.enclosingClass; + return classElement == helpers.coreClasses.objectClass || + classElement == helpers.jsInterceptorClass || + classElement == helpers.jsNullClass; + } } diff --git a/pkg/compiler/lib/src/native/ssa.dart b/pkg/compiler/lib/src/native/ssa.dart index f3134c37ed3..945995d2f63 100644 --- a/pkg/compiler/lib/src/native/ssa.dart +++ b/pkg/compiler/lib/src/native/ssa.dart @@ -101,7 +101,7 @@ void handleSsaNative(SsaBuilder builder, Expression nativeBody) { // be proportional to the number of native methods, which is bounded // by the dart: libraries. js.js.uncachedExpressionTemplate(nativeMethodCall), - backend.dynamicType, + builder.commonMasks.dynamicType, inputs, effects: new SideEffects())); // TODO(johnniwinther): Provide source information. @@ -122,6 +122,6 @@ void handleSsaNative(SsaBuilder builder, Expression nativeBody) { [], new SideEffects(), null, - backend.dynamicType)); + builder.commonMasks.dynamicType)); } } diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart index aebf9b8ad7b..d630c950d8b 100644 --- a/pkg/compiler/lib/src/ssa/builder.dart +++ b/pkg/compiler/lib/src/ssa/builder.dart @@ -441,8 +441,7 @@ class SsaBuilder extends ast.Visitor message: "Missing selector for inlining of $element.")); if (selector != null) { if (!selector.applies(function)) return false; - if (mask != null && - !mask.canHit(function, selector, compiler.closedWorld)) { + if (mask != null && !mask.canHit(function, selector, closedWorld)) { return false; } } @@ -567,7 +566,7 @@ class SsaBuilder extends ast.Visitor !element.isGenerativeConstructorBody && (mask == null || mask.isNullable)) { addWithPosition( - new HFieldGet(null, providedArguments[0], backend.dynamicType, + new HFieldGet(null, providedArguments[0], commonMasks.dynamicType, isAssignable: false), currentNode); } @@ -685,7 +684,7 @@ class SsaBuilder extends ast.Visitor */ HGraph buildMethod(FunctionElement functionElement) { assert(invariant(functionElement, functionElement.isImplementation)); - graph.calledInLoop = compiler.closedWorld.isCalledInLoop(functionElement); + graph.calledInLoop = closedWorld.isCalledInLoop(functionElement); ast.FunctionExpression function = resolvedAst.node; assert(function != null); assert(elements.getFunctionDefinition(function) != null); @@ -711,7 +710,7 @@ class SsaBuilder extends ast.Visitor visitCondition: () { HParameterValue parameter = parameters.values.first; push(new HIdentity(parameter, graph.addConstantNull(compiler), - null, backend.boolType)); + null, commonMasks.boolType)); }, visitThen: () { closeAndGotoExit(new HReturn( @@ -744,7 +743,7 @@ class SsaBuilder extends ast.Visitor // TODO(sra): Figure out how to keep comment anchored without effects. void addComment(String text) { add(new HForeignCode(js.js.statementTemplateYielding(new js.Comment(text)), - backend.dynamicType, [], + commonMasks.dynamicType, [], isStatement: true)); } @@ -754,7 +753,8 @@ class SsaBuilder extends ast.Visitor HInstruction thisInstruction = localsHandler.readThis(); // Use dynamic type because the type computed by the inferrer is // narrowed to the type annotation. - HInstruction parameter = new HParameterValue(field, backend.dynamicType); + HInstruction parameter = + new HParameterValue(field, commonMasks.dynamicType); // Add the parameter as the last instruction of the entry block. // If the method is intercepted, we want the actual receiver // to be the first parameter. @@ -1284,8 +1284,8 @@ class SsaBuilder extends ast.Visitor }, includeSuperAndInjectedMembers: true); InterfaceType type = classElement.thisType; - TypeMask ssaType = new TypeMask.nonNullExact( - classElement.declaration, compiler.closedWorld); + TypeMask ssaType = + new TypeMask.nonNullExact(classElement.declaration, closedWorld); List instantiatedTypes; addInlinedInstantiation(type); if (!currentInlinedInstantiations.isEmpty) { @@ -1311,7 +1311,7 @@ class SsaBuilder extends ast.Visitor TypeInfoExpressionKind.INSTANCE, classElement.thisType, typeArguments, - backend.dynamicType); + commonMasks.dynamicType); add(typeInfo); constructorArguments.add(typeInfo); } @@ -1331,7 +1331,7 @@ class SsaBuilder extends ast.Visitor // Null guard ensures an error if we are being called from an explicit // 'new' of the constructor instead of via an upgrade. It is optimized out // if there are field initializers. - add(new HFieldGet(null, newObject, backend.dynamicType, + add(new HFieldGet(null, newObject, commonMasks.dynamicType, isAssignable: false)); for (int i = 0; i < fields.length; i++) { add(new HFieldSet(fields[i], newObject, constructorArguments[i])); @@ -1398,9 +1398,8 @@ class SsaBuilder extends ast.Visitor pop(); } else { HInvokeConstructorBody invoke = new HInvokeConstructorBody( - body.declaration, bodyCallInputs, backend.nonNullType); - invoke.sideEffects = - compiler.closedWorld.getSideEffectsOfElement(constructor); + body.declaration, bodyCallInputs, commonMasks.nonNullType); + invoke.sideEffects = closedWorld.getSideEffectsOfElement(constructor); add(invoke); } } @@ -1437,7 +1436,7 @@ class SsaBuilder extends ast.Visitor backend.classNeedsRti(enclosing)) { enclosing.typeVariables.forEach((TypeVariableType typeVariable) { HParameterValue param = - addParameter(typeVariable.element, backend.nonNullType); + addParameter(typeVariable.element, commonMasks.nonNullType); localsHandler.directLocals[ localsHandler.getTypeVariableAsLocal(typeVariable)] = param; }); @@ -1501,7 +1500,7 @@ class SsaBuilder extends ast.Visitor "${n(element)}"; HConstant nameConstant = addConstantString(name); add(new HInvokeStatic(backend.helpers.traceHelper, - [nameConstant], backend.dynamicType)); + [nameConstant], commonMasks.dynamicType)); } } @@ -1512,7 +1511,7 @@ class SsaBuilder extends ast.Visitor HConstant idConstant = graph.addConstantInt(element.hashCode, compiler); HConstant nameConstant = addConstantString(element.name); add(new HInvokeStatic(backend.helpers.traceHelper, - [idConstant, nameConstant], backend.dynamicType)); + [idConstant, nameConstant], commonMasks.dynamicType)); } } @@ -1558,7 +1557,7 @@ class SsaBuilder extends ast.Visitor value, compiler.coreTypes.boolType, kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); } - HInstruction result = new HBoolify(value, backend.boolType); + HInstruction result = new HBoolify(value, commonMasks.boolType); add(result); return result; } @@ -1871,8 +1870,7 @@ class SsaBuilder extends ast.Visitor capturedVariables.add(localsHandler.readLocal(capturedLocal)); }); - TypeMask type = - new TypeMask.nonNullExact(closureClassElement, compiler.closedWorld); + TypeMask type = new TypeMask.nonNullExact(closureClassElement, closedWorld); push(new HCreate(closureClassElement, capturedVariables, type) ..sourceInformation = sourceInformationBuilder.buildCreate(node)); @@ -1976,7 +1974,7 @@ class SsaBuilder extends ast.Visitor visit(expression); SourceInformation sourceInformation = sourceInformationBuilder.buildGeneric(node); - push(new HNot(popBoolified(), backend.boolType) + push(new HNot(popBoolified(), commonMasks.boolType) ..sourceInformation = sourceInformation); } @@ -2021,7 +2019,8 @@ class SsaBuilder extends ast.Visitor @override void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) { handleBinary(node, left, right); - pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); + pushWithPosition( + new HNot(popBoolified(), commonMasks.boolType), node.selector); } void handleBinary(ast.Send node, ast.Node left, ast.Node right) { @@ -2137,8 +2136,7 @@ class SsaBuilder extends ast.Visitor // handler in the case of lists, because the constant handler // does not look at elements in the list. TypeMask type = TypeMaskFactory.inferredTypeForElement(field, compiler); - if (!type.containsAll(compiler.closedWorld) && - !instruction.isConstantNull()) { + if (!type.containsAll(closedWorld) && !instruction.isConstantNull()) { // TODO(13429): The inferrer should know that an element // cannot be null. instruction.instructionType = type.nonNullable(); @@ -2202,7 +2200,7 @@ class SsaBuilder extends ast.Visitor // creating an [HStatic]. SourceInformation sourceInformation = sourceInformationBuilder.buildGet(node); - push(new HStatic(method, backend.nonNullType) + push(new HStatic(method, commonMasks.nonNullType) ..sourceInformation = sourceInformation); } @@ -2376,13 +2374,14 @@ class SsaBuilder extends ast.Visitor } HInstruction invokeInterceptor(HInstruction receiver) { - HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); + HInterceptor interceptor = + new HInterceptor(receiver, commonMasks.nonNullType); add(interceptor); return interceptor; } HLiteralList buildLiteralList(List inputs) { - return new HLiteralList(inputs, backend.extendableArrayType); + return new HLiteralList(inputs, commonMasks.extendableArrayType); } @override @@ -2417,7 +2416,7 @@ class SsaBuilder extends ast.Visitor HInstruction expressionInstruction = visitAndPop(expression); HInstruction instruction = buildIsNode(node, type, expressionInstruction); add(instruction); - push(new HNot(instruction, backend.boolType)); + push(new HNot(instruction, commonMasks.boolType)); } HInstruction buildIsNode( @@ -2435,7 +2434,7 @@ class SsaBuilder extends ast.Visitor } generateTypeError(node, message); HInstruction call = pop(); - return new HIs.compound(type, expression, call, backend.boolType); + return new HIs.compound(type, expression, call, commonMasks.boolType); } else if (type.isFunctionType) { List arguments = [buildFunctionType(type), expression]; pushInvokeDynamic( @@ -2444,15 +2443,15 @@ class SsaBuilder extends ast.Visitor CallStructure.ONE_ARG), null, arguments); - return new HIs.compound(type, expression, pop(), backend.boolType); + return new HIs.compound(type, expression, pop(), commonMasks.boolType); } else if (type.isTypeVariable) { HInstruction runtimeType = typeBuilder.addTypeVariableReference(type, sourceElement); Element helper = helpers.checkSubtypeOfRuntimeType; List inputs = [expression, runtimeType]; - pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); + pushInvokeStatic(null, helper, inputs, typeMask: commonMasks.boolType); HInstruction call = pop(); - return new HIs.variable(type, expression, call, backend.boolType); + return new HIs.variable(type, expression, call, commonMasks.boolType); } else if (RuntimeTypes.hasTypeArguments(type)) { ClassElement element = type.element; Element helper = helpers.checkSubtype; @@ -2461,8 +2460,7 @@ class SsaBuilder extends ast.Visitor add(representations); js.Name operator = backend.namer.operatorIs(element); HInstruction isFieldName = addConstantStringFromName(operator); - HInstruction asFieldName = compiler.closedWorld - .hasAnyStrictSubtype(element) + HInstruction asFieldName = closedWorld.hasAnyStrictSubtype(element) ? addConstantStringFromName(backend.namer.substitutionName(element)) : graph.addConstantNull(compiler); List inputs = [ @@ -2471,17 +2469,17 @@ class SsaBuilder extends ast.Visitor representations, asFieldName ]; - pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); + pushInvokeStatic(node, helper, inputs, typeMask: commonMasks.boolType); HInstruction call = pop(); - return new HIs.compound(type, expression, call, backend.boolType); + return new HIs.compound(type, expression, call, commonMasks.boolType); } else { if (backend.hasDirectCheckFor(type)) { - return new HIs.direct(type, expression, backend.boolType); + return new HIs.direct(type, expression, commonMasks.boolType); } // The interceptor is not always needed. It is removed by optimization // when the receiver type or tested type permit. - return new HIs.raw( - type, expression, invokeInterceptor(expression), backend.boolType); + return new HIs.raw(type, expression, invokeInterceptor(expression), + commonMasks.boolType); } } @@ -2698,7 +2696,7 @@ class SsaBuilder extends ast.Visitor if (inputs.length != 2) { reporter.internalError(node.argumentsNode, 'Two arguments expected.'); } - push(new HStringConcat(inputs[0], inputs[1], backend.stringType)); + push(new HStringConcat(inputs[0], inputs[1], commonMasks.stringType)); } void handleForeignJsCurrentIsolateContext(ast.Send node) { @@ -2712,7 +2710,7 @@ class SsaBuilder extends ast.Visitor // to fetch the static state. String name = backend.namer.staticStateHolder; push(new HForeignCode( - js.js.parseForeignJS(name), backend.dynamicType, [], + js.js.parseForeignJS(name), commonMasks.dynamicType, [], nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); } else { // Call a helper method from the isolate library. The isolate @@ -2722,7 +2720,7 @@ class SsaBuilder extends ast.Visitor if (element == null) { reporter.internalError(node, 'Isolate library and compiler mismatch.'); } - pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); + pushInvokeStatic(null, element, [], typeMask: commonMasks.dynamicType); } } @@ -2908,7 +2906,7 @@ class SsaBuilder extends ast.Visitor // closure. visit(link.tail.head); push(new HInvokeClosure(new Selector.callClosure(0), - [pop()], backend.dynamicType)); + [pop()], commonMasks.dynamicType)); } else { // Call a helper method from the isolate library. Element element = helpers.callInIsolate; @@ -2917,7 +2915,8 @@ class SsaBuilder extends ast.Visitor } List inputs = []; addGenericSendArgumentsToList(link, inputs); - pushInvokeStatic(node, element, inputs, typeMask: backend.dynamicType); + pushInvokeStatic(node, element, inputs, + typeMask: commonMasks.dynamicType); } } @@ -2947,7 +2946,7 @@ class SsaBuilder extends ast.Visitor push(new HForeignCode( js.js.expressionTemplateYielding( backend.emitter.staticFunctionAccess(function)), - backend.dynamicType, + commonMasks.dynamicType, [], nativeBehavior: native.NativeBehavior.PURE)); return params; @@ -2970,7 +2969,7 @@ class SsaBuilder extends ast.Visitor SideEffects sideEffects = new SideEffects.empty(); sideEffects.setAllSideEffects(); push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"), - backend.dynamicType, [pop()], + commonMasks.dynamicType, [pop()], nativeBehavior: native.NativeBehavior.CHANGES_OTHER, effects: sideEffects)); } @@ -2980,7 +2979,7 @@ class SsaBuilder extends ast.Visitor reporter.internalError(node.argumentsNode, 'Too many arguments.'); } push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder), - backend.dynamicType, [], + commonMasks.dynamicType, [], nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); } @@ -3030,7 +3029,7 @@ class SsaBuilder extends ast.Visitor var inputs = [ graph.addConstantString(new ast.DartString.literal(loadId), compiler) ]; - push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, + push(new HInvokeStatic(loadFunction, inputs, commonMasks.nonNullType, targetCanThrow: false)..sourceInformation = sourceInformation); } @@ -3085,7 +3084,7 @@ class SsaBuilder extends ast.Visitor argumentsInstruction, argumentNamesInstruction ], - typeMask: backend.dynamicType); + typeMask: commonMasks.dynamicType); var inputs = [pop()]; push(buildInvokeSuper(Selectors.noSuchMethod_, element, inputs)); @@ -3233,7 +3232,8 @@ class SsaBuilder extends ast.Visitor void visitSuperNotEquals( ast.Send node, MethodElement method, ast.Node argument, _) { handleSuperMethodInvoke(node, method); - pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); + pushWithPosition( + new HNot(popBoolified(), commonMasks.boolType), node.selector); } @override @@ -3262,11 +3262,9 @@ class SsaBuilder extends ast.Visitor } bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { - ClosedWorld closedWorld = compiler.closedWorld; if (closedWorld.isUsedAsMixin(cls)) return true; - return compiler.closedWorld.anyStrictSubclassOf(cls, - (ClassElement subclass) { + return closedWorld.anyStrictSubclassOf(cls, (ClassElement subclass) { return !rti.isTrivialSubstitution(subclass, cls); }); } @@ -3292,7 +3290,7 @@ class SsaBuilder extends ast.Visitor Element typeInfoSetterElement = helpers.setRuntimeTypeInfo; pushInvokeStatic( null, typeInfoSetterElement, [newObject, typeInfo], - typeMask: backend.dynamicType, + typeMask: commonMasks.dynamicType, sourceInformation: newObject.sourceInformation); // The new object will now be referenced through the @@ -3324,13 +3322,13 @@ class SsaBuilder extends ast.Visitor originalElement, send, compiler)) { isFixedList = true; TypeMask inferred = _inferredTypeOfNewList(send); - return inferred.containsAll(compiler.closedWorld) - ? backend.fixedArrayType + return inferred.containsAll(closedWorld) + ? commonMasks.fixedArrayType : inferred; } else if (isGrowableListConstructorCall) { TypeMask inferred = _inferredTypeOfNewList(send); - return inferred.containsAll(compiler.closedWorld) - ? backend.extendableArrayType + return inferred.containsAll(closedWorld) + ? commonMasks.extendableArrayType : inferred; } else if (Elements.isConstructorOfTypedArraySubclass( originalElement, compiler)) { @@ -3338,9 +3336,8 @@ class SsaBuilder extends ast.Visitor TypeMask inferred = _inferredTypeOfNewList(send); ClassElement cls = element.enclosingClass; assert(backend.isNative(cls.thisType.element)); - return inferred.containsAll(compiler.closedWorld) - ? new TypeMask.nonNullExact( - cls.thisType.element, compiler.closedWorld) + return inferred.containsAll(closedWorld) + ? new TypeMask.nonNullExact(cls.thisType.element, closedWorld) : inferred; } else if (element.isGenerativeConstructor) { ClassElement cls = element.enclosingClass; @@ -3348,8 +3345,7 @@ class SsaBuilder extends ast.Visitor // An error will be thrown. return new TypeMask.nonNullEmpty(); } else { - return new TypeMask.nonNullExact( - cls.thisType.element, compiler.closedWorld); + return new TypeMask.nonNullExact(cls.thisType.element, closedWorld); } } else { return TypeMaskFactory.inferredReturnTypeForElement( @@ -3427,7 +3423,7 @@ class SsaBuilder extends ast.Visitor return; } - var inputs = []; + List inputs = []; if (constructor.isGenerativeConstructor && backend.isNativeOrExtendsNative(constructor.enclosingClass) && !backend.isJsInterop(constructor)) { @@ -3439,9 +3435,12 @@ class SsaBuilder extends ast.Visitor TypeMask elementType = computeType(constructor); if (isFixedListConstructorCall) { - if (!inputs[0].isNumber(compiler)) { - HTypeConversion conversion = new HTypeConversion(null, - HTypeConversion.ARGUMENT_TYPE_CHECK, backend.numType, inputs[0]); + if (!inputs[0].isNumber(closedWorld)) { + HTypeConversion conversion = new HTypeConversion( + null, + HTypeConversion.ARGUMENT_TYPE_CHECK, + commonMasks.numType, + inputs[0]); add(conversion); inputs[0] = conversion; } @@ -3453,7 +3452,7 @@ class SsaBuilder extends ast.Visitor // TODO(sra): Array allocation should be an instruction so that canThrow // can depend on a length type discovered in optimization. bool canThrow = true; - if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) { + if (inputs[0].isInteger(closedWorld) && inputs[0] is HConstant) { var constant = inputs[0]; int value = constant.constant.primitiveValue; if (0 <= value && value < 0x100000000) canThrow = false; @@ -3468,7 +3467,7 @@ class SsaBuilder extends ast.Visitor js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); // We set the instruction as [canThrow] to avoid it being dead code. // We need a finer grained side effect. - add(new HForeignCode(code, backend.nullType, [stack.last], + add(new HForeignCode(code, commonMasks.nullType, [stack.last], throwBehavior: native.NativeThrowBehavior.MAY)); } } else if (isGrowableListConstructorCall) { @@ -3593,7 +3592,8 @@ class SsaBuilder extends ast.Visitor if (function == compiler.commonElements.identicalFunction) { pushWithPosition( - new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); + new HIdentity(inputs[0], inputs[1], null, commonMasks.boolType), + node); return; } else { pushInvokeStatic(node, function, inputs, @@ -3798,7 +3798,7 @@ class SsaBuilder extends ast.Visitor HInstruction value = typeBuilder.analyzeTypeArgument(type, sourceElement, sourceInformation: sourceInformationBuilder.buildGet(node)); pushInvokeStatic(node, helpers.runtimeTypeToString, [value], - typeMask: backend.stringType); + typeMask: commonMasks.stringType); pushInvokeStatic(node, helpers.createRuntimeType, [pop()]); } } @@ -3821,7 +3821,7 @@ class SsaBuilder extends ast.Visitor List inputs = [target]; addDynamicSendArgumentsToList(node, inputs); push(new HInvokeClosure( - new Selector.callClosureFrom(selector), inputs, backend.dynamicType) + new Selector.callClosureFrom(selector), inputs, commonMasks.dynamicType) ..sourceInformation = sourceInformation); } @@ -3970,11 +3970,10 @@ class SsaBuilder extends ast.Visitor bool isOptimizableOperationOnIndexable(Selector selector, Element element) { bool isLength = selector.isGetter && selector.name == "length"; if (isLength || selector.isIndex) { - return compiler.closedWorld.isSubtypeOf( + return closedWorld.isSubtypeOf( element.enclosingClass.declaration, helpers.jsIndexableClass); } else if (selector.isIndexSet) { - return compiler.closedWorld.isSubtypeOf( - element.enclosingClass.declaration, + return closedWorld.isSubtypeOf(element.enclosingClass.declaration, helpers.jsMutableIndexableClass); } else { return false; @@ -3997,7 +3996,7 @@ class SsaBuilder extends ast.Visitor return false; } - Element element = compiler.closedWorld.locateSingleElement(selector, mask); + Element element = closedWorld.locateSingleElement(selector, mask); if (element != null && !element.isField && !(element.isGetter && selector.isCall) && @@ -4067,14 +4066,14 @@ class SsaBuilder extends ast.Visitor nativeBehavior.typesReturned.add(constructor.enclosingClass.thisType); } return new HForeignCode( - codeTemplate, backend.dynamicType, filteredArguments, + codeTemplate, commonMasks.dynamicType, filteredArguments, nativeBehavior: nativeBehavior) ..sourceInformation = sourceInformation; } var target = new HForeignCode( js.js.parseForeignJS("${backend.namer.fixedBackendPath(element)}." "${backend.nativeData.getFixedBackendName(element)}"), - backend.dynamicType, + commonMasks.dynamicType, []); add(target); // Strip off trailing arguments that were not specified. @@ -4125,7 +4124,7 @@ class SsaBuilder extends ast.Visitor js.Template codeTemplate = js.js.parseForeignJS(code); nativeBehavior.codeTemplate = codeTemplate; - return new HForeignCode(codeTemplate, backend.dynamicType, inputs, + return new HForeignCode(codeTemplate, commonMasks.dynamicType, inputs, nativeBehavior: nativeBehavior)..sourceInformation = sourceInformation; } @@ -4145,7 +4144,7 @@ class SsaBuilder extends ast.Visitor typeMask = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); } - bool targetCanThrow = !compiler.closedWorld.getCannotThrow(element); + bool targetCanThrow = !closedWorld.getCannotThrow(element); // TODO(5346): Try to avoid the need for calling [declaration] before var instruction; if (backend.isJsInterop(element)) { @@ -4160,8 +4159,7 @@ class SsaBuilder extends ast.Visitor instruction.instantiatedTypes = new List.from(currentInlinedInstantiations); } - instruction.sideEffects = - compiler.closedWorld.getSideEffectsOfElement(element); + instruction.sideEffects = closedWorld.getSideEffectsOfElement(element); } if (location == null) { push(instruction); @@ -4195,7 +4193,7 @@ class SsaBuilder extends ast.Visitor selector, inputs, type, sourceInformation, isSetter: selector.isSetter || selector.isIndexSet); instruction.sideEffects = - compiler.closedWorld.getSideEffectsOfSelector(selector, null); + closedWorld.getSideEffectsOfSelector(selector, null); return instruction; } @@ -5199,8 +5197,8 @@ class SsaBuilder extends ast.Visitor visit(node.expression); HInstruction awaited = pop(); // TODO(herhut): Improve this type. - push(new HAwait(awaited, - new TypeMask.subclass(coreClasses.objectClass, compiler.closedWorld))); + push(new HAwait( + awaited, new TypeMask.subclass(coreClasses.objectClass, closedWorld))); } visitTypeAnnotation(ast.TypeAnnotation node) { @@ -5259,15 +5257,14 @@ class SsaBuilder extends ast.Visitor } TypeMask type = _inferredTypeOfNewList(node); - if (!type.containsAll(compiler.closedWorld)) { + if (!type.containsAll(closedWorld)) { instruction.instructionType = type; } stack.add(instruction); } _inferredTypeOfNewList(ast.Node node) => - _resultOf(sourceElement).typeOfNewList(node) ?? - compiler.closedWorld.commonMasks.dynamicType; + _resultOf(sourceElement).typeOfNewList(node) ?? commonMasks.dynamicType; visitConditional(ast.Conditional node) { SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); @@ -5366,9 +5363,7 @@ class SsaBuilder extends ast.Visitor pushInvokeDynamic(node, selector, mask, [streamIterator]); HInstruction future = pop(); push(new HAwait( - future, - new TypeMask.subclass( - coreClasses.objectClass, compiler.closedWorld))); + future, new TypeMask.subclass(coreClasses.objectClass, closedWorld))); return popBoolified(); } @@ -5404,9 +5399,7 @@ class SsaBuilder extends ast.Visitor }, () { pushInvokeDynamic(node, Selectors.cancel, null, [streamIterator]); push(new HAwait( - pop(), - new TypeMask.subclass( - coreClasses.objectClass, compiler.closedWorld))); + pop(), new TypeMask.subclass(coreClasses.objectClass, closedWorld))); pop(); }); } @@ -5424,7 +5417,6 @@ class SsaBuilder extends ast.Visitor TypeMask mask = elementInferenceResults.typeOfIterator(node); - ClosedWorld closedWorld = compiler.closedWorld; if (mask != null && mask.satisfies(helpers.jsIndexableClass, closedWorld) && // String is indexable but not iterable. @@ -5503,7 +5495,7 @@ class SsaBuilder extends ast.Visitor // } Element loopVariable = elements.getForInVariable(node); SyntheticLocal indexVariable = new SyntheticLocal('_i', loopVariable); - TypeMask boolType = backend.boolType; + TypeMask boolType = commonMasks.boolType; // These variables are shared by initializer, condition, body and update. HInstruction array; // Set in buildInitializer. @@ -5513,7 +5505,7 @@ class SsaBuilder extends ast.Visitor HInstruction buildGetLength() { MemberElement lengthElement = helpers.jsIndexableLength; HFieldGet result = new HFieldGet( - lengthElement, array, backend.positiveIntType, + lengthElement, array, commonMasks.positiveIntType, isAssignable: !isFixed); add(result); return result; @@ -5584,7 +5576,7 @@ class SsaBuilder extends ast.Visitor HInstruction index = localsHandler.readLocal(indexVariable); HInstruction one = graph.addConstantInt(1, compiler); HInstruction addInstruction = - new HAdd(index, one, null, backend.positiveIntType); + new HAdd(index, one, null, commonMasks.positiveIntType); add(addInstruction); localsHandler.updateLocal(indexVariable, addInstruction); } @@ -5705,12 +5697,12 @@ class SsaBuilder extends ast.Visitor // The instruction type will always be a subtype of the mapLiteralClass, but // type inference might discover a more specific type, or find nothing (in // dart2js unit tests). - TypeMask mapType = new TypeMask.nonNullSubtype( - helpers.mapLiteralClass, compiler.closedWorld); + TypeMask mapType = + new TypeMask.nonNullSubtype(helpers.mapLiteralClass, closedWorld); TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement(constructor, compiler); TypeMask instructionType = - mapType.intersection(returnTypeMask, compiler.closedWorld); + mapType.intersection(returnTypeMask, closedWorld); addInlinedInstantiation(expectedType); pushInvokeStatic(node, constructor, inputs, @@ -5946,7 +5938,7 @@ class SsaBuilder extends ast.Visitor void buildCondition() { js.Template code = js.js.parseForeignJS('#'); push(new HForeignCode( - code, backend.boolType, [localsHandler.readLocal(switchTarget)], + code, commonMasks.boolType, [localsHandler.readLocal(switchTarget)], nativeBehavior: native.NativeBehavior.PURE)); } @@ -6228,7 +6220,7 @@ class SsaBuilder extends ast.Visitor // Note that the name of this local is irrelevant. SyntheticLocal local = new SyntheticLocal('exception', localsHandler.executableContext); - exception = new HLocalValue(local, backend.nonNullType); + exception = new HLocalValue(local, commonMasks.nonNullType); add(exception); HInstruction oldRethrowableException = rethrowableException; rethrowableException = exception; @@ -6538,7 +6530,7 @@ class StringBuilderVisitor extends ast.Visitor { // conversions. // 2. The value can be primitive, because the library stringifier has // fast-path code for most primitives. - if (expression.canBePrimitive(compiler)) { + if (expression.canBePrimitive(builder.closedWorld)) { append(stringify(node, expression)); return; } @@ -6548,7 +6540,7 @@ class StringBuilderVisitor extends ast.Visitor { Selector selector = Selectors.toString_; TypeMask type = TypeMaskFactory.inferredTypeForSelector( selector, expression.instructionType, compiler); - if (type.containsOnlyString(compiler.closedWorld)) { + if (type.containsOnlyString(builder.closedWorld)) { builder.pushInvokeDynamic(node, selector, expression.instructionType, [expression]); append(builder.pop()); @@ -6581,14 +6573,14 @@ class StringBuilderVisitor extends ast.Visitor { HInstruction concat(HInstruction left, HInstruction right) { HInstruction instruction = - new HStringConcat(left, right, builder.backend.stringType); + new HStringConcat(left, right, builder.commonMasks.stringType); builder.add(instruction); return instruction; } HInstruction stringify(ast.Node node, HInstruction expression) { HInstruction instruction = - new HStringify(expression, builder.backend.stringType); + new HStringify(expression, builder.commonMasks.stringType); builder.add(instruction); return instruction; } diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart index f53eddf9aac..f3e651b44c2 100644 --- a/pkg/compiler/lib/src/ssa/builder_kernel.dart +++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart @@ -32,6 +32,7 @@ import '../universe/call_structure.dart' show CallStructure; import '../universe/selector.dart'; import '../universe/use.dart' show StaticUse, TypeUse; import '../universe/side_effects.dart' show SideEffects; +import '../world.dart' show ClosedWorld; import 'graph_builder.dart'; import 'kernel_ast_adapter.dart'; import 'kernel_string_builder.dart'; @@ -207,7 +208,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { value, compiler.coreTypes.boolType, kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); } - HInstruction result = new HBoolify(value, backend.boolType); + HInstruction result = new HBoolify(value, commonMasks.boolType); add(result); return result; } @@ -244,8 +245,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { astAdapter.getClass(constructor.enclosingClass), constructorArguments, new TypeMask.nonNullExact( - astAdapter.getClass(constructor.enclosingClass), - compiler.closedWorld), + astAdapter.getClass(constructor.enclosingClass), closedWorld), instantiatedTypes: [ astAdapter.getClass(constructor.enclosingClass).thisType ], @@ -426,8 +426,8 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { /// Pushes a boolean checking [expression] against null. pushCheckNull(HInstruction expression) { - push(new HIdentity( - expression, graph.addConstantNull(compiler), null, backend.boolType)); + push(new HIdentity(expression, graph.addConstantNull(compiler), null, + commonMasks.boolType)); } @override @@ -447,7 +447,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { HInstruction errorMessage = graph.addConstantString(new DartString.literal(message), compiler); HInstruction trap = new HForeignCode(js.js.parseForeignJS("#.#"), - backend.dynamicType, [nullValue, errorMessage]); + commonMasks.dynamicType, [nullValue, errorMessage]); trap.sideEffects ..setAllSideEffects() ..setDependsOnSomething(); @@ -590,7 +590,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { HInstruction buildGetLength() { HFieldGet result = new HFieldGet( - astAdapter.jsIndexableLength, array, backend.positiveIntType, + astAdapter.jsIndexableLength, array, commonMasks.positiveIntType, isAssignable: !isFixed); add(result); return result; @@ -604,7 +604,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { // array.length == _end || throwConcurrentModificationError(array) // HInstruction length = buildGetLength(); - push(new HIdentity(length, originalLength, null, backend.boolType)); + push(new HIdentity(length, originalLength, null, commonMasks.boolType)); _pushStaticInvocation( astAdapter.checkConcurrentModificationError, [pop(), array], @@ -624,7 +624,8 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { HInstruction buildCondition() { HInstruction index = localsHandler.readLocal(indexVariable); HInstruction length = buildGetLength(); - HInstruction compare = new HLess(index, length, null, backend.boolType); + HInstruction compare = + new HLess(index, length, null, commonMasks.boolType); add(compare); return compare; } @@ -663,7 +664,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { HInstruction index = localsHandler.readLocal(indexVariable); HInstruction one = graph.addConstantInt(1, compiler); HInstruction addInstruction = - new HAdd(index, one, null, backend.positiveIntType); + new HAdd(index, one, null, commonMasks.positiveIntType); add(addInstruction); localsHandler.updateLocal(indexVariable, addInstruction); } @@ -718,7 +719,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { ir.Procedure typeInfoSetterFn = astAdapter.setRuntimeTypeInfo; // TODO(efortuna): Insert source information in this static invocation. _pushStaticInvocation(typeInfoSetterFn, [newObject, typeInfo], - backend.dynamicType); + commonMasks.dynamicType); // The new object will now be referenced through the // `setRuntimeTypeInfo` call. We therefore set the type of that @@ -895,14 +896,15 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { element.accept(this); elements.add(pop()); } - listInstruction = new HLiteralList(elements, backend.extendableArrayType); + listInstruction = + new HLiteralList(elements, commonMasks.extendableArrayType); add(listInstruction); listInstruction = setListRuntimeTypeInfoIfNeeded(listInstruction, listLiteral); } TypeMask type = astAdapter.typeOfListLiteral(targetElement, listLiteral); - if (!type.containsAll(compiler.closedWorld)) { + if (!type.containsAll(closedWorld)) { listInstruction.instructionType = type; } stack.add(listInstruction); @@ -932,7 +934,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { } else { constructor = astAdapter.mapLiteralConstructor; HLiteralList argList = - new HLiteralList(constructorArgs, backend.extendableArrayType); + new HLiteralList(constructorArgs, commonMasks.extendableArrayType); add(argList); inputs.add(argList); } @@ -973,12 +975,11 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { // type inference might discover a more specific type, or find nothing (in // dart2js unit tests). TypeMask mapType = new TypeMask.nonNullSubtype( - astAdapter.getElement(astAdapter.mapLiteralClass), - compiler.closedWorld); + astAdapter.getElement(astAdapter.mapLiteralClass), closedWorld); TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( astAdapter.getElement(constructor), compiler); TypeMask instructionType = - mapType.intersection(returnTypeMask, compiler.closedWorld); + mapType.intersection(returnTypeMask, closedWorld); addImplicitInstantiation(type); _pushStaticInvocation(constructor, inputs, instructionType); @@ -1009,7 +1010,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { dartType, sourceElement, sourceInformation: null); _pushStaticInvocation(astAdapter.runtimeTypeToString, - [value], backend.stringType); + [value], commonMasks.stringType); _pushStaticInvocation(astAdapter.createRuntimeType, [pop()], astAdapter.createRuntimeTypeReturnType); return; @@ -1374,7 +1375,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { // to fetch the static state. String name = backend.namer.staticStateHolder; push(new HForeignCode( - js.js.parseForeignJS(name), backend.dynamicType, [], + js.js.parseForeignJS(name), commonMasks.dynamicType, [], nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); } else { // Call a helper method from the isolate library. The isolate library uses @@ -1385,7 +1386,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { compiler.reporter.internalError(astAdapter.getNode(invocation), 'Isolate library and compiler mismatch.'); } - _pushStaticInvocation(target, [], backend.dynamicType); + _pushStaticInvocation(target, [], commonMasks.dynamicType); } } @@ -1401,7 +1402,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { // If the isolate library is not used, we ignore the isolate argument and // just invoke the closure. push(new HInvokeClosure(new Selector.callClosure(0), - [inputs[1]], backend.dynamicType)); + [inputs[1]], commonMasks.dynamicType)); } else { // Call a helper method from the isolate library. ir.Procedure callInIsolate = astAdapter.callInIsolate; @@ -1409,7 +1410,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { compiler.reporter.internalError(astAdapter.getNode(invocation), 'Isolate library and compiler mismatch.'); } - _pushStaticInvocation(callInIsolate, inputs, backend.dynamicType); + _pushStaticInvocation(callInIsolate, inputs, commonMasks.dynamicType); } } @@ -1443,7 +1444,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { push(new HForeignCode( js.js.expressionTemplateYielding(backend.emitter .staticFunctionAccess(astAdapter.getMember(staticTarget))), - backend.dynamicType, + commonMasks.dynamicType, [], nativeBehavior: native.NativeBehavior.PURE)); return; @@ -1470,8 +1471,8 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { String isolateName = backend.namer.staticStateHolder; SideEffects sideEffects = new SideEffects.empty(); sideEffects.setAllSideEffects(); - push(new HForeignCode( - js.js.parseForeignJS("$isolateName = #"), backend.dynamicType, inputs, + push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"), + commonMasks.dynamicType, inputs, nativeBehavior: native.NativeBehavior.CHANGES_OTHER, effects: sideEffects)); } @@ -1483,7 +1484,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { } push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder), - backend.dynamicType, [], + commonMasks.dynamicType, [], nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); } @@ -1670,7 +1671,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { return; } List inputs = _visitPositionalArguments(invocation.arguments); - push(new HStringConcat(inputs[0], inputs[1], backend.stringType)); + push(new HStringConcat(inputs[0], inputs[1], commonMasks.stringType)); } void _pushStaticInvocation( @@ -1736,8 +1737,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { capturedVariables.add(localsHandler.readLocal(capturedLocal)); }); - TypeMask type = - new TypeMask.nonNullExact(closureClassElement, compiler.closedWorld); + TypeMask type = new TypeMask.nonNullExact(closureClassElement, closedWorld); // TODO(efortuna): Add source information here. push(new HCreate(closureClassElement, capturedVariables, type)); @@ -1798,7 +1798,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { HInterceptor _interceptorFor(HInstruction intercepted) { HInterceptor interceptor = - new HInterceptor(intercepted, backend.nonNullType); + new HInterceptor(intercepted, commonMasks.nonNullType); add(interceptor); return interceptor; } @@ -1835,7 +1835,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { null, isSetter: selector.isSetter || selector.isIndexSet); instruction.sideEffects = - compiler.closedWorld.getSideEffectsOfSelector(selector, null); + closedWorld.getSideEffectsOfSelector(selector, null); push(instruction); } @@ -1846,7 +1846,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { List arguments = _visitArgumentsForStaticTarget(target.function, invocation.arguments); TypeMask typeMask = new TypeMask.nonNullExact( - astAdapter.getElement(target.enclosingClass), compiler.closedWorld); + astAdapter.getElement(target.enclosingClass), closedWorld); _pushStaticInvocation(target, arguments, typeMask); } @@ -1868,17 +1868,17 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { if (type is MalformedType) { ErroneousElement element = type.element; generateTypeError(isExpression, element.message); - push(new HIs.compound(type, expression, pop(), backend.boolType)); + push(new HIs.compound(type, expression, pop(), commonMasks.boolType)); return; } if (type.isFunctionType) { List arguments = [buildFunctionType(type), expression]; - _pushDynamicInvocation(isExpression, backend.boolType, arguments, + _pushDynamicInvocation(isExpression, commonMasks.boolType, arguments, selector: new Selector.call( new PrivateName('_isTest', astAdapter.jsHelperLibrary), CallStructure.ONE_ARG)); - push(new HIs.compound(type, expression, pop(), backend.boolType)); + push(new HIs.compound(type, expression, pop(), commonMasks.boolType)); return; } @@ -1886,22 +1886,22 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { HInstruction runtimeType = typeBuilder.addTypeVariableReference(type, sourceElement); _pushStaticInvocation(astAdapter.checkSubtypeOfRuntimeType, - [expression, runtimeType], backend.boolType); - push(new HIs.variable(type, expression, pop(), backend.boolType)); + [expression, runtimeType], commonMasks.boolType); + push(new HIs.variable(type, expression, pop(), commonMasks.boolType)); return; } // TODO(sra): Type with type parameters. if (backend.hasDirectCheckFor(type)) { - push(new HIs.direct(type, expression, backend.boolType)); + push(new HIs.direct(type, expression, commonMasks.boolType)); return; } // The interceptor is not always needed. It is removed by optimization // when the receiver type or tested type permit. HInterceptor interceptor = _interceptorFor(expression); - push(new HIs.raw(type, expression, interceptor, backend.boolType)); + push(new HIs.raw(type, expression, interceptor, commonMasks.boolType)); } @override @@ -1931,7 +1931,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { @override void visitNot(ir.Not not) { not.operand.accept(this); - push(new HNot(popBoolified(), backend.boolType)); + push(new HNot(popBoolified(), commonMasks.boolType)); } @override diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart index cd9d7c099fe..83a0f7f3370 100644 --- a/pkg/compiler/lib/src/ssa/codegen.dart +++ b/pkg/compiler/lib/src/ssa/codegen.dart @@ -179,6 +179,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { Compiler get compiler => backend.compiler; + ClosedWorld get closedWorld => compiler.closedWorld; + NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; CodegenRegistry get registry => work.registry; @@ -261,8 +263,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { return MAX; } - bool requiresUintConversion(instruction) { - if (instruction.isUInt31(compiler)) return false; + bool requiresUintConversion(HInstruction instruction) { + if (instruction.isUInt31(closedWorld)) return false; if (bitWidth(instruction) <= 31) return false; // If the result of a bit-operation is only used by other bit // operations, we do not have to convert to an unsigned integer. @@ -1381,11 +1383,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>'); visitTruncatingDivide(HTruncatingDivide node) { - assert(node.isUInt31(compiler)); + assert(node.isUInt31(closedWorld)); // TODO(karlklose): Enable this assertion again when type propagation is // fixed. Issue 23555. // assert(node.left.isUInt32(compiler)); - assert(node.right.isPositiveInteger(compiler)); + assert(node.right.isPositiveInteger(closedWorld)); use(node.left); js.Expression jsLeft = pop(); use(node.right); @@ -1709,22 +1711,20 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { // type because our optimizations might end up in a state where the // invoke dynamic knows more than the receiver. ClassElement enclosing = node.element.enclosingClass; - if (compiler.closedWorld.isInstantiated(enclosing)) { - return new TypeMask.nonNullExact( - enclosing.declaration, compiler.closedWorld); + if (closedWorld.isInstantiated(enclosing)) { + return new TypeMask.nonNullExact(enclosing.declaration, closedWorld); } else { // The element is mixed in so a non-null subtype mask is the most // precise we have. - assert(invariant(node, compiler.closedWorld.isUsedAsMixin(enclosing), + assert(invariant(node, closedWorld.isUsedAsMixin(enclosing), message: "Element ${node.element} from $enclosing expected " "to be mixed in.")); - return new TypeMask.nonNullSubtype( - enclosing.declaration, compiler.closedWorld); + return new TypeMask.nonNullSubtype(enclosing.declaration, closedWorld); } } // If [JSInvocationMirror._invokeOn] is enabled, and this call // might hit a `noSuchMethod`, we register an untyped selector. - return compiler.closedWorld.extendMaskIfReachesAll(selector, mask); + return closedWorld.extendMaskIfReachesAll(selector, mask); } void registerMethodInvoke(HInvokeDynamic node) { @@ -2098,13 +2098,14 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { HInstruction left = relational.left; HInstruction right = relational.right; - if (left.isStringOrNull(compiler) && right.isStringOrNull(compiler)) { + if (left.isStringOrNull(closedWorld) && + right.isStringOrNull(closedWorld)) { return true; } // This optimization doesn't work for NaN, so we only do it if the // type is known to be an integer. - return left.isInteger(compiler) && right.isInteger(compiler); + return left.isInteger(closedWorld) && right.isInteger(closedWorld); } bool handledBySpecialCase = false; @@ -2240,13 +2241,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { js.Expression over; if (node.staticChecks != HBoundsCheck.ALWAYS_ABOVE_ZERO) { use(node.index); - if (node.index.isInteger(compiler)) { + if (node.index.isInteger(closedWorld)) { under = js.js("# < 0", pop()); } else { js.Expression jsIndex = pop(); under = js.js("# >>> 0 !== #", [jsIndex, jsIndex]); } - } else if (!node.index.isInteger(compiler)) { + } else if (!node.index.isInteger(closedWorld)) { checkInt(node.index, '!=='); under = pop(); } @@ -2376,9 +2377,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { void visitStringify(HStringify node) { HInstruction input = node.inputs.first; - if (input.isString(compiler)) { + if (input.isString(closedWorld)) { use(input); - } else if (input.isInteger(compiler) || input.isBoolean(compiler)) { + } else if (input.isInteger(closedWorld) || input.isBoolean(closedWorld)) { // JavaScript's + operator with a string for the left operand will convert // the right operand to a string, and the conversion result is correct. use(input); @@ -2761,8 +2762,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { } else if (type.isFunctionType) { checkType(input, interceptor, type, sourceInformation, negative: negative); - } else if ((input.canBePrimitive(compiler) && - !input.canBePrimitiveArray(compiler)) || + } else if ((input.canBePrimitive(closedWorld) && + !input.canBePrimitiveArray(closedWorld)) || input.canBeNull()) { checkObject(input, relation, node.sourceInformation); js.Expression objectTest = pop(); @@ -2787,14 +2788,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { js.Expression generateReceiverOrArgumentTypeTest( HInstruction input, TypeMask checkedType) { - ClosedWorld closedWorld = compiler.closedWorld; TypeMask inputType = input.instructionType; // Figure out if it is beneficial to turn this into a null check. // V8 generally prefers 'typeof' checks, but for integers and // indexable primitives we cannot compile this test into a single // typeof check so the null check is cheaper. bool isIntCheck = checkedType.containsOnlyInt(closedWorld); - bool turnIntoNumCheck = isIntCheck && input.isIntegerOrNull(compiler); + bool turnIntoNumCheck = isIntCheck && input.isIntegerOrNull(closedWorld); bool turnIntoNullCheck = !turnIntoNumCheck && (checkedType.nullable() == inputType) && (isIntCheck || @@ -2827,12 +2827,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { void visitTypeConversion(HTypeConversion node) { if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { - ClosedWorld closedWorld = compiler.closedWorld; // An int check if the input is not int or null, is not // sufficient for doing an argument or receiver check. assert(compiler.options.trustTypeAnnotations || !node.checkedType.containsOnlyInt(closedWorld) || - node.checkedInput.isIntegerOrNull(compiler)); + node.checkedInput.isIntegerOrNull(closedWorld)); js.Expression test = generateReceiverOrArgumentTypeTest( node.checkedInput, node.checkedType); js.Block oldContainer = currentContainer; @@ -3010,7 +3009,6 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { bool typeVariableAccessNeedsSubstitution( TypeVariableElement element, TypeMask receiverMask) { ClassElement cls = element.enclosingClass; - ClosedWorld closedWorld = compiler.closedWorld; // See if the receiver type narrows the set of classes to ones that can be // indexed. diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart index 34d156b2928..04fdb11aac3 100644 --- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart +++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart @@ -8,6 +8,7 @@ import '../elements/elements.dart'; import '../js_backend/js_backend.dart'; import '../types/types.dart'; import '../universe/selector.dart' show Selector; +import '../world.dart' show ClosedWorld; import 'nodes.dart'; /** @@ -22,6 +23,8 @@ class SsaInstructionSelection extends HBaseVisitor { JavaScriptBackend get backend => compiler.backend; + ClosedWorld get closedWorld => compiler.closedWorld; + void visitGraph(HGraph graph) { this.graph = graph; visitDominatorTree(graph); @@ -67,7 +70,7 @@ class SsaInstructionSelection extends HBaseVisitor { HInstruction interceptor = node.interceptor; if (interceptor != null) { return new HIsViaInterceptor( - node.typeExpression, interceptor, backend.boolType); + node.typeExpression, interceptor, closedWorld.commonMasks.boolType); } } return node; @@ -86,7 +89,7 @@ class SsaInstructionSelection extends HBaseVisitor { if (leftType.isNullable && rightType.isNullable) { if (left.isConstantNull() || right.isConstantNull() || - (left.isPrimitive(compiler) && leftType == rightType)) { + (left.isPrimitive(closedWorld) && leftType == rightType)) { return '=='; } return null; @@ -242,7 +245,7 @@ class SsaInstructionSelection extends HBaseVisitor { HInstruction bitop(String assignOp) { // HBitAnd, HBitOr etc. are more difficult because HBitAnd(a.x, y) // sometimes needs to be forced to unsigned: a.x = (a.x & y) >>> 0. - if (op.isUInt31(compiler)) return simpleBinary(assignOp); + if (op.isUInt31(closedWorld)) return simpleBinary(assignOp); return noMatchingRead(); } diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart index e5dce33ba56..c35e34fb48e 100644 --- a/pkg/compiler/lib/src/ssa/graph_builder.dart +++ b/pkg/compiler/lib/src/ssa/graph_builder.dart @@ -42,6 +42,10 @@ abstract class GraphBuilder { CodegenRegistry get registry; + ClosedWorld get closedWorld => compiler.closedWorld; + + CommonMasks get commonMasks => closedWorld.commonMasks; + /// Used to track the locals while building the graph. LocalsHandler localsHandler; @@ -75,8 +79,8 @@ abstract class GraphBuilder { /// Pushes a boolean checking [expression] against null. pushCheckNull(HInstruction expression) { - push(new HIdentity( - expression, graph.addConstantNull(compiler), null, backend.boolType)); + push(new HIdentity(expression, graph.addConstantNull(compiler), null, + closedWorld.commonMasks.boolType)); } void dup() { @@ -225,7 +229,7 @@ abstract class GraphBuilder { TypeInfoExpressionKind.INSTANCE, (type.element as ClassElement).thisType, rtiInputs, - backend.dynamicType); + closedWorld.commonMasks.dynamicType); add(typeInfo); return callSetRuntimeTypeInfo(typeInfo, newObject); } diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart index 1716c7f9d20..d35ee860e53 100644 --- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart +++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart @@ -97,7 +97,7 @@ class SsaSimplifyInterceptors extends HBaseVisitor bool canUseSelfForInterceptor( HInstruction receiver, Set interceptedClasses) { - if (receiver.canBePrimitive(compiler)) { + if (receiver.canBePrimitive(closedWorld)) { // Primitives always need interceptors. return false; } @@ -312,9 +312,9 @@ class SsaSimplifyInterceptors extends HBaseVisitor if (receiver.canBeNull()) { if (!interceptedClasses.contains(helpers.jsNullClass)) { // Can use `(receiver && C)` only if receiver is either null or truthy. - if (!(receiver.canBePrimitiveNumber(compiler) || - receiver.canBePrimitiveBoolean(compiler) || - receiver.canBePrimitiveString(compiler))) { + if (!(receiver.canBePrimitiveNumber(closedWorld) || + receiver.canBePrimitiveBoolean(closedWorld) || + receiver.canBePrimitiveString(closedWorld))) { ClassElement interceptorClass = tryComputeConstantInterceptorFromType( receiver.instructionType.nonNullable(), interceptedClasses); if (interceptorClass != null) { diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart index 63e3a26aa37..e4137488cbe 100644 --- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart +++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart @@ -24,13 +24,13 @@ class InvokeDynamicSpecializer { const InvokeDynamicSpecializer(); TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { return TypeMaskFactory.inferredTypeForSelector( instruction.selector, instruction.mask, compiler); } HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { return null; } @@ -85,9 +85,9 @@ class IndexAssignSpecializer extends InvokeDynamicSpecializer { const IndexAssignSpecializer(); HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { - if (instruction.inputs[1].isMutableIndexable(compiler)) { - if (!instruction.inputs[2].isInteger(compiler) && + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + if (instruction.inputs[1].isMutableIndexable(closedWorld)) { + if (!instruction.inputs[2].isInteger(closedWorld) && compiler.options.enableTypeAssertions) { // We want the right checked mode error. return null; @@ -103,9 +103,9 @@ class IndexSpecializer extends InvokeDynamicSpecializer { const IndexSpecializer(); HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { - if (!instruction.inputs[1].isIndexablePrimitive(compiler)) return null; - if (!instruction.inputs[2].isInteger(compiler) && + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + if (!instruction.inputs[1].isIndexablePrimitive(closedWorld)) return null; + if (!instruction.inputs[2].isInteger(closedWorld) && compiler.options.enableTypeAssertions) { // We want the right checked mode error. return null; @@ -127,22 +127,21 @@ class BitNotSpecializer extends InvokeDynamicSpecializer { } TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { // All bitwise operations on primitive types either produce an // integer or throw an error. - JavaScriptBackend backend = compiler.backend; - if (instruction.inputs[1].isPrimitiveOrNull(compiler)) { - return backend.uint32Type; + if (instruction.inputs[1].isPrimitiveOrNull(closedWorld)) { + return closedWorld.commonMasks.uint32Type; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction input = instruction.inputs[1]; - if (input.isNumber(compiler)) { + if (input.isNumber(closedWorld)) { return new HBitNot(input, instruction.selector, - computeTypeFromInputTypes(instruction, compiler)); + computeTypeFromInputTypes(instruction, compiler, closedWorld)); } return null; } @@ -156,16 +155,16 @@ class UnaryNegateSpecializer extends InvokeDynamicSpecializer { } TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { TypeMask operandType = instruction.inputs[1].instructionType; - if (instruction.inputs[1].isNumberOrNull(compiler)) return operandType; - return super.computeTypeFromInputTypes(instruction, compiler); + if (instruction.inputs[1].isNumberOrNull(closedWorld)) return operandType; + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction input = instruction.inputs[1]; - if (input.isNumber(compiler)) { + if (input.isNumber(closedWorld)) { return new HNegate(input, instruction.selector, input.instructionType); } return null; @@ -176,31 +175,33 @@ abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { const BinaryArithmeticSpecializer(); TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; - JavaScriptBackend backend = compiler.backend; - if (left.isIntegerOrNull(compiler) && right.isIntegerOrNull(compiler)) { - return backend.intType; + if (left.isIntegerOrNull(closedWorld) && + right.isIntegerOrNull(closedWorld)) { + return closedWorld.commonMasks.intType; } - if (left.isNumberOrNull(compiler)) { - if (left.isDoubleOrNull(compiler) || right.isDoubleOrNull(compiler)) { - return backend.doubleType; + if (left.isNumberOrNull(closedWorld)) { + if (left.isDoubleOrNull(closedWorld) || + right.isDoubleOrNull(closedWorld)) { + return closedWorld.commonMasks.doubleType; } - return backend.numType; + return closedWorld.commonMasks.numType; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } - bool isBuiltin(HInvokeDynamic instruction, Compiler compiler) { - return instruction.inputs[1].isNumber(compiler) && - instruction.inputs[2].isNumber(compiler); + bool isBuiltin(HInvokeDynamic instruction, ClosedWorld closedWorld) { + return instruction.inputs[1].isNumber(closedWorld) && + instruction.inputs[2].isNumber(closedWorld); } HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { - if (isBuiltin(instruction, compiler)) { - HInstruction builtin = newBuiltinVariant(instruction, compiler); + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + if (isBuiltin(instruction, closedWorld)) { + HInstruction builtin = + newBuiltinVariant(instruction, compiler, closedWorld); if (builtin != null) return builtin; // Even if there is no builtin equivalent instruction, we know // the instruction does not have any side effect, and that it @@ -210,20 +211,22 @@ abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { return null; } - bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) { + bool inputsArePositiveIntegers( + HInstruction instruction, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; - return left.isPositiveIntegerOrNull(compiler) && - right.isPositiveIntegerOrNull(compiler); + return left.isPositiveIntegerOrNull(closedWorld) && + right.isPositiveIntegerOrNull(closedWorld); } - bool inputsAreUInt31(HInstruction instruction, Compiler compiler) { + bool inputsAreUInt31(HInstruction instruction, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; - return left.isUInt31(compiler) && right.isUInt31(compiler); + return left.isUInt31(closedWorld) && right.isUInt31(closedWorld); } - HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); + HInstruction newBuiltinVariant( + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld); Selector renameToOptimizedSelector( String name, Selector selector, Compiler compiler) { @@ -239,16 +242,14 @@ class AddSpecializer extends BinaryArithmeticSpecializer { const AddSpecializer(); TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { - if (inputsAreUInt31(instruction, compiler)) { - JavaScriptBackend backend = compiler.backend; - return backend.uint32Type; + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + if (inputsAreUInt31(instruction, closedWorld)) { + return closedWorld.commonMasks.uint32Type; } - if (inputsArePositiveIntegers(instruction, compiler)) { - JavaScriptBackend backend = compiler.backend; - return backend.positiveIntType; + if (inputsArePositiveIntegers(instruction, closedWorld)) { + return closedWorld.commonMasks.positiveIntType; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } BinaryOperation operation(ConstantSystem constantSystem) { @@ -256,9 +257,12 @@ class AddSpecializer extends BinaryArithmeticSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - return new HAdd(instruction.inputs[1], instruction.inputs[2], - instruction.selector, computeTypeFromInputTypes(instruction, compiler)); + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + return new HAdd( + instruction.inputs[1], + instruction.inputs[2], + instruction.selector, + computeTypeFromInputTypes(instruction, compiler, closedWorld)); } } @@ -270,20 +274,18 @@ class DivideSpecializer extends BinaryArithmeticSpecializer { } TypeMask computeTypeFromInputTypes( - HInstruction instruction, Compiler compiler) { + HInstruction instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; - JavaScriptBackend backend = compiler.backend; - if (left.isNumberOrNull(compiler)) { - return backend.doubleType; + if (left.isNumberOrNull(closedWorld)) { + return closedWorld.commonMasks.doubleType; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - JavaScriptBackend backend = compiler.backend; + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { return new HDivide(instruction.inputs[1], instruction.inputs[2], - instruction.selector, backend.doubleType); + instruction.selector, closedWorld.commonMasks.doubleType); } } @@ -291,12 +293,11 @@ class ModuloSpecializer extends BinaryArithmeticSpecializer { const ModuloSpecializer(); TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { - if (inputsArePositiveIntegers(instruction, compiler)) { - JavaScriptBackend backend = compiler.backend; - return backend.positiveIntType; + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + if (inputsArePositiveIntegers(instruction, closedWorld)) { + return closedWorld.commonMasks.positiveIntType; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } BinaryOperation operation(ConstantSystem constantSystem) { @@ -304,7 +305,7 @@ class ModuloSpecializer extends BinaryArithmeticSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { // Modulo cannot be mapped to the native operator (different semantics). // TODO(sra): For non-negative values we can use JavaScript's %. return null; @@ -319,18 +320,20 @@ class MultiplySpecializer extends BinaryArithmeticSpecializer { } TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { - if (inputsArePositiveIntegers(instruction, compiler)) { - JavaScriptBackend backend = compiler.backend; - return backend.positiveIntType; + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + if (inputsArePositiveIntegers(instruction, closedWorld)) { + return closedWorld.commonMasks.positiveIntType; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - return new HMultiply(instruction.inputs[1], instruction.inputs[2], - instruction.selector, computeTypeFromInputTypes(instruction, compiler)); + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + return new HMultiply( + instruction.inputs[1], + instruction.inputs[2], + instruction.selector, + computeTypeFromInputTypes(instruction, compiler, closedWorld)); } } @@ -342,9 +345,12 @@ class SubtractSpecializer extends BinaryArithmeticSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - return new HSubtract(instruction.inputs[1], instruction.inputs[2], - instruction.selector, computeTypeFromInputTypes(instruction, compiler)); + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + return new HSubtract( + instruction.inputs[1], + instruction.inputs[2], + instruction.selector, + computeTypeFromInputTypes(instruction, compiler, closedWorld)); } } @@ -356,18 +362,17 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { } TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { - JavaScriptBackend backend = compiler.backend; - if (hasUint31Result(instruction, compiler)) { - return backend.uint31Type; + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + if (hasUint31Result(instruction, closedWorld)) { + return closedWorld.commonMasks.uint31Type; } - if (inputsArePositiveIntegers(instruction, compiler)) { - return backend.positiveIntType; + if (inputsArePositiveIntegers(instruction, closedWorld)) { + return closedWorld.commonMasks.positiveIntType; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } - bool isNotZero(HInstruction instruction, Compiler compiler) { + bool isNotZero(HInstruction instruction) { if (!instruction.isConstantInteger()) return false; HConstant rightConstant = instruction; IntConstantValue intConstant = rightConstant.constant; @@ -375,7 +380,7 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { return count != 0; } - bool isTwoOrGreater(HInstruction instruction, Compiler compiler) { + bool isTwoOrGreater(HInstruction instruction) { if (!instruction.isConstantInteger()) return false; HConstant rightConstant = instruction; IntConstantValue intConstant = rightConstant.constant; @@ -383,14 +388,14 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { return count >= 2; } - bool hasUint31Result(HInstruction instruction, Compiler compiler) { + bool hasUint31Result(HInstruction instruction, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; - if (right.isPositiveInteger(compiler)) { - if (left.isUInt31(compiler) && isNotZero(right, compiler)) { + if (right.isPositiveInteger(closedWorld)) { + if (left.isUInt31(closedWorld) && isNotZero(right)) { return true; } - if (left.isUInt32(compiler) && isTwoOrGreater(right, compiler)) { + if (left.isUInt32(closedWorld) && isTwoOrGreater(right)) { return true; } } @@ -398,12 +403,12 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { } HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction right = instruction.inputs[2]; - if (isBuiltin(instruction, compiler)) { - if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) { - if (hasUint31Result(instruction, compiler)) { - return newBuiltinVariant(instruction, compiler); + if (isBuiltin(instruction, closedWorld)) { + if (right.isPositiveInteger(closedWorld) && isNotZero(right)) { + if (hasUint31Result(instruction, closedWorld)) { + return newBuiltinVariant(instruction, compiler, closedWorld); } // We can call _tdivFast because the rhs is a 32bit integer // and not 0, nor -1. @@ -416,9 +421,12 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - return new HTruncatingDivide(instruction.inputs[1], instruction.inputs[2], - instruction.selector, computeTypeFromInputTypes(instruction, compiler)); + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + return new HTruncatingDivide( + instruction.inputs[1], + instruction.inputs[2], + instruction.selector, + computeTypeFromInputTypes(instruction, compiler, closedWorld)); } } @@ -426,15 +434,14 @@ abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { const BinaryBitOpSpecializer(); TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { // All bitwise operations on primitive types either produce an // integer or throw an error. HInstruction left = instruction.inputs[1]; - JavaScriptBackend backend = compiler.backend; - if (left.isPrimitiveOrNull(compiler)) { - return backend.uint32Type; + if (left.isPrimitiveOrNull(closedWorld)) { + return closedWorld.commonMasks.uint32Type; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } bool argumentLessThan32(HInstruction instruction) { @@ -445,10 +452,10 @@ abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { return count >= 0 && count <= 31; } - bool isPositive(HInstruction instruction, Compiler compiler) { + bool isPositive(HInstruction instruction, ClosedWorld closedWorld) { // TODO: We should use the value range analysis. Currently, ranges // are discarded just after the analysis. - return instruction.isPositiveInteger(compiler); + return instruction.isPositiveInteger(closedWorld); } } @@ -460,18 +467,18 @@ class ShiftLeftSpecializer extends BinaryBitOpSpecializer { } HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; - if (left.isNumber(compiler)) { + if (left.isNumber(closedWorld)) { if (argumentLessThan32(right)) { - return newBuiltinVariant(instruction, compiler); + return newBuiltinVariant(instruction, compiler, closedWorld); } // Even if there is no builtin equivalent instruction, we know // the instruction does not have any side effect, and that it // can be GVN'ed. clearAllSideEffects(instruction); - if (isPositive(right, compiler)) { + if (isPositive(right, closedWorld)) { instruction.selector = renameToOptimizedSelector( '_shlPositive', instruction.selector, compiler); } @@ -480,9 +487,12 @@ class ShiftLeftSpecializer extends BinaryBitOpSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - return new HShiftLeft(instruction.inputs[1], instruction.inputs[2], - instruction.selector, computeTypeFromInputTypes(instruction, compiler)); + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + return new HShiftLeft( + instruction.inputs[1], + instruction.inputs[2], + instruction.selector, + computeTypeFromInputTypes(instruction, compiler, closedWorld)); } } @@ -490,31 +500,31 @@ class ShiftRightSpecializer extends BinaryBitOpSpecializer { const ShiftRightSpecializer(); TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; - if (left.isUInt32(compiler)) return left.instructionType; - return super.computeTypeFromInputTypes(instruction, compiler); + if (left.isUInt32(closedWorld)) return left.instructionType; + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; - if (left.isNumber(compiler)) { - if (argumentLessThan32(right) && isPositive(left, compiler)) { - return newBuiltinVariant(instruction, compiler); + if (left.isNumber(closedWorld)) { + if (argumentLessThan32(right) && isPositive(left, closedWorld)) { + return newBuiltinVariant(instruction, compiler, closedWorld); } // Even if there is no builtin equivalent instruction, we know // the instruction does not have any side effect, and that it // can be GVN'ed. clearAllSideEffects(instruction); - if (isPositive(right, compiler) && isPositive(left, compiler)) { + if (isPositive(right, closedWorld) && isPositive(left, closedWorld)) { instruction.selector = renameToOptimizedSelector( '_shrBothPositive', instruction.selector, compiler); - } else if (isPositive(left, compiler) && right.isNumber(compiler)) { + } else if (isPositive(left, closedWorld) && right.isNumber(closedWorld)) { instruction.selector = renameToOptimizedSelector( '_shrReceiverPositive', instruction.selector, compiler); - } else if (isPositive(right, compiler)) { + } else if (isPositive(right, closedWorld)) { instruction.selector = renameToOptimizedSelector( '_shrOtherPositive', instruction.selector, compiler); } @@ -523,9 +533,12 @@ class ShiftRightSpecializer extends BinaryBitOpSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - return new HShiftRight(instruction.inputs[1], instruction.inputs[2], - instruction.selector, computeTypeFromInputTypes(instruction, compiler)); + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + return new HShiftRight( + instruction.inputs[1], + instruction.inputs[2], + instruction.selector, + computeTypeFromInputTypes(instruction, compiler, closedWorld)); } BinaryOperation operation(ConstantSystem constantSystem) { @@ -541,20 +554,22 @@ class BitOrSpecializer extends BinaryBitOpSpecializer { } TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; - JavaScriptBackend backend = compiler.backend; - if (left.isUInt31(compiler) && right.isUInt31(compiler)) { - return backend.uint31Type; + if (left.isUInt31(closedWorld) && right.isUInt31(closedWorld)) { + return closedWorld.commonMasks.uint31Type; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - return new HBitOr(instruction.inputs[1], instruction.inputs[2], - instruction.selector, computeTypeFromInputTypes(instruction, compiler)); + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + return new HBitOr( + instruction.inputs[1], + instruction.inputs[2], + instruction.selector, + computeTypeFromInputTypes(instruction, compiler, closedWorld)); } } @@ -566,21 +581,23 @@ class BitAndSpecializer extends BinaryBitOpSpecializer { } TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; - JavaScriptBackend backend = compiler.backend; - if (left.isPrimitiveOrNull(compiler) && - (left.isUInt31(compiler) || right.isUInt31(compiler))) { - return backend.uint31Type; + if (left.isPrimitiveOrNull(closedWorld) && + (left.isUInt31(closedWorld) || right.isUInt31(closedWorld))) { + return closedWorld.commonMasks.uint31Type; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - return new HBitAnd(instruction.inputs[1], instruction.inputs[2], - instruction.selector, computeTypeFromInputTypes(instruction, compiler)); + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + return new HBitAnd( + instruction.inputs[1], + instruction.inputs[2], + instruction.selector, + computeTypeFromInputTypes(instruction, compiler, closedWorld)); } } @@ -592,20 +609,22 @@ class BitXorSpecializer extends BinaryBitOpSpecializer { } TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; - JavaScriptBackend backend = compiler.backend; - if (left.isUInt31(compiler) && right.isUInt31(compiler)) { - return backend.uint31Type; + if (left.isUInt31(closedWorld) && right.isUInt31(closedWorld)) { + return closedWorld.commonMasks.uint31Type; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - return new HBitXor(instruction.inputs[1], instruction.inputs[2], - instruction.selector, computeTypeFromInputTypes(instruction, compiler)); + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + return new HBitXor( + instruction.inputs[1], + instruction.inputs[2], + instruction.selector, + computeTypeFromInputTypes(instruction, compiler, closedWorld)); } } @@ -613,47 +632,46 @@ abstract class RelationalSpecializer extends InvokeDynamicSpecializer { const RelationalSpecializer(); TypeMask computeTypeFromInputTypes( - HInvokeDynamic instruction, Compiler compiler) { - JavaScriptBackend backend = compiler.backend; - if (instruction.inputs[1].isPrimitiveOrNull(compiler)) { - return backend.boolType; + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { + if (instruction.inputs[1].isPrimitiveOrNull(closedWorld)) { + return closedWorld.commonMasks.boolType; } - return super.computeTypeFromInputTypes(instruction, compiler); + return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); } HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; - if (left.isNumber(compiler) && right.isNumber(compiler)) { - return newBuiltinVariant(instruction, compiler); + if (left.isNumber(closedWorld) && right.isNumber(closedWorld)) { + return newBuiltinVariant(instruction, closedWorld); } return null; } - HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler); + HInstruction newBuiltinVariant( + HInvokeDynamic instruction, ClosedWorld closedWorld); } class EqualsSpecializer extends RelationalSpecializer { const EqualsSpecializer(); HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction left = instruction.inputs[1]; HInstruction right = instruction.inputs[2]; TypeMask instructionType = left.instructionType; - if (right.isConstantNull() || left.isPrimitiveOrNull(compiler)) { - return newBuiltinVariant(instruction, compiler); + if (right.isConstantNull() || left.isPrimitiveOrNull(closedWorld)) { + return newBuiltinVariant(instruction, closedWorld); } - ClosedWorld world = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; Iterable matches = - world.allFunctions.filter(instruction.selector, instructionType); + closedWorld.allFunctions.filter(instruction.selector, instructionType); // This test relies the on `Object.==` and `Interceptor.==` always being // implemented because if the selector matches by subtype, it still will be // a regular object or an interceptor. - if (matches.every(backend.isDefaultEqualityImplementation)) { - return newBuiltinVariant(instruction, compiler); + if (matches + .every(closedWorld.backendClasses.isDefaultEqualityImplementation)) { + return newBuiltinVariant(instruction, closedWorld); } return null; } @@ -663,10 +681,9 @@ class EqualsSpecializer extends RelationalSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - JavaScriptBackend backend = compiler.backend; + HInvokeDynamic instruction, ClosedWorld closedWorld) { return new HIdentity(instruction.inputs[1], instruction.inputs[2], - instruction.selector, backend.boolType); + instruction.selector, closedWorld.commonMasks.boolType); } } @@ -678,10 +695,9 @@ class LessSpecializer extends RelationalSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - JavaScriptBackend backend = compiler.backend; + HInvokeDynamic instruction, ClosedWorld closedWorld) { return new HLess(instruction.inputs[1], instruction.inputs[2], - instruction.selector, backend.boolType); + instruction.selector, closedWorld.commonMasks.boolType); } } @@ -693,10 +709,9 @@ class GreaterSpecializer extends RelationalSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - JavaScriptBackend backend = compiler.backend; + HInvokeDynamic instruction, ClosedWorld closedWorld) { return new HGreater(instruction.inputs[1], instruction.inputs[2], - instruction.selector, backend.boolType); + instruction.selector, closedWorld.commonMasks.boolType); } } @@ -708,10 +723,9 @@ class GreaterEqualSpecializer extends RelationalSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - JavaScriptBackend backend = compiler.backend; + HInvokeDynamic instruction, ClosedWorld closedWorld) { return new HGreaterEqual(instruction.inputs[1], instruction.inputs[2], - instruction.selector, backend.boolType); + instruction.selector, closedWorld.commonMasks.boolType); } } @@ -723,10 +737,9 @@ class LessEqualSpecializer extends RelationalSpecializer { } HInstruction newBuiltinVariant( - HInvokeDynamic instruction, Compiler compiler) { - JavaScriptBackend backend = compiler.backend; + HInvokeDynamic instruction, ClosedWorld closedWorld) { return new HLessEqual(instruction.inputs[1], instruction.inputs[2], - instruction.selector, backend.boolType); + instruction.selector, closedWorld.commonMasks.boolType); } } @@ -738,11 +751,11 @@ class CodeUnitAtSpecializer extends InvokeDynamicSpecializer { } HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index // bounds checking optimizations as for HIndex. HInstruction receiver = instruction.getDartReceiver(compiler); - if (receiver.isStringOrNull(compiler)) { + if (receiver.isStringOrNull(closedWorld)) { // Even if there is no builtin equivalent instruction, we know // String.codeUnitAt does not have any side effect (other than throwing), // and that it can be GVN'ed. @@ -760,9 +773,9 @@ class RoundSpecializer extends InvokeDynamicSpecializer { } HInstruction tryConvertToBuiltin( - HInvokeDynamic instruction, Compiler compiler) { + HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { HInstruction receiver = instruction.getDartReceiver(compiler); - if (receiver.isNumberOrNull(compiler)) { + if (receiver.isNumberOrNull(closedWorld)) { // Even if there is no builtin equivalent instruction, we know the // instruction does not have any side effect, and that it can be GVN'ed. clearAllSideEffects(instruction); diff --git a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart index bcecfae838c..4c2309efe23 100644 --- a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart +++ b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart @@ -67,6 +67,7 @@ class KernelAstAdapter { TreeElements get elements => _resolvedAst.elements; DiagnosticReporter get reporter => _compiler.reporter; Element get _target => _resolvedAst.element; + ClosedWorld get _closedWorld => _compiler.closedWorld; GlobalTypeInferenceElementResult _resultOf(Element e) => _compiler.globalInference.results.resultOf(e); @@ -127,7 +128,7 @@ class KernelAstAdapter { bool getCanThrow(ir.Node procedure) { FunctionElement function = getElement(procedure); - return !_compiler.closedWorld.getCannotThrow(function); + return !_closedWorld.getCannotThrow(function); } TypeMask returnTypeOf(ir.Member node) { @@ -136,7 +137,7 @@ class KernelAstAdapter { } SideEffects getSideEffects(ir.Node node) { - return _compiler.closedWorld.getSideEffectsOfElement(getElement(node)); + return _closedWorld.getSideEffectsOfElement(getElement(node)); } CallStructure getCallStructure(ir.Arguments arguments) { @@ -214,7 +215,7 @@ class KernelAstAdapter { } TypeMask typeOfSet(ir.PropertySet setter) { - return _compiler.closedWorld.commonMasks.dynamicType; + return _closedWorld.commonMasks.dynamicType; } TypeMask typeOfSend(ir.Expression send) { @@ -226,10 +227,10 @@ class KernelAstAdapter { ast.Node node = getNodeOrNull(listLiteral); if (node == null) { assertNodeIsSynthetic(listLiteral); - return _compiler.closedWorld.commonMasks.growableListType; + return _closedWorld.commonMasks.growableListType; } return _resultOf(owner).typeOfNewList(getNode(listLiteral)) ?? - _compiler.closedWorld.commonMasks.dynamicType; + _closedWorld.commonMasks.dynamicType; } TypeMask typeOfIterator(ir.ForInStatement forInStatement) { @@ -246,24 +247,24 @@ class KernelAstAdapter { bool isJsIndexableIterator(ir.ForInStatement forInStatement) { TypeMask mask = typeOfIterator(forInStatement); - ClosedWorld closedWorld = _compiler.closedWorld; return mask != null && - mask.satisfies(_backend.helpers.jsIndexableClass, closedWorld) && + mask.satisfies(_backend.helpers.jsIndexableClass, _closedWorld) && // String is indexable but not iterable. - !mask.satisfies(_backend.helpers.jsStringClass, closedWorld); + !mask.satisfies(_backend.helpers.jsStringClass, _closedWorld); } bool isFixedLength(TypeMask mask) { - ClosedWorld closedWorld = _compiler.closedWorld; JavaScriptBackend backend = _compiler.backend; if (mask.isContainer && (mask as ContainerTypeMask).length != null) { // A container on which we have inferred the length. return true; } // TODO(sra): Recognize any combination of fixed length indexables. - if (mask.containsOnly(backend.helpers.jsFixedArrayClass) || - mask.containsOnly(backend.helpers.jsUnmodifiableArrayClass) || - mask.containsOnlyString(closedWorld) || + if (mask.containsOnly( + _closedWorld.backendClasses.fixedListImplementation) || + mask.containsOnly( + _closedWorld.backendClasses.constListImplementation) || + mask.containsOnlyString(_closedWorld) || backend.isTypedArray(mask)) { return true; } diff --git a/pkg/compiler/lib/src/ssa/kernel_string_builder.dart b/pkg/compiler/lib/src/ssa/kernel_string_builder.dart index 38a3f639dcc..ddef20aa35b 100644 --- a/pkg/compiler/lib/src/ssa/kernel_string_builder.dart +++ b/pkg/compiler/lib/src/ssa/kernel_string_builder.dart @@ -38,7 +38,7 @@ class KernelStringBuilder extends ir.Visitor { // conversions. // 2. The value can be primitive, because the library stringifier has // fast-path code for most primitives. - if (expression.canBePrimitive(compiler)) { + if (expression.canBePrimitive(builder.closedWorld)) { append(stringify(expression)); return; } @@ -62,14 +62,14 @@ class KernelStringBuilder extends ir.Visitor { HInstruction concat(HInstruction left, HInstruction right) { HInstruction instruction = - new HStringConcat(left, right, builder.backend.stringType); + new HStringConcat(left, right, builder.commonMasks.stringType); builder.add(instruction); return instruction; } HInstruction stringify(HInstruction expression) { HInstruction instruction = - new HStringify(expression, builder.backend.stringType); + new HStringify(expression, builder.commonMasks.stringType); builder.add(instruction); return instruction; } diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart index 0eca03abf41..d6e6745cb56 100644 --- a/pkg/compiler/lib/src/ssa/locals_handler.dart +++ b/pkg/compiler/lib/src/ssa/locals_handler.dart @@ -70,6 +70,10 @@ class LocalsHandler { ? null : instanceType; + ClosedWorld get closedWorld => builder.closedWorld; + + CommonMasks get commonMasks => closedWorld.commonMasks; + /// Substituted type variables occurring in [type] into the context of /// [contextClass]. DartType substInContext(DartType type) { @@ -111,9 +115,8 @@ class LocalsHandler { HInstruction createBox() { // TODO(floitsch): Clean up this hack. Should we create a box-object by // just creating an empty object literal? - JavaScriptBackend backend = _compiler.backend; HInstruction box = new HForeignCode( - js.js.parseForeignJS('{}'), backend.nonNullType, [], + js.js.parseForeignJS('{}'), commonMasks.nonNullType, [], nativeBehavior: native.NativeBehavior.PURE_ALLOCATION); builder.add(box); return box; @@ -131,8 +134,7 @@ class LocalsHandler { if (element != null && element.isGenerativeConstructorBody) { // The box is passed as a parameter to a generative // constructor body. - JavaScriptBackend backend = _compiler.backend; - box = builder.addParameter(scopeData.boxElement, backend.nonNullType); + box = builder.addParameter(scopeData.boxElement, commonMasks.nonNullType); } else { box = createBox(); } @@ -222,7 +224,7 @@ class LocalsHandler { if (closureData.isClosure) { // Inside closure redirect references to itself to [:this:]. HThis thisInstruction = - new HThis(closureData.thisLocal, backend.nonNullType); + new HThis(closureData.thisLocal, commonMasks.nonNullType); builder.graph.thisInstruction = thisInstruction; builder.graph.entry.addAtEntry(thisInstruction); updateLocal(closureData.closureElement, thisInstruction); @@ -267,7 +269,6 @@ class LocalsHandler { new SyntheticLocal('receiver', executableContext); // Unlike `this`, receiver is nullable since direct calls to generative // constructor call the constructor with `null`. - ClosedWorld closedWorld = _compiler.closedWorld; HParameterValue value = new HParameterValue(parameter, new TypeMask.exact(cls, closedWorld)); builder.graph.explicitReceiverParameter = value; @@ -325,7 +326,7 @@ class LocalsHandler { ClosureFieldElement redirect = redirectionMapping[local]; HInstruction receiver = readLocal(closureData.closureElement); TypeMask type = local is BoxLocal - ? (_compiler.backend as JavaScriptBackend).nonNullType + ? commonMasks.nonNullType : getTypeOfCapturedVariable(redirect); HInstruction fieldGet = new HFieldGet(redirect, receiver, type); builder.add(fieldGet); @@ -346,10 +347,7 @@ class LocalsHandler { assert(isUsedInTryOrGenerator(local)); HLocalValue localValue = getLocal(local); HInstruction instruction = new HLocalGet( - local, - localValue, - (_compiler.backend as JavaScriptBackend).dynamicType, - sourceInformation); + local, localValue, commonMasks.dynamicType, sourceInformation); builder.add(instruction); return instruction; } @@ -377,8 +375,7 @@ class LocalsHandler { } return activationVariables.putIfAbsent(local, () { - JavaScriptBackend backend = _compiler.backend; - HLocalValue localValue = new HLocalValue(local, backend.nonNullType) + HLocalValue localValue = new HLocalValue(local, commonMasks.nonNullType) ..sourceInformation = sourceInformation; builder.graph.entry.addAtExit(localValue); return localValue; @@ -489,7 +486,7 @@ class LocalsHandler { // We know 'this' cannot be modified. if (local != closureData.thisLocal) { HPhi phi = - new HPhi.singleInput(local, instruction, backend.dynamicType); + new HPhi.singleInput(local, instruction, commonMasks.dynamicType); loopEntry.addPhi(phi); directLocals[local] = phi; } else { @@ -546,7 +543,6 @@ class LocalsHandler { // variable cannot be alive outside the block. Note: this is only // true for nodes where we do joins. Map joinedLocals = new Map(); - JavaScriptBackend backend = _compiler.backend; otherLocals.directLocals.forEach((Local local, HInstruction instruction) { // We know 'this' cannot be modified. if (local == closureData.thisLocal) { @@ -558,8 +554,8 @@ class LocalsHandler { if (identical(instruction, mine)) { joinedLocals[local] = instruction; } else { - HInstruction phi = new HPhi.manyInputs( - local, [mine, instruction], backend.dynamicType); + HInstruction phi = new HPhi.manyInputs(local, + [mine, instruction], commonMasks.dynamicType); joinBlock.addPhi(phi); joinedLocals[local] = phi; } @@ -579,10 +575,9 @@ class LocalsHandler { if (localsHandlers.length == 1) return localsHandlers[0]; Map joinedLocals = new Map(); HInstruction thisValue = null; - JavaScriptBackend backend = _compiler.backend; directLocals.forEach((Local local, HInstruction instruction) { if (local != closureData.thisLocal) { - HPhi phi = new HPhi.noInputs(local, backend.dynamicType); + HPhi phi = new HPhi.noInputs(local, commonMasks.dynamicType); joinedLocals[local] = phi; joinBlock.addPhi(phi); } else { @@ -625,17 +620,14 @@ class LocalsHandler { if (result == null) { ThisLocal local = closureData.thisLocal; ClassElement cls = local.enclosingClass; - ClosedWorld closedWorld = _compiler.closedWorld; if (closedWorld.isUsedAsMixin(cls)) { // If the enclosing class is used as a mixin, [:this:] can be // of the class that mixins the enclosing class. These two // classes do not have a subclass relationship, so, for // simplicity, we mark the type as an interface type. - result = - new TypeMask.nonNullSubtype(cls.declaration, _compiler.closedWorld); + result = new TypeMask.nonNullSubtype(cls.declaration, closedWorld); } else { - result = new TypeMask.nonNullSubclass( - cls.declaration, _compiler.closedWorld); + result = new TypeMask.nonNullSubclass(cls.declaration, closedWorld); } cachedTypeOfThis = result; } diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart index 712ff298bf4..bbd214ca133 100644 --- a/pkg/compiler/lib/src/ssa/nodes.dart +++ b/pkg/compiler/lib/src/ssa/nodes.dart @@ -4,6 +4,7 @@ import '../closure.dart'; import '../common.dart'; +import '../common/backend_api.dart' show BackendClasses; import '../compiler.dart' show Compiler; import '../constants/constant_system.dart'; import '../constants/values.dart'; @@ -949,203 +950,168 @@ abstract class HInstruction implements Spannable { typeMask.satisfies(cls, closedWorld); } - bool canBePrimitive(Compiler compiler) { - return canBePrimitiveNumber(compiler) || - canBePrimitiveArray(compiler) || - canBePrimitiveBoolean(compiler) || - canBePrimitiveString(compiler) || + bool canBePrimitive(ClosedWorld closedWorld) { + return canBePrimitiveNumber(closedWorld) || + canBePrimitiveArray(closedWorld) || + canBePrimitiveBoolean(closedWorld) || + canBePrimitiveString(closedWorld) || isNull(); } - bool canBePrimitiveNumber(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; + bool canBePrimitiveNumber(ClosedWorld closedWorld) { + BackendClasses backendClasses = closedWorld.backendClasses; // TODO(sra): It should be possible to test only jsDoubleClass and // jsUInt31Class, since all others are superclasses of these two. - return containsType(instructionType, helpers.jsNumberClass, closedWorld) || - containsType(instructionType, helpers.jsIntClass, closedWorld) || + return containsType( + instructionType, backendClasses.numImplementation, closedWorld) || containsType( - instructionType, helpers.jsPositiveIntClass, closedWorld) || - containsType(instructionType, helpers.jsUInt32Class, closedWorld) || - containsType(instructionType, helpers.jsUInt31Class, closedWorld) || - containsType(instructionType, helpers.jsDoubleClass, closedWorld); + instructionType, backendClasses.intImplementation, closedWorld) || + containsType(instructionType, backendClasses.positiveIntImplementation, + closedWorld) || + containsType(instructionType, backendClasses.uint32Implementation, + closedWorld) || + containsType(instructionType, backendClasses.uint31Implementation, + closedWorld) || + containsType( + instructionType, backendClasses.doubleImplementation, closedWorld); } - bool canBePrimitiveBoolean(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; - return containsType(instructionType, helpers.jsBoolClass, closedWorld); + bool canBePrimitiveBoolean(ClosedWorld closedWorld) { + return containsType(instructionType, + closedWorld.backendClasses.boolImplementation, closedWorld); } - bool canBePrimitiveArray(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; - return containsType(instructionType, helpers.jsArrayClass, closedWorld) || - containsType(instructionType, helpers.jsFixedArrayClass, closedWorld) || - containsType( - instructionType, helpers.jsExtendableArrayClass, closedWorld) || - containsType( - instructionType, helpers.jsUnmodifiableArrayClass, closedWorld); + bool canBePrimitiveArray(ClosedWorld closedWorld) { + BackendClasses backendClasses = closedWorld.backendClasses; + return containsType( + instructionType, backendClasses.listImplementation, closedWorld) || + containsType(instructionType, backendClasses.fixedListImplementation, + closedWorld) || + containsType(instructionType, backendClasses.growableListImplementation, + closedWorld) || + containsType(instructionType, backendClasses.constListImplementation, + closedWorld); } - bool isIndexablePrimitive(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; + bool isIndexablePrimitive(ClosedWorld closedWorld) { return instructionType.containsOnlyString(closedWorld) || - isInstanceOf(instructionType, helpers.jsIndexableClass, closedWorld); + isInstanceOf(instructionType, + closedWorld.backendClasses.indexableImplementation, closedWorld); } - bool isFixedArray(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; + bool isFixedArray(ClosedWorld closedWorld) { + BackendClasses backendClasses = closedWorld.backendClasses; // TODO(sra): Recognize the union of these types as well. - return containsOnlyType( - instructionType, helpers.jsFixedArrayClass, closedWorld) || - containsOnlyType( - instructionType, helpers.jsUnmodifiableArrayClass, closedWorld); + return containsOnlyType(instructionType, + backendClasses.fixedListImplementation, closedWorld) || + containsOnlyType(instructionType, + backendClasses.constListImplementation, closedWorld); } - bool isExtendableArray(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; - return containsOnlyType( - instructionType, helpers.jsExtendableArrayClass, closedWorld); + bool isExtendableArray(ClosedWorld closedWorld) { + return containsOnlyType(instructionType, + closedWorld.backendClasses.growableListImplementation, closedWorld); } - bool isMutableArray(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; - return isInstanceOf( - instructionType, helpers.jsMutableArrayClass, closedWorld); + bool isMutableArray(ClosedWorld closedWorld) { + return isInstanceOf(instructionType, + closedWorld.backendClasses.mutableListImplementation, closedWorld); } - bool isReadableArray(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; - return isInstanceOf(instructionType, helpers.jsArrayClass, closedWorld); + bool isReadableArray(ClosedWorld closedWorld) { + return isInstanceOf(instructionType, + closedWorld.backendClasses.listImplementation, closedWorld); } - bool isMutableIndexable(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; - return isInstanceOf( - instructionType, helpers.jsMutableIndexableClass, closedWorld); + bool isMutableIndexable(ClosedWorld closedWorld) { + return isInstanceOf(instructionType, + closedWorld.backendClasses.mutableIndexableImplementation, closedWorld); } - bool isArray(Compiler compiler) => isReadableArray(compiler); + bool isArray(ClosedWorld closedWorld) => isReadableArray(closedWorld); - bool canBePrimitiveString(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; - return containsType(instructionType, helpers.jsStringClass, closedWorld); + bool canBePrimitiveString(ClosedWorld closedWorld) { + return containsType(instructionType, + closedWorld.backendClasses.stringImplementation, closedWorld); } - bool isInteger(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; + bool isInteger(ClosedWorld closedWorld) { return instructionType.containsOnlyInt(closedWorld) && !instructionType.isNullable; } - bool isUInt32(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; + bool isUInt32(ClosedWorld closedWorld) { return !instructionType.isNullable && - isInstanceOf(instructionType, helpers.jsUInt32Class, closedWorld); + isInstanceOf(instructionType, + closedWorld.backendClasses.uint32Implementation, closedWorld); } - bool isUInt31(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; + bool isUInt31(ClosedWorld closedWorld) { return !instructionType.isNullable && - isInstanceOf(instructionType, helpers.jsUInt31Class, closedWorld); + isInstanceOf(instructionType, + closedWorld.backendClasses.uint31Implementation, closedWorld); } - bool isPositiveInteger(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; + bool isPositiveInteger(ClosedWorld closedWorld) { return !instructionType.isNullable && - isInstanceOf(instructionType, helpers.jsPositiveIntClass, closedWorld); + isInstanceOf(instructionType, + closedWorld.backendClasses.positiveIntImplementation, closedWorld); } - bool isPositiveIntegerOrNull(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; - JavaScriptBackend backend = compiler.backend; - BackendHelpers helpers = backend.helpers; - return isInstanceOf( - instructionType, helpers.jsPositiveIntClass, closedWorld); + bool isPositiveIntegerOrNull(ClosedWorld closedWorld) { + return isInstanceOf(instructionType, + closedWorld.backendClasses.positiveIntImplementation, closedWorld); } - bool isIntegerOrNull(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; + bool isIntegerOrNull(ClosedWorld closedWorld) { return instructionType.containsOnlyInt(closedWorld); } - bool isNumber(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; + bool isNumber(ClosedWorld closedWorld) { return instructionType.containsOnlyNum(closedWorld) && !instructionType.isNullable; } - bool isNumberOrNull(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; + bool isNumberOrNull(ClosedWorld closedWorld) { return instructionType.containsOnlyNum(closedWorld); } - bool isDouble(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; + bool isDouble(ClosedWorld closedWorld) { return instructionType.containsOnlyDouble(closedWorld) && !instructionType.isNullable; } - bool isDoubleOrNull(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; + bool isDoubleOrNull(ClosedWorld closedWorld) { return instructionType.containsOnlyDouble(closedWorld); } - bool isBoolean(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; + bool isBoolean(ClosedWorld closedWorld) { return instructionType.containsOnlyBool(closedWorld) && !instructionType.isNullable; } - bool isBooleanOrNull(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; + bool isBooleanOrNull(ClosedWorld closedWorld) { return instructionType.containsOnlyBool(closedWorld); } - bool isString(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; + bool isString(ClosedWorld closedWorld) { return instructionType.containsOnlyString(closedWorld) && !instructionType.isNullable; } - bool isStringOrNull(Compiler compiler) { - ClosedWorld closedWorld = compiler.closedWorld; + bool isStringOrNull(ClosedWorld closedWorld) { return instructionType.containsOnlyString(closedWorld); } - bool isPrimitive(Compiler compiler) { - return (isPrimitiveOrNull(compiler) && !instructionType.isNullable) || + bool isPrimitive(ClosedWorld closedWorld) { + return (isPrimitiveOrNull(closedWorld) && !instructionType.isNullable) || isNull(); } - bool isPrimitiveOrNull(Compiler compiler) { - return isIndexablePrimitive(compiler) || - isNumberOrNull(compiler) || - isBooleanOrNull(compiler) || + bool isPrimitiveOrNull(ClosedWorld closedWorld) { + return isIndexablePrimitive(closedWorld) || + isNumberOrNull(closedWorld) || + isBooleanOrNull(closedWorld) || isNull(); } @@ -1364,7 +1330,7 @@ abstract class HInstruction implements Spannable { return false; } - HInstruction convertType(Compiler compiler, DartType type, int kind) { + HInstruction convertType(ClosedWorld closedWorld, DartType type, int kind) { if (type == null) return this; type = type.unaliased; // Only the builder knows how to create [HTypeConversion] @@ -1374,19 +1340,20 @@ abstract class HInstruction implements Spannable { assert(type.treatAsRaw || type.isFunctionType); if (type.isDynamic) return this; if (type.isObject) return this; - JavaScriptBackend backend = compiler.backend; if (type.isVoid || type.isFunctionType || type.isMalformed) { - return new HTypeConversion(type, kind, backend.dynamicType, this); + return new HTypeConversion( + type, kind, closedWorld.commonMasks.dynamicType, this); } assert(type.isInterfaceType); if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) { // Boolean conversion checks work on non-nullable booleans. - return new HTypeConversion(type, kind, backend.boolType, this); + return new HTypeConversion( + type, kind, closedWorld.commonMasks.boolType, this); } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) { throw 'creating compound check to $type (this = ${this})'; } else { Entity cls = type.element; - TypeMask subtype = new TypeMask.subtype(cls, compiler.closedWorld); + TypeMask subtype = new TypeMask.subtype(cls, closedWorld); return new HTypeConversion(type, kind, subtype, this); } } @@ -1412,8 +1379,8 @@ class HRef extends HInstruction { HInstruction get value => inputs[0]; @override - HInstruction convertType(Compiler compiler, DartType type, int kind) { - HInstruction converted = value.convertType(compiler, type, kind); + HInstruction convertType(ClosedWorld closedWorld, DartType type, int kind) { + HInstruction converted = value.convertType(closedWorld, type, kind); if (converted == value) return this; HTypeConversion conversion = converted; conversion.inputs[0] = this; @@ -2862,7 +2829,7 @@ class HTypeConversion extends HCheck { HInstruction get checkedInput => usesMethodOnType ? inputs[1] : super.checkedInput; - HInstruction convertType(Compiler compiler, DartType type, int kind) { + HInstruction convertType(ClosedWorld closedWorld, DartType type, int kind) { if (typeExpression == type) { // Don't omit a boolean conversion (which doesn't allow `null`) unless // this type conversion is already a boolean conversion. @@ -2870,7 +2837,7 @@ class HTypeConversion extends HCheck { return this; } } - return super.convertType(compiler, type, kind); + return super.convertType(closedWorld, type, kind); } bool get isCheckedModeCheck { diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart index de90a81bf44..c5286677edd 100644 --- a/pkg/compiler/lib/src/ssa/optimize.dart +++ b/pkg/compiler/lib/src/ssa/optimize.dart @@ -40,6 +40,7 @@ class SsaOptimizerTask extends CompilerTask { super(backend.compiler.measurer); String get name => 'SSA optimizer'; Compiler get compiler => backend.compiler; + ClosedWorld get closedWorld => compiler.closedWorld; Map ranges = {}; void optimize(CodegenWorkItem work, HGraph graph) { @@ -59,16 +60,18 @@ class SsaOptimizerTask extends CompilerTask { // Run trivial instruction simplification first to optimize // some patterns useful for type conversion. new SsaInstructionSimplifier(constantSystem, backend, this, registry), - new SsaTypeConversionInserter(compiler), + new SsaTypeConversionInserter(closedWorld), new SsaRedundantPhiEliminator(), new SsaDeadPhiEliminator(), new SsaTypePropagator(compiler), // After type propagation, more instructions can be // simplified. new SsaInstructionSimplifier(constantSystem, backend, this, registry), - new SsaCheckInserter(trustPrimitives, backend, boundsChecked), + new SsaCheckInserter( + trustPrimitives, backend, closedWorld, boundsChecked), new SsaInstructionSimplifier(constantSystem, backend, this, registry), - new SsaCheckInserter(trustPrimitives, backend, boundsChecked), + new SsaCheckInserter( + trustPrimitives, backend, closedWorld, boundsChecked), new SsaTypePropagator(compiler), // Run a dead code eliminator before LICM because dead // interceptors are often in the way of LICM'able instructions. @@ -86,7 +89,8 @@ class SsaOptimizerTask extends CompilerTask { // Previous optimizations may have generated new // opportunities for instruction simplification. new SsaInstructionSimplifier(constantSystem, backend, this, registry), - new SsaCheckInserter(trustPrimitives, backend, boundsChecked), + new SsaCheckInserter( + trustPrimitives, backend, closedWorld, boundsChecked), ]; phases.forEach(runPhase); @@ -105,7 +109,8 @@ class SsaOptimizerTask extends CompilerTask { new SsaCodeMotion(), new SsaValueRangeAnalyzer(compiler, constantSystem, this), new SsaInstructionSimplifier(constantSystem, backend, this, registry), - new SsaCheckInserter(trustPrimitives, backend, boundsChecked), + new SsaCheckInserter( + trustPrimitives, backend, closedWorld, boundsChecked), new SsaSimplifyInterceptors(compiler, constantSystem, work.element), new SsaDeadCodeEliminator(compiler, this), ]; @@ -167,6 +172,8 @@ class SsaInstructionSimplifier extends HBaseVisitor CoreClasses get coreClasses => compiler.coreClasses; + ClosedWorld get closedWorld => compiler.closedWorld; + BackendHelpers get helpers => backend.helpers; void visitGraph(HGraph visitee) { @@ -187,12 +194,12 @@ class SsaInstructionSimplifier extends HBaseVisitor // might be that an operation thought to return double, can be // simplified to an int. For example: // `2.5 * 10`. - if (!(replacement.isNumberOrNull(compiler) && - instruction.isNumberOrNull(compiler))) { + if (!(replacement.isNumberOrNull(closedWorld) && + instruction.isNumberOrNull(closedWorld))) { // If we can replace [instruction] with [replacement], then // [replacement]'s type can be narrowed. TypeMask newType = replacement.instructionType - .intersection(instruction.instructionType, compiler.closedWorld); + .intersection(instruction.instructionType, closedWorld); replacement.instructionType = newType; } @@ -275,7 +282,7 @@ class SsaInstructionSimplifier extends HBaseVisitor List inputs = node.inputs; assert(inputs.length == 1); HInstruction input = inputs[0]; - if (input.isBoolean(compiler)) return input; + if (input.isBoolean(closedWorld)) return input; // If the code is unreachable, remove the HBoolify. This can happen when // there is a throw expression in a short-circuit conditional. Removing the @@ -285,7 +292,7 @@ class SsaInstructionSimplifier extends HBaseVisitor // All values that cannot be 'true' are boolified to false. TypeMask mask = input.instructionType; - if (!mask.contains(helpers.jsBoolClass, compiler.closedWorld)) { + if (!mask.contains(helpers.jsBoolClass, closedWorld)) { return graph.addConstantBool(false, compiler); } return node; @@ -322,7 +329,7 @@ class SsaInstructionSimplifier extends HBaseVisitor HInstruction tryOptimizeLengthInterceptedGetter(HInvokeDynamic node) { HInstruction actualReceiver = node.inputs[1]; - if (actualReceiver.isIndexablePrimitive(compiler)) { + if (actualReceiver.isIndexablePrimitive(closedWorld)) { if (actualReceiver.isConstantString()) { HConstant constantInput = actualReceiver; StringConstantValue constant = constantInput.constant; @@ -335,15 +342,14 @@ class SsaInstructionSimplifier extends HBaseVisitor MemberElement element = helpers.jsIndexableLength; bool isFixed = isFixedLength(actualReceiver.instructionType, compiler); TypeMask actualType = node.instructionType; - ClosedWorld closedWorld = compiler.closedWorld; - TypeMask resultType = backend.positiveIntType; + TypeMask resultType = closedWorld.commonMasks.positiveIntType; // If we already have computed a more specific type, keep that type. if (HInstruction.isInstanceOf( actualType, helpers.jsUInt31Class, closedWorld)) { - resultType = backend.uint31Type; + resultType = closedWorld.commonMasks.uint31Type; } else if (HInstruction.isInstanceOf( actualType, helpers.jsUInt32Class, closedWorld)) { - resultType = backend.uint32Type; + resultType = closedWorld.commonMasks.uint32Type; } HFieldGet result = new HFieldGet(element, actualReceiver, resultType, isAssignable: !isFixed); @@ -368,23 +374,21 @@ class SsaInstructionSimplifier extends HBaseVisitor // Try converting the instruction to a builtin instruction. HInstruction instruction = - node.specializer.tryConvertToBuiltin(node, compiler); + node.specializer.tryConvertToBuiltin(node, compiler, closedWorld); if (instruction != null) return instruction; Selector selector = node.selector; TypeMask mask = node.mask; HInstruction input = node.inputs[1]; - ClosedWorld world = compiler.closedWorld; - bool applies(Element element) { return selector.applies(element) && - (mask == null || mask.canHit(element, selector, world)); + (mask == null || mask.canHit(element, selector, closedWorld)); } if (selector.isCall || selector.isOperator) { MethodElement target; - if (input.isExtendableArray(compiler)) { + if (input.isExtendableArray(closedWorld)) { if (applies(helpers.jsArrayRemoveLast)) { target = helpers.jsArrayRemoveLast; } else if (applies(helpers.jsArrayAdd)) { @@ -394,10 +398,10 @@ class SsaInstructionSimplifier extends HBaseVisitor target = helpers.jsArrayAdd; } } - } else if (input.isStringOrNull(compiler)) { + } else if (input.isStringOrNull(closedWorld)) { if (applies(helpers.jsStringSplit)) { HInstruction argument = node.inputs[2]; - if (argument.isString(compiler)) { + if (argument.isString(closedWorld)) { target = helpers.jsStringSplit; } } else if (applies(helpers.jsStringOperatorAdd)) { @@ -405,7 +409,7 @@ class SsaInstructionSimplifier extends HBaseVisitor // make sure the receiver and the argument are not null. // TODO(sra): Do this via [node.specializer]. HInstruction argument = node.inputs[2]; - if (argument.isString(compiler) && !input.canBeNull()) { + if (argument.isString(closedWorld) && !input.canBeNull()) { return new HStringConcat(input, argument, node.instructionType); } } else if (applies(helpers.jsStringToString) && !input.canBeNull()) { @@ -559,7 +563,7 @@ class SsaInstructionSimplifier extends HBaseVisitor HInstruction visitBoundsCheck(HBoundsCheck node) { HInstruction index = node.index; - if (index.isInteger(compiler)) return node; + if (index.isInteger(closedWorld)) return node; if (index.isConstant()) { HConstant constantInstruction = index; assert(!constantInstruction.constant.isInt); @@ -587,7 +591,7 @@ class SsaInstructionSimplifier extends HBaseVisitor HInstruction right = node.right; // We can only perform this rewriting on Integer, as it is not // valid for -0.0. - if (left.isInteger(compiler) && right.isInteger(compiler)) { + if (left.isInteger(closedWorld) && right.isInteger(closedWorld)) { if (left is HConstant && left.constant.isZero) return right; if (right is HConstant && right.constant.isZero) return left; } @@ -597,7 +601,7 @@ class SsaInstructionSimplifier extends HBaseVisitor HInstruction visitMultiply(HMultiply node) { HInstruction left = node.left; HInstruction right = node.right; - if (left.isNumber(compiler) && right.isNumber(compiler)) { + if (left.isNumber(closedWorld) && right.isNumber(closedWorld)) { if (left is HConstant && left.constant.isOne) return right; if (right is HConstant && right.constant.isOne) return left; } @@ -643,8 +647,9 @@ class SsaInstructionSimplifier extends HBaseVisitor // Intersection of int and double return conflicting, so // we don't optimize on numbers to preserve the runtime semantics. - if (!(left.isNumberOrNull(compiler) && right.isNumberOrNull(compiler))) { - if (leftType.isDisjoint(rightType, compiler.closedWorld)) { + if (!(left.isNumberOrNull(closedWorld) && + right.isNumberOrNull(closedWorld))) { + if (leftType.isDisjoint(rightType, closedWorld)) { return makeFalse(); } } @@ -657,15 +662,15 @@ class SsaInstructionSimplifier extends HBaseVisitor if (constant.constant.isTrue) { return input; } else { - return new HNot(input, backend.boolType); + return new HNot(input, closedWorld.commonMasks.boolType); } } - if (left.isConstantBoolean() && right.isBoolean(compiler)) { + if (left.isConstantBoolean() && right.isBoolean(closedWorld)) { return compareConstant(left, right); } - if (right.isConstantBoolean() && left.isBoolean(compiler)) { + if (right.isConstantBoolean() && left.isBoolean(closedWorld)) { return compareConstant(right, left); } @@ -674,8 +679,8 @@ class SsaInstructionSimplifier extends HBaseVisitor // dart2js runtime has not always been consistent with the Dart // specification (section 16.0.1), which makes distinctions on NaNs and // -0.0 that are hard to implement efficiently. - if (left.isIntegerOrNull(compiler)) return makeTrue(); - if (!left.canBePrimitiveNumber(compiler)) return makeTrue(); + if (left.isIntegerOrNull(closedWorld)) return makeTrue(); + if (!left.canBePrimitiveNumber(closedWorld)) return makeTrue(); } return null; @@ -735,9 +740,8 @@ class SsaInstructionSimplifier extends HBaseVisitor return graph.addConstantBool(true, compiler); } - ClosedWorld closedWorld = compiler.closedWorld; HInstruction expression = node.expression; - if (expression.isInteger(compiler)) { + if (expression.isInteger(closedWorld)) { if (element == coreClasses.intClass || element == coreClasses.numClass || Elements.isNumberOrStringSupertype(element, compiler)) { @@ -749,7 +753,7 @@ class SsaInstructionSimplifier extends HBaseVisitor } else { return graph.addConstantBool(false, compiler); } - } else if (expression.isDouble(compiler)) { + } else if (expression.isDouble(closedWorld)) { if (element == coreClasses.doubleClass || element == coreClasses.numClass || Elements.isNumberOrStringSupertype(element, compiler)) { @@ -762,14 +766,14 @@ class SsaInstructionSimplifier extends HBaseVisitor } else { return graph.addConstantBool(false, compiler); } - } else if (expression.isNumber(compiler)) { + } else if (expression.isNumber(closedWorld)) { if (element == coreClasses.numClass) { return graph.addConstantBool(true, compiler); } else { // We cannot just return false, because the expression may be of // type int or double. } - } else if (expression.canBePrimitiveNumber(compiler) && + } else if (expression.canBePrimitiveNumber(closedWorld) && element == coreClasses.intClass) { // We let the JS semantics decide for that check. return node; @@ -785,7 +789,7 @@ class SsaInstructionSimplifier extends HBaseVisitor : new TypeMask.nonNullSubtype(element, closedWorld); if (expressionMask.union(typeMask, closedWorld) == typeMask) { return graph.addConstantBool(true, compiler); - } else if (expressionMask.isDisjoint(typeMask, compiler.closedWorld)) { + } else if (expressionMask.isDisjoint(typeMask, closedWorld)) { return graph.addConstantBool(false, compiler); } } @@ -830,7 +834,6 @@ class SsaInstructionSimplifier extends HBaseVisitor } HInstruction removeIfCheckAlwaysSucceeds(HCheck node, TypeMask checkedType) { - ClosedWorld closedWorld = compiler.closedWorld; if (checkedType.containsAll(closedWorld)) return node; HInstruction input = node.checkedInput; TypeMask inputType = input.instructionType; @@ -854,7 +857,7 @@ class SsaInstructionSimplifier extends HBaseVisitor // should not be necessary but it currently makes it easier for // other optimizations to reason about a fixed length constructor // that we know takes an int. - if (receiver.inputs[0].isInteger(compiler)) { + if (receiver.inputs[0].isInteger(closedWorld)) { return receiver.inputs[0]; } } else if (receiver.isConstantList() || receiver.isConstantString()) { @@ -919,8 +922,8 @@ class SsaInstructionSimplifier extends HBaseVisitor if (field != null) return directFieldGet(receiver, field); if (node.element == null) { - MemberElement element = compiler.closedWorld - .locateSingleElement(node.selector, receiver.instructionType); + MemberElement element = closedWorld.locateSingleElement( + node.selector, receiver.instructionType); if (element != null && element.name == node.selector.name) { node.element = element; if (element.isFunction) { @@ -935,7 +938,7 @@ class SsaInstructionSimplifier extends HBaseVisitor } HInstruction directFieldGet(HInstruction receiver, FieldElement field) { - bool isAssignable = !compiler.closedWorld.fieldNeverChanges(field); + bool isAssignable = !closedWorld.fieldNeverChanges(field); TypeMask type; if (backend.isNative(field.enclosingClass)) { @@ -972,8 +975,8 @@ class SsaInstructionSimplifier extends HBaseVisitor // can skip the test an generate the HFieldSet. return node; } - HInstruction other = - value.convertType(compiler, type, HTypeConversion.CHECKED_MODE_CHECK); + HInstruction other = value.convertType( + closedWorld, type, HTypeConversion.CHECKED_MODE_CHECK); if (other != value) { node.block.addBefore(node, other); value = other; @@ -997,17 +1000,17 @@ class SsaInstructionSimplifier extends HBaseVisitor } else if (element == backend.helpers.checkInt) { if (node.inputs.length == 1) { HInstruction argument = node.inputs[0]; - if (argument.isInteger(compiler)) return argument; + if (argument.isInteger(closedWorld)) return argument; } } else if (element == backend.helpers.checkNum) { if (node.inputs.length == 1) { HInstruction argument = node.inputs[0]; - if (argument.isNumber(compiler)) return argument; + if (argument.isNumber(closedWorld)) return argument; } } else if (element == backend.helpers.checkString) { if (node.inputs.length == 1) { HInstruction argument = node.inputs[0]; - if (argument.isString(compiler)) return argument; + if (argument.isString(closedWorld)) return argument; } } return node; @@ -1057,12 +1060,13 @@ class SsaInstructionSimplifier extends HBaseVisitor leftString.primitiveValue, rightString.primitiveValue)), compiler); if (prefix == null) return folded; - return new HStringConcat(prefix, folded, backend.stringType); + return new HStringConcat( + prefix, folded, closedWorld.commonMasks.stringType); } HInstruction visitStringify(HStringify node) { HInstruction input = node.inputs[0]; - if (input.isString(compiler)) return input; + if (input.isString(closedWorld)) return input; HInstruction tryConstant() { if (!input.isConstant()) return null; @@ -1086,12 +1090,11 @@ class SsaInstructionSimplifier extends HBaseVisitor // it directly. Keep the stringifier for primitives (since they have fast // path code in the stringifier) and for classes requiring interceptors // (since SsaInstructionSimplifier runs after SsaSimplifyInterceptors). - if (input.canBePrimitive(compiler)) return null; + if (input.canBePrimitive(closedWorld)) return null; if (input.canBeNull()) return null; Selector selector = Selectors.toString_; TypeMask toStringType = TypeMaskFactory.inferredTypeForSelector( selector, input.instructionType, compiler); - ClosedWorld closedWorld = compiler.closedWorld; if (!toStringType.containsOnlyString(closedWorld)) return null; // All intercepted classes extend `Interceptor`, so if the receiver can't // be a class extending `Interceptor` then it can be called directly. @@ -1116,7 +1119,6 @@ class SsaInstructionSimplifier extends HBaseVisitor } bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { - ClosedWorld closedWorld = compiler.closedWorld; if (closedWorld.isUsedAsMixin(cls)) return true; return closedWorld.anyStrictSubclassOf(cls, (ClassElement subclass) { @@ -1169,7 +1171,7 @@ class SsaInstructionSimplifier extends HBaseVisitor } if (source == null) return null; - return new HTypeInfoReadRaw(source, backend.dynamicType); + return new HTypeInfoReadRaw(source, closedWorld.commonMasks.dynamicType); } // TODO(sra): Consider fusing type expression trees with no type variables, @@ -1192,7 +1194,7 @@ class SsaInstructionSimplifier extends HBaseVisitor TypeInfoExpressionKind.COMPLETE, typeArgument, const [], - backend.dynamicType); + closedWorld.commonMasks.dynamicType); return replacement; } return node; @@ -1222,7 +1224,7 @@ class SsaInstructionSimplifier extends HBaseVisitor TypeInfoExpressionKind.COMPLETE, type, arguments, - backend.dynamicType); + closedWorld.commonMasks.dynamicType); return replacement; } @@ -1289,10 +1291,12 @@ class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { final Set boundsChecked; final bool trustPrimitives; final JavaScriptBackend backend; + final ClosedWorld closedWorld; final String name = "SsaCheckInserter"; HGraph graph; - SsaCheckInserter(this.trustPrimitives, this.backend, this.boundsChecked); + SsaCheckInserter( + this.trustPrimitives, this.backend, this.closedWorld, this.boundsChecked); BackendHelpers get helpers => backend.helpers; @@ -1319,14 +1323,14 @@ class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { HBoundsCheck insertBoundsCheck( HInstruction indexNode, HInstruction array, HInstruction indexArgument) { Compiler compiler = backend.compiler; - HFieldGet length = new HFieldGet( - helpers.jsIndexableLength, array, backend.positiveIntType, + HFieldGet length = new HFieldGet(helpers.jsIndexableLength, array, + closedWorld.commonMasks.positiveIntType, isAssignable: !isFixedLength(array.instructionType, compiler)); indexNode.block.addBefore(indexNode, length); - TypeMask type = indexArgument.isPositiveInteger(compiler) + TypeMask type = indexArgument.isPositiveInteger(closedWorld) ? indexArgument.instructionType - : backend.positiveIntType; + : closedWorld.commonMasks.positiveIntType; HBoundsCheck check = new HBoundsCheck(indexArgument, length, array, type); indexNode.block.addBefore(indexNode, check); // If the index input to the bounds check was not known to be an integer @@ -1336,7 +1340,7 @@ class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { // the index eg. if it is a constant. The range information from the // BoundsCheck instruction is attached to the input directly by // visitBoundsCheck in the SsaValueRangeAnalyzer. - if (!indexArgument.isInteger(compiler)) { + if (!indexArgument.isInteger(closedWorld)) { indexArgument.replaceAllUsersDominatedBy(indexNode, check); } boundsChecked.add(indexNode); @@ -1382,6 +1386,8 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { SsaDeadCodeEliminator(this.compiler, this.optimizer); + ClosedWorld get closedWorld => compiler.closedWorld; + HInstruction zapInstructionCache; HInstruction get zapInstruction { if (zapInstructionCache == null) { @@ -1512,7 +1518,7 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { } void visitGraph(HGraph graph) { - analyzer = new SsaLiveBlockAnalyzer(graph, compiler, optimizer); + analyzer = new SsaLiveBlockAnalyzer(graph, closedWorld, optimizer); analyzer.analyze(); visitPostDominatorTree(graph); cleanPhis(graph); @@ -1600,9 +1606,9 @@ class SsaLiveBlockAnalyzer extends HBaseVisitor { final Set live = new Set(); final List worklist = []; final SsaOptimizerTask optimizer; - final Compiler compiler; + final ClosedWorld closedWorld; - SsaLiveBlockAnalyzer(this.graph, this.compiler, this.optimizer); + SsaLiveBlockAnalyzer(this.graph, this.closedWorld, this.optimizer); Map get ranges => optimizer.ranges; @@ -1641,7 +1647,7 @@ class SsaLiveBlockAnalyzer extends HBaseVisitor { } void visitSwitch(HSwitch node) { - if (node.expression.isInteger(compiler)) { + if (node.expression.isInteger(closedWorld)) { Range switchRange = ranges[node.expression]; if (switchRange != null && switchRange.lower is IntValue && @@ -2095,9 +2101,9 @@ class SsaCodeMotion extends HBaseVisitor implements OptimizationPhase { class SsaTypeConversionInserter extends HBaseVisitor implements OptimizationPhase { final String name = "SsaTypeconversionInserter"; - final Compiler compiler; + final ClosedWorld closedWorld; - SsaTypeConversionInserter(this.compiler); + SsaTypeConversionInserter(this.closedWorld); void visitGraph(HGraph graph) { visitDominatorTree(graph); @@ -2135,8 +2141,7 @@ class SsaTypeConversionInserter extends HBaseVisitor if (trueTargets.isEmpty && falseTargets.isEmpty) return; - TypeMask convertedType = - new TypeMask.nonNullSubtype(element, compiler.closedWorld); + TypeMask convertedType = new TypeMask.nonNullSubtype(element, closedWorld); HInstruction input = instruction.expression; for (HBasicBlock block in trueTargets) { diff --git a/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart b/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart index c0dfa0b15f9..b34552cd652 100644 --- a/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart +++ b/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart @@ -161,8 +161,7 @@ class SsaBranchBuilder { boolifiedLeft = builder.popBoolified(); builder.stack.add(boolifiedLeft); if (!isAnd) { - JavaScriptBackend backend = compiler.backend; - builder.push(new HNot(builder.pop(), backend.boolType)); + builder.push(new HNot(builder.pop(), builder.commonMasks.boolType)); } } @@ -173,9 +172,10 @@ class SsaBranchBuilder { handleIf(visitCondition, visitThen, null); HConstant notIsAnd = builder.graph.addConstantBool(!isAnd, compiler); - JavaScriptBackend backend = compiler.backend; HPhi result = new HPhi.manyInputs( - null, [boolifiedRight, notIsAnd], backend.dynamicType); + null, + [boolifiedRight, notIsAnd], + builder.commonMasks.dynamicType); builder.current.addPhi(result); builder.stack.add(result); } @@ -200,9 +200,8 @@ class SsaBranchBuilder { if (isExpression) { assert(thenValue != null && elseValue != null); - JavaScriptBackend backend = compiler.backend; - HPhi phi = new HPhi.manyInputs( - null, [thenValue, elseValue], backend.dynamicType); + HPhi phi = new HPhi.manyInputs(null, [thenValue, elseValue], + builder.commonMasks.dynamicType); joinBranch.block.addPhi(phi); builder.stack.add(phi); } diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart index 6c1d54319cd..ce13448c429 100644 --- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart +++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart @@ -10,6 +10,7 @@ import '../compiler.dart' show Compiler; import '../diagnostics/invariant.dart' show DEBUG_MODE; import '../js_backend/js_backend.dart'; import '../tracer.dart'; +import '../world.dart' show ClosedWorld; import 'nodes.dart'; /** @@ -117,6 +118,8 @@ class HInstructionStringifier implements HVisitor { HInstructionStringifier(this.currentBlock, this.compiler); + ClosedWorld get closedWorld => compiler.closedWorld; + visit(HInstruction node) => '${node.accept(this)} ${node.instructionType}'; String temporaryId(HInstruction instruction) { @@ -125,27 +128,27 @@ class HInstructionStringifier implements HVisitor { prefix = 'u'; } else if (instruction.isConflicting()) { prefix = 'c'; - } else if (instruction.isExtendableArray(compiler)) { + } else if (instruction.isExtendableArray(closedWorld)) { prefix = 'e'; - } else if (instruction.isFixedArray(compiler)) { + } else if (instruction.isFixedArray(closedWorld)) { prefix = 'f'; - } else if (instruction.isMutableArray(compiler)) { + } else if (instruction.isMutableArray(closedWorld)) { prefix = 'm'; - } else if (instruction.isReadableArray(compiler)) { + } else if (instruction.isReadableArray(closedWorld)) { prefix = 'a'; - } else if (instruction.isString(compiler)) { + } else if (instruction.isString(closedWorld)) { prefix = 's'; - } else if (instruction.isIndexablePrimitive(compiler)) { + } else if (instruction.isIndexablePrimitive(closedWorld)) { prefix = 'r'; - } else if (instruction.isBoolean(compiler)) { + } else if (instruction.isBoolean(closedWorld)) { prefix = 'b'; - } else if (instruction.isInteger(compiler)) { + } else if (instruction.isInteger(closedWorld)) { prefix = 'i'; - } else if (instruction.isDouble(compiler)) { + } else if (instruction.isDouble(closedWorld)) { prefix = 'd'; - } else if (instruction.isNumber(compiler)) { + } else if (instruction.isNumber(closedWorld)) { prefix = 'n'; - } else if (instruction.instructionType.containsAll(compiler.closedWorld)) { + } else if (instruction.instructionType.containsAll(closedWorld)) { prefix = 'v'; } else { prefix = 'U'; diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart index 605678bf870..c04d4159e04 100644 --- a/pkg/compiler/lib/src/ssa/type_builder.dart +++ b/pkg/compiler/lib/src/ssa/type_builder.dart @@ -30,7 +30,7 @@ class TypeBuilder { if (type.isObject) return original; // The type element is either a class or the void element. Element element = type.element; - TypeMask mask = new TypeMask.subtype(element, builder.compiler.closedWorld); + TypeMask mask = new TypeMask.subtype(element, builder.closedWorld); return new HTypeKnown.pinned(mask, original); } @@ -133,9 +133,9 @@ class TypeBuilder { assert(member.isInstanceMember); assert(variable is! MethodTypeVariableType); HInstruction target = builder.localsHandler.readThis(); - builder.push( - new HTypeInfoReadVariable(variable, target, builder.backend.dynamicType) - ..sourceInformation = sourceInformation); + builder.push(new HTypeInfoReadVariable( + variable, target, builder.commonMasks.dynamicType) + ..sourceInformation = sourceInformation); return builder.pop(); } @@ -154,7 +154,7 @@ class TypeBuilder { TypeInfoExpressionKind.INSTANCE, interface.element.thisType, inputs, - builder.backend.dynamicType); + builder.commonMasks.dynamicType); return representation; } @@ -195,7 +195,7 @@ class TypeBuilder { TypeInfoExpressionKind.COMPLETE, argument, inputs, - builder.backend.dynamicType)..sourceInformation = sourceInformation; + builder.commonMasks.dynamicType)..sourceInformation = sourceInformation; builder.add(result); return result; } @@ -246,7 +246,7 @@ class TypeBuilder { } else if (type.isFunctionType) { return builder.buildFunctionTypeConversion(original, type, kind); } else { - return original.convertType(builder.compiler, type, kind); + return original.convertType(builder.closedWorld, type, kind); } } } diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart index 63da6283869..b02072de894 100644 --- a/pkg/compiler/lib/src/ssa/types_propagation.dart +++ b/pkg/compiler/lib/src/ssa/types_propagation.dart @@ -109,18 +109,21 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { TypeMask visitBinaryArithmetic(HBinaryArithmetic instruction) { HInstruction left = instruction.left; HInstruction right = instruction.right; - if (left.isInteger(compiler) && right.isInteger(compiler)) { - return backend.intType; + if (left.isInteger(closedWorld) && right.isInteger(closedWorld)) { + return closedWorld.commonMasks.intType; } - if (left.isDouble(compiler)) return backend.doubleType; - return backend.numType; + if (left.isDouble(closedWorld)) { + return closedWorld.commonMasks.doubleType; + } + return closedWorld.commonMasks.numType; } TypeMask checkPositiveInteger(HBinaryArithmetic instruction) { HInstruction left = instruction.left; HInstruction right = instruction.right; - if (left.isPositiveInteger(compiler) && right.isPositiveInteger(compiler)) { - return backend.positiveIntType; + if (left.isPositiveInteger(closedWorld) && + right.isPositiveInteger(closedWorld)) { + return closedWorld.commonMasks.positiveIntType; } return visitBinaryArithmetic(instruction); } @@ -147,7 +150,9 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { HInstruction operand = instruction.operand; // We have integer subclasses that represent ranges, so widen any int // subclass to full integer. - if (operand.isInteger(compiler)) return backend.intType; + if (operand.isInteger(closedWorld)) { + return closedWorld.commonMasks.intType; + } return instruction.operand.instructionType; } @@ -157,7 +162,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { } TypeMask visitPhi(HPhi phi) { - TypeMask candidateType = backend.emptyType; + TypeMask candidateType = closedWorld.commonMasks.emptyType; for (int i = 0, length = phi.inputs.length; i < length; i++) { TypeMask inputType = phi.inputs[i].instructionType; candidateType = candidateType.union(inputType, closedWorld); @@ -175,11 +180,11 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { // We only do an int check if the input is integer or null. if (checkedType.containsOnlyNum(closedWorld) && !checkedType.containsOnlyDouble(closedWorld) && - input.isIntegerOrNull(compiler)) { - instruction.checkedType = backend.intType; + input.isIntegerOrNull(closedWorld)) { + instruction.checkedType = closedWorld.commonMasks.intType; } else if (checkedType.containsOnlyInt(closedWorld) && - !input.isIntegerOrNull(compiler)) { - instruction.checkedType = backend.numType; + !input.isIntegerOrNull(closedWorld)) { + instruction.checkedType = closedWorld.commonMasks.numType; } } @@ -193,9 +198,9 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { if (inputType.containsOnlyInt(closedWorld) && checkedType.containsOnlyDouble(closedWorld)) { if (inputType.isNullable && checkedType.isNullable) { - outputType = backend.doubleType.nullable(); + outputType = closedWorld.commonMasks.doubleType.nullable(); } else { - outputType = backend.doubleType; + outputType = closedWorld.commonMasks.doubleType; } } } @@ -248,7 +253,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { // If the instruction's type is integer or null, the codegen // will emit a null check, which is enough to know if it will // hit a noSuchMethod. - return instruction.isIntegerOrNull(compiler); + return instruction.isIntegerOrNull(closedWorld); } return true; } @@ -259,8 +264,8 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { bool checkReceiver(HInvokeDynamic instruction) { assert(instruction.isInterceptedCall); HInstruction receiver = instruction.inputs[1]; - if (receiver.isNumber(compiler)) return false; - if (receiver.isNumberOrNull(compiler)) { + if (receiver.isNumber(closedWorld)) return false; + if (receiver.isNumberOrNull(closedWorld)) { convertInput( instruction, receiver, @@ -268,7 +273,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { HTypeConversion.RECEIVER_TYPE_CHECK); return true; } else if (instruction.element == null) { - Iterable targets = compiler.closedWorld.allFunctions + Iterable targets = closedWorld.allFunctions .filter(instruction.selector, instruction.mask); if (targets.length == 1) { MemberElement target = targets.first; @@ -302,11 +307,11 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { HInstruction right = instruction.inputs[2]; Selector selector = instruction.selector; - if (selector.isOperator && left.isNumber(compiler)) { - if (right.isNumber(compiler)) return false; - TypeMask type = right.isIntegerOrNull(compiler) + if (selector.isOperator && left.isNumber(closedWorld)) { + if (right.isNumber(closedWorld)) return false; + TypeMask type = right.isIntegerOrNull(closedWorld) ? right.instructionType.nonNullable() - : backend.numType; + : closedWorld.commonMasks.numType; // TODO(ngeoffray): Some number operations don't have a builtin // variant and will do the check in their method anyway. We // still add a check because it allows to GVN these operations, @@ -371,7 +376,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { if (!instruction.selector.isClosureCall) { TypeMask newType; TypeMask computeNewType() { - newType = compiler.closedWorld.allFunctions + newType = closedWorld.allFunctions .receiverType(instruction.selector, instruction.mask); newType = newType.intersection(receiverType, closedWorld); return newType; @@ -406,6 +411,6 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase { } return instruction.specializer - .computeTypeFromInputTypes(instruction, compiler); + .computeTypeFromInputTypes(instruction, compiler, closedWorld); } } diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart index 1882fc6bb1f..67e861eb2d8 100644 --- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart +++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart @@ -7,6 +7,7 @@ import '../constant_system_dart.dart'; import '../constants/constant_system.dart'; import '../constants/values.dart'; import '../js_backend/js_backend.dart'; +import '../world.dart' show ClosedWorld; import 'nodes.dart'; import 'optimize.dart'; @@ -611,6 +612,8 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { : info = new ValueRangeInfo(constantSystem), this.constantSystem = constantSystem; + ClosedWorld get closedWorld => compiler.closedWorld; + void visitGraph(HGraph graph) { this.graph = graph; visitDominatorTree(graph); @@ -632,7 +635,7 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { void visitBasicBlock(HBasicBlock block) { void visit(HInstruction instruction) { Range range = instruction.accept(this); - if (instruction.isInteger(compiler)) { + if (instruction.isInteger(closedWorld)) { assert(range != null); ranges[instruction] = range; } @@ -643,10 +646,10 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { } Range visitInstruction(HInstruction instruction) { - if (instruction.isPositiveInteger(compiler)) { + if (instruction.isPositiveInteger(closedWorld)) { return info.newNormalizedRange( info.intZero, info.newPositiveValue(instruction)); - } else if (instruction.isInteger(compiler)) { + } else if (instruction.isInteger(closedWorld)) { InstructionValue value = info.newInstructionValue(instruction); return info.newNormalizedRange(value, value); } else { @@ -655,16 +658,17 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { } Range visitPhi(HPhi phi) { - if (!phi.isInteger(compiler)) return info.newUnboundRange(); + if (!phi.isInteger(closedWorld)) return info.newUnboundRange(); // Some phases may replace instructions that change the inputs of // this phi. Only the [SsaTypesPropagation] phase will update the // phi type. Play it safe by assuming the [SsaTypesPropagation] // phase is not necessarily run before the [ValueRangeAnalyzer]. - if (phi.inputs.any((i) => !i.isInteger(compiler))) { + if (phi.inputs.any((i) => !i.isInteger(closedWorld))) { return info.newUnboundRange(); } if (phi.block.isLoopHeader()) { - Range range = new LoopUpdateRecognizer(compiler, ranges, info).run(phi); + Range range = + new LoopUpdateRecognizer(closedWorld, ranges, info).run(phi); if (range == null) return info.newUnboundRange(); return range; } @@ -677,7 +681,7 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { } Range visitConstant(HConstant hConstant) { - if (!hConstant.isInteger(compiler)) return info.newUnboundRange(); + if (!hConstant.isInteger(closedWorld)) return info.newUnboundRange(); ConstantValue constant = hConstant.constant; NumConstantValue constantNum; if (constant is DeferredConstantValue) { @@ -694,8 +698,8 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { } Range visitFieldGet(HFieldGet fieldGet) { - if (!fieldGet.isInteger(compiler)) return info.newUnboundRange(); - if (!fieldGet.receiver.isIndexablePrimitive(compiler)) { + if (!fieldGet.isInteger(closedWorld)) return info.newUnboundRange(); + if (!fieldGet.receiver.isIndexablePrimitive(closedWorld)) { return visitInstruction(fieldGet); } JavaScriptBackend backend = compiler.backend; @@ -715,7 +719,7 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { Range lengthRange = ranges[check.length]; if (indexRange == null) { indexRange = info.newUnboundRange(); - assert(!check.index.isInteger(compiler)); + assert(!check.index.isInteger(closedWorld)); } if (lengthRange == null) { // We might have lost the length range due to a type conversion that @@ -723,7 +727,7 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { // get to this point anyway, so no need to try and refine ranges. return indexRange; } - assert(check.length.isInteger(compiler)); + assert(check.length.isInteger(closedWorld)); // Check if the index is strictly below the upper bound of the length // range. @@ -776,8 +780,8 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { Range visitRelational(HRelational relational) { HInstruction right = relational.right; HInstruction left = relational.left; - if (!left.isInteger(compiler)) return info.newUnboundRange(); - if (!right.isInteger(compiler)) return info.newUnboundRange(); + if (!left.isInteger(closedWorld)) return info.newUnboundRange(); + if (!right.isInteger(closedWorld)) return info.newUnboundRange(); BinaryOperation operation = relational.operation(constantSystem); Range rightRange = ranges[relational.right]; Range leftRange = ranges[relational.left]; @@ -812,7 +816,7 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { if (divisor != null) { // For Integer values we can be precise in the upper bound, // so special case those. - if (left.isInteger(compiler) && right.isInteger(compiler)) { + if (left.isInteger(closedWorld) && right.isInteger(closedWorld)) { if (divisor.isPositive) { return info.newNormalizedRange( info.intZero, divisor.upper - info.intOne); @@ -820,7 +824,7 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { return info.newNormalizedRange( info.intZero, info.newNegateValue(divisor.lower) - info.intOne); } - } else if (left.isNumber(compiler) && right.isNumber(compiler)) { + } else if (left.isNumber(closedWorld) && right.isNumber(closedWorld)) { if (divisor.isPositive) { return info.newNormalizedRange(info.intZero, divisor.upper); } else if (divisor.isNegative) { @@ -839,7 +843,7 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { } Range handleBinaryOperation(HBinaryArithmetic instruction) { - if (!instruction.isInteger(compiler)) return info.newUnboundRange(); + if (!instruction.isInteger(closedWorld)) return info.newUnboundRange(); return instruction .operation(constantSystem) .apply(ranges[instruction.left], ranges[instruction.right]); @@ -854,10 +858,10 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { } Range visitBitAnd(HBitAnd node) { - if (!node.isInteger(compiler)) return info.newUnboundRange(); + if (!node.isInteger(closedWorld)) return info.newUnboundRange(); HInstruction right = node.right; HInstruction left = node.left; - if (left.isInteger(compiler) && right.isInteger(compiler)) { + if (left.isInteger(closedWorld) && right.isInteger(closedWorld)) { return ranges[left] & ranges[right]; } @@ -871,9 +875,9 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { return info.newUnboundRange(); } - if (left.isInteger(compiler)) { + if (left.isInteger(closedWorld)) { return tryComputeRange(left); - } else if (right.isInteger(compiler)) { + } else if (right.isInteger(closedWorld)) { return tryComputeRange(right); } return info.newUnboundRange(); @@ -888,9 +892,8 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { HInstruction createRangeConversion( HInstruction cursor, HInstruction instruction) { - JavaScriptBackend backend = compiler.backend; HRangeConversion newInstruction = - new HRangeConversion(instruction, backend.intType); + new HRangeConversion(instruction, closedWorld.commonMasks.intType); conversions.add(newInstruction); cursor.block.addBefore(cursor, newInstruction); // Update the users of the instruction dominated by [cursor] to @@ -953,8 +956,8 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { if (condition is HIdentity) return info.newUnboundRange(); HInstruction right = condition.right; HInstruction left = condition.left; - if (!left.isInteger(compiler)) return info.newUnboundRange(); - if (!right.isInteger(compiler)) return info.newUnboundRange(); + if (!left.isInteger(closedWorld)) return info.newUnboundRange(); + if (!right.isInteger(closedWorld)) return info.newUnboundRange(); Range rightRange = ranges[right]; Range leftRange = ranges[left]; @@ -1016,10 +1019,10 @@ class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase { * Tries to find a range for the update instruction of a loop phi. */ class LoopUpdateRecognizer extends HBaseVisitor { - final Compiler compiler; + final ClosedWorld closedWorld; final Map ranges; final ValueRangeInfo info; - LoopUpdateRecognizer(this.compiler, this.ranges, this.info); + LoopUpdateRecognizer(this.closedWorld, this.ranges, this.info); Range run(HPhi loopPhi) { // Create a marker range for the loop phi, so that if the update @@ -1044,7 +1047,7 @@ class LoopUpdateRecognizer extends HBaseVisitor { } Range visit(HInstruction instruction) { - if (!instruction.isInteger(compiler)) return null; + if (!instruction.isInteger(closedWorld)) return null; if (ranges[instruction] != null) return ranges[instruction]; return instruction.accept(this); } diff --git a/pkg/compiler/lib/src/types/masks.dart b/pkg/compiler/lib/src/types/masks.dart index 5cbc4c06dd4..43e06009ef1 100644 --- a/pkg/compiler/lib/src/types/masks.dart +++ b/pkg/compiler/lib/src/types/masks.dart @@ -61,6 +61,12 @@ class CommonMasks { TypeMask _syncStarIterableType; TypeMask _asyncFutureType; TypeMask _asyncStarStreamType; + TypeMask _indexablePrimitiveType; + TypeMask _readableArrayType; + TypeMask _mutableArrayType; + TypeMask _fixedArrayType; + TypeMask _extendableArrayType; + TypeMask _unmodifiableArrayType; TypeMask get dynamicType => _dynamicType ??= new TypeMask.subclass(closedWorld.coreClasses.objectClass, closedWorld); @@ -132,4 +138,29 @@ class CommonMasks { // TODO(johnniwinther): Assert that the null type has been resolved. TypeMask get nullType => _nullType ??= const TypeMask.empty(); + + TypeMask get emptyType => const TypeMask.nonNullEmpty(); + + TypeMask get indexablePrimitiveType => + _indexablePrimitiveType ??= new TypeMask.nonNullSubtype( + backendClasses.indexableImplementation, closedWorld); + + TypeMask get readableArrayType => + _readableArrayType ??= new TypeMask.nonNullSubclass( + backendClasses.listImplementation, closedWorld); + + TypeMask get mutableArrayType => + _mutableArrayType ??= new TypeMask.nonNullSubclass( + backendClasses.mutableListImplementation, closedWorld); + + TypeMask get fixedArrayType => _fixedArrayType ??= new TypeMask.nonNullExact( + backendClasses.fixedListImplementation, closedWorld); + + TypeMask get extendableArrayType => + _extendableArrayType ??= new TypeMask.nonNullExact( + backendClasses.growableListImplementation, closedWorld); + + TypeMask get unmodifiableArrayType => + _unmodifiableArrayType ??= new TypeMask.nonNullExact( + backendClasses.constListImplementation, closedWorld); }