Chromium Code Reviews| Index: pkg/compiler/lib/src/ssa/optimize.dart |
| diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart |
| index 607688dd7dc1335045136ff00a819d2c159a26de..27b3e97a51a477350f50e76e5dee7a0cfea63e1a 100644 |
| --- a/pkg/compiler/lib/src/ssa/optimize.dart |
| +++ b/pkg/compiler/lib/src/ssa/optimize.dart |
| @@ -9,9 +9,10 @@ import '../compiler.dart' show Compiler; |
| import '../constants/constant_system.dart'; |
| import '../constants/values.dart'; |
| import '../core_types.dart' show CommonElements; |
| -import '../elements/resolution_types.dart'; |
| -import '../elements/elements.dart'; |
| +import '../elements/elements.dart' |
| + show ClassElement, Entity, FieldElement, MethodElement; |
| import '../elements/entities.dart'; |
| +import '../elements/resolution_types.dart'; |
| import '../js/js.dart' as js; |
| import '../js_backend/backend_helpers.dart' show BackendHelpers; |
| import '../js_backend/js_backend.dart'; |
| @@ -343,7 +344,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| ListConstantValue constant = constantInput.constant; |
| return graph.addConstantInt(constant.length, closedWorld); |
| } |
| - MemberElement element = helpers.jsIndexableLength; |
| + MemberEntity element = helpers.jsIndexableLength; |
| bool isFixed = isFixedLength(actualReceiver.instructionType, closedWorld); |
| TypeMask actualType = node.instructionType; |
| TypeMask resultType = closedWorld.commonMasks.positiveIntType; |
| @@ -385,13 +386,13 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| TypeMask mask = node.mask; |
| HInstruction input = node.inputs[1]; |
| - bool applies(Element element) { |
| + bool applies(MemberEntity element) { |
| return selector.applies(element) && |
| (mask == null || mask.canHit(element, selector, closedWorld)); |
| } |
| if (selector.isCall || selector.isOperator) { |
| - MethodElement target; |
| + FunctionEntity target; |
| if (input.isExtendableArray(closedWorld)) { |
| if (applies(helpers.jsArrayRemoveLast)) { |
| target = helpers.jsArrayRemoveLast; |
| @@ -452,7 +453,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| } |
| TypeMask receiverType = node.getDartReceiver(closedWorld).instructionType; |
| - Element element = |
| + MemberEntity element = |
| closedWorld.locateSingleElement(node.selector, receiverType); |
| // TODO(ngeoffray): Also fold if it's a getter or variable. |
| if (element != null && |
| @@ -469,9 +470,12 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| } else { |
| // TODO(ngeoffray): If the method has optional parameters, |
| // we should pass the default values. |
| - FunctionSignature parameters = method.functionSignature; |
| - if (parameters.optionalParameterCount == 0 || |
| - parameters.parameterCount == node.selector.argumentCount) { |
| + FunctionType type = method.type; |
| + int optionalParameterCount = |
| + type.optionalParameterTypes.length + type.namedParameters.length; |
| + if (optionalParameterCount == 0 || |
| + type.parameterTypes.length + optionalParameterCount == |
| + node.selector.argumentCount) { |
| node.element = method; |
| } |
| } |
| @@ -485,11 +489,11 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| if (element != null && |
| element.isField && |
| element.name == node.selector.name) { |
| - FieldElement field = element; |
| + FieldEntity field = element; |
| if (!backend.isNative(field) && !node.isCallOnInterceptor(closedWorld)) { |
| HInstruction receiver = node.getDartReceiver(closedWorld); |
| TypeMask type = TypeMaskFactory.inferredTypeForElement( |
| - field, globalInferenceResults); |
| + field as Entity, globalInferenceResults); |
|
sra1
2017/01/04 17:20:48
Why is 'as' needed? is a FieldEntity not an Entity
Johnni Winther
2017/01/05 08:54:42
It is. The Dart type system doesn't handle diamond
Siggi Cherem (dart-lang)
2017/01/05 18:14:08
mmm... this feels like it might be hiding the issu
Johnni Winther
2017/01/06 09:04:51
I like _not_ being able to write `Element` in this
|
| HInstruction load = new HFieldGet(field, receiver, type); |
| node.block.addBefore(node, load); |
| Selector callSelector = new Selector.callClosureFrom(node.selector); |
| @@ -524,8 +528,8 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| // foo() native 'return something'; |
| // They should not be used. |
| - FunctionSignature signature = method.functionSignature; |
| - if (signature.optionalParametersAreNamed) return null; |
| + FunctionType type = method.type; |
| + if (type.namedParameters.isNotEmpty) return null; |
| // Return types on native methods don't need to be checked, since the |
| // declaration has to be truthful. |
| @@ -534,23 +538,27 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| // preserve the number of arguments, so check only the actual arguments. |
| List<HInstruction> inputs = node.inputs.sublist(1); |
| - int inputPosition = 1; // Skip receiver. |
| bool canInline = true; |
| - signature.forEachParameter((ParameterElement element) { |
| - if (inputPosition++ < inputs.length && canInline) { |
| - DartType type = element.type.unaliased; |
| - if (type is FunctionType) { |
| - canInline = false; |
| - } |
| - if (compiler.options.enableTypeAssertions) { |
| - // TODO(sra): Check if [input] is guaranteed to pass the parameter |
| - // type check. Consider using a strengthened type check to avoid |
| - // passing `null` to primitive types since the native methods usually |
| - // have non-nullable primitive parameter types. |
| - canInline = false; |
| + if (compiler.options.enableTypeAssertions && inputs.length > 1) { |
| + // TODO(sra): Check if [input] is guaranteed to pass the parameter |
| + // type check. Consider using a strengthened type check to avoid |
| + // passing `null` to primitive types since the native methods usually |
| + // have non-nullable primitive parameter types. |
| + canInline = false; |
| + } else { |
| + int inputPosition = 1; // Skip receiver. |
| + void checkParameterType(DartType type) { |
| + if (inputPosition++ < inputs.length && canInline) { |
| + if (type.unaliased.isFunctionType) { |
| + canInline = false; |
| + } |
| } |
| } |
| - }); |
| + |
| + type.parameterTypes.forEach(checkParameterType); |
| + type.optionalParameterTypes.forEach(checkParameterType); |
| + type.namedParameterTypes.forEach(checkParameterType); |
| + } |
| if (!canInline) return null; |
| @@ -731,20 +739,20 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| HInstruction visitIs(HIs node) { |
| DartType type = node.typeExpression; |
| - Element element = type.element; |
| if (!node.isRawCheck) { |
| return node; |
| } else if (type.isTypedef) { |
| return node; |
| - } else if (element == commonElements.functionClass) { |
| + } else if (type.isFunctionType) { |
| return node; |
| } |
| if (type.isObject || type.treatAsDynamic) { |
| return graph.addConstantBool(true, closedWorld); |
| } |
| - |
| + InterfaceType interfaceType = type; |
| + ClassEntity element = interfaceType.element; |
| HInstruction expression = node.expression; |
| if (expression.isInteger(closedWorld)) { |
| if (element == commonElements.intClass || |
| @@ -847,7 +855,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| HInstruction removeCheck(HCheck node) => node.checkedInput; |
| - FieldElement findConcreteFieldForDynamicAccess( |
| + FieldEntity findConcreteFieldForDynamicAccess( |
| HInstruction receiver, Selector selector) { |
| TypeMask receiverType = receiver.instructionType; |
| return closedWorld.locateSingleField(selector, receiverType); |
| @@ -923,12 +931,12 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| if (folded != node) return folded; |
| } |
| HInstruction receiver = node.getDartReceiver(closedWorld); |
| - FieldElement field = |
| + FieldEntity field = |
| findConcreteFieldForDynamicAccess(receiver, node.selector); |
| if (field != null) return directFieldGet(receiver, field); |
| if (node.element == null) { |
| - MemberElement element = closedWorld.locateSingleElement( |
| + MemberEntity element = closedWorld.locateSingleElement( |
| node.selector, receiver.instructionType); |
| if (element != null && element.name == node.selector.name) { |
| node.element = element; |
| @@ -943,16 +951,16 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| return node; |
| } |
| - HInstruction directFieldGet(HInstruction receiver, FieldElement field) { |
| - bool isAssignable = !closedWorld.fieldNeverChanges(field); |
| + HInstruction directFieldGet(HInstruction receiver, FieldEntity field) { |
| + bool isAssignable = !closedWorld.fieldNeverChanges(field as MemberEntity); |
| TypeMask type; |
| if (backend.isNative(field.enclosingClass)) { |
| type = TypeMaskFactory.fromNativeBehavior( |
| backend.getNativeFieldLoadBehavior(field), closedWorld); |
| } else { |
| - type = |
| - TypeMaskFactory.inferredTypeForElement(field, globalInferenceResults); |
| + type = TypeMaskFactory.inferredTypeForElement( |
| + field as Entity, globalInferenceResults); |
| } |
| return new HFieldGet(field, receiver, type, isAssignable: isAssignable); |
| @@ -994,7 +1002,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| HInstruction visitInvokeStatic(HInvokeStatic node) { |
| propagateConstantValueToUses(node); |
| - MemberElement element = node.element; |
| + MemberEntity element = node.element; |
| if (element == backend.helpers.checkConcurrentModificationError) { |
| if (node.inputs.length == 2) { |
| @@ -1125,10 +1133,10 @@ class SsaInstructionSimplifier extends HBaseVisitor |
| return handleInterceptedCall(node); |
| } |
| - bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { |
| + bool needsSubstitutionForTypeVariableAccess(ClassEntity cls) { |
| if (closedWorld.isUsedAsMixin(cls)) return true; |
| - return closedWorld.anyStrictSubclassOf(cls, (ClassElement subclass) { |
| + return closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) { |
| return !backend.rti.isTrivialSubstitution(subclass, cls); |
| }); |
| } |
| @@ -1366,7 +1374,7 @@ class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { |
| } |
| void visitInvokeDynamicMethod(HInvokeDynamicMethod node) { |
| - MemberElement element = node.element; |
| + MemberEntity element = node.element; |
| if (node.isInterceptedCall) return; |
| if (element != helpers.jsArrayRemoveLast) return; |
| if (boundsChecked.contains(node)) return; |
| @@ -2130,12 +2138,13 @@ class SsaTypeConversionInserter extends HBaseVisitor |
| void visitIs(HIs instruction) { |
| DartType type = instruction.typeExpression; |
| - Element element = type.element; |
| if (!instruction.isRawCheck) { |
| return; |
| - } else if (element.isTypedef) { |
| + } else if (type.isTypedef) { |
| return; |
| } |
| + InterfaceType interfaceType = type; |
| + ClassEntity cls = interfaceType.element; |
| List<HBasicBlock> trueTargets = <HBasicBlock>[]; |
| List<HBasicBlock> falseTargets = <HBasicBlock>[]; |
| @@ -2144,7 +2153,7 @@ class SsaTypeConversionInserter extends HBaseVisitor |
| if (trueTargets.isEmpty && falseTargets.isEmpty) return; |
| - TypeMask convertedType = new TypeMask.nonNullSubtype(element, closedWorld); |
| + TypeMask convertedType = new TypeMask.nonNullSubtype(cls, closedWorld); |
| HInstruction input = instruction.expression; |
| for (HBasicBlock block in trueTargets) { |
| @@ -2286,7 +2295,7 @@ class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { |
| void visitFieldGet(HFieldGet instruction) { |
| if (instruction.isNullCheck) return; |
| - MemberElement element = instruction.element; |
| + MemberEntity element = instruction.element; |
| HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck(); |
| HInstruction existing = memorySet.lookupFieldValue(element, receiver); |
| if (existing != null) { |
| @@ -2308,8 +2317,8 @@ class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { |
| if (shouldTrackInitialValues(instruction)) { |
| int argumentIndex = 0; |
| compiler.codegenWorld.forEachInstanceField(instruction.element, |
| - (_, FieldElement member) { |
| - if (compiler.elementHasCompileTimeError(member)) return; |
| + (_, FieldEntity member) { |
| + if (compiler.elementHasCompileTimeError(member as Entity)) return; |
| memorySet.registerFieldValue( |
| member, instruction, instruction.inputs[argumentIndex++]); |
| }); |
| @@ -2365,11 +2374,11 @@ class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { |
| } |
| void visitLazyStatic(HLazyStatic instruction) { |
| - FieldElement field = instruction.element; |
| + FieldEntity field = instruction.element; |
| handleStaticLoad(field, instruction); |
| } |
| - void handleStaticLoad(MemberElement element, HInstruction instruction) { |
| + void handleStaticLoad(MemberEntity element, HInstruction instruction) { |
| HInstruction existing = memorySet.lookupFieldValue(element, null); |
| if (existing != null) { |
| instruction.block.rewriteWithBetterUser(instruction, existing); |
| @@ -2444,8 +2453,8 @@ class MemorySet { |
| /** |
| * Maps a field to a map of receiver to value. |
| */ |
| - final Map<Element, Map<HInstruction, HInstruction>> fieldValues = |
| - <Element, Map<HInstruction, HInstruction>>{}; |
| + final Map<MemberEntity, Map<HInstruction, HInstruction>> fieldValues = |
| + <MemberEntity, Map<HInstruction, HInstruction>>{}; |
| /** |
| * Maps a receiver to a map of keys to value. |
| @@ -2481,7 +2490,7 @@ class MemorySet { |
| .isDisjoint(second.instructionType, closedWorld); |
| } |
| - bool isFinal(Element element) { |
| + bool isFinal(MemberEntity element) { |
| return closedWorld.fieldNeverChanges(element); |
| } |
| @@ -2513,9 +2522,9 @@ class MemorySet { |
| * may be affected by this update. |
| */ |
| void registerFieldValueUpdate( |
| - MemberElement element, HInstruction receiver, HInstruction value) { |
| + MemberEntity element, HInstruction receiver, HInstruction value) { |
| assert(receiver == null || receiver == receiver.nonCheck()); |
| - if (closedWorld.backendClasses.isNative(element)) { |
| + if (closedWorld.backendClasses.isNativeMember(element)) { |
| return; // TODO(14955): Remove this restriction? |
| } |
| // [value] is being set in some place in memory, we remove it from |
| @@ -2533,9 +2542,9 @@ class MemorySet { |
| * Registers that `receiver.element` is now [value]. |
| */ |
| void registerFieldValue( |
| - MemberElement element, HInstruction receiver, HInstruction value) { |
| + MemberEntity element, HInstruction receiver, HInstruction value) { |
| assert(receiver == null || receiver == receiver.nonCheck()); |
| - if (closedWorld.backendClasses.isNative(element)) { |
| + if (closedWorld.backendClasses.isNativeMember(element)) { |
| return; // TODO(14955): Remove this restriction? |
| } |
| Map<HInstruction, HInstruction> map = |
| @@ -2547,7 +2556,7 @@ class MemorySet { |
| * Returns the value stored in `receiver.element`. Returns `null` if we don't |
| * know. |
| */ |
| - HInstruction lookupFieldValue(Element element, HInstruction receiver) { |
| + HInstruction lookupFieldValue(MemberEntity element, HInstruction receiver) { |
| assert(receiver == null || receiver == receiver.nonCheck()); |
| Map<HInstruction, HInstruction> map = fieldValues[element]; |
| return (map == null) ? null : map[receiver]; |
| @@ -2568,7 +2577,7 @@ class MemorySet { |
| if (instruction.sideEffects.changesInstanceProperty() || |
| instruction.sideEffects.changesStaticProperty()) { |
| - fieldValues.forEach((element, map) { |
| + fieldValues.forEach((MemberEntity element, map) { |
| if (isFinal(element)) return; |
| map.forEach((receiver, value) { |
| if (escapes(receiver)) { |