OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:math' as math; | 5 import 'dart:math' as math; |
6 import '../common.dart'; | 6 import '../common.dart'; |
7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
8 import '../common/tasks.dart' show CompilerTask; | 8 import '../common/tasks.dart' show CompilerTask; |
9 import '../compiler.dart' show Compiler; | 9 import '../compiler.dart' show Compiler; |
10 import '../constants/constant_system.dart'; | 10 import '../constants/constant_system.dart'; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 parameters = <js.Parameter>[], | 172 parameters = <js.Parameter>[], |
173 expressionStack = <js.Expression>[], | 173 expressionStack = <js.Expression>[], |
174 oldContainerStack = <js.Block>[], | 174 oldContainerStack = <js.Block>[], |
175 generateAtUseSite = new Set<HInstruction>(), | 175 generateAtUseSite = new Set<HInstruction>(), |
176 controlFlowOperators = new Set<HInstruction>(), | 176 controlFlowOperators = new Set<HInstruction>(), |
177 breakAction = new Map<Entity, EntityAction>(), | 177 breakAction = new Map<Entity, EntityAction>(), |
178 continueAction = new Map<Entity, EntityAction>(); | 178 continueAction = new Map<Entity, EntityAction>(); |
179 | 179 |
180 Compiler get compiler => backend.compiler; | 180 Compiler get compiler => backend.compiler; |
181 | 181 |
| 182 ClosedWorld get closedWorld => compiler.closedWorld; |
| 183 |
182 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; | 184 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; |
183 | 185 |
184 CodegenRegistry get registry => work.registry; | 186 CodegenRegistry get registry => work.registry; |
185 | 187 |
186 BackendHelpers get helpers => backend.helpers; | 188 BackendHelpers get helpers => backend.helpers; |
187 | 189 |
188 native.NativeEnqueuer get nativeEnqueuer { | 190 native.NativeEnqueuer get nativeEnqueuer { |
189 return compiler.enqueuer.codegen.nativeEnqueuer; | 191 return compiler.enqueuer.codegen.nativeEnqueuer; |
190 } | 192 } |
191 | 193 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 return math.max(leftWidth - shiftCount, 0); | 256 return math.max(leftWidth - shiftCount, 0); |
255 } | 257 } |
256 if (instruction is HAdd) { | 258 if (instruction is HAdd) { |
257 return math.min( | 259 return math.min( |
258 1 + math.max(bitWidth(instruction.left), bitWidth(instruction.right)), | 260 1 + math.max(bitWidth(instruction.left), bitWidth(instruction.right)), |
259 MAX); | 261 MAX); |
260 } | 262 } |
261 return MAX; | 263 return MAX; |
262 } | 264 } |
263 | 265 |
264 bool requiresUintConversion(instruction) { | 266 bool requiresUintConversion(HInstruction instruction) { |
265 if (instruction.isUInt31(compiler)) return false; | 267 if (instruction.isUInt31(closedWorld)) return false; |
266 if (bitWidth(instruction) <= 31) return false; | 268 if (bitWidth(instruction) <= 31) return false; |
267 // If the result of a bit-operation is only used by other bit | 269 // If the result of a bit-operation is only used by other bit |
268 // operations, we do not have to convert to an unsigned integer. | 270 // operations, we do not have to convert to an unsigned integer. |
269 return hasNonBitOpUser(instruction, new Set<HPhi>()); | 271 return hasNonBitOpUser(instruction, new Set<HPhi>()); |
270 } | 272 } |
271 | 273 |
272 /** | 274 /** |
273 * If the [instruction] is not `null` it will be used to attach the position | 275 * If the [instruction] is not `null` it will be used to attach the position |
274 * to the [statement]. | 276 * to the [statement]. |
275 */ | 277 */ |
(...skipping 1098 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1374 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); | 1376 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); |
1375 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); | 1377 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); |
1376 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&'); | 1378 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&'); |
1377 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~'); | 1379 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~'); |
1378 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|'); | 1380 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|'); |
1379 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^'); | 1381 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^'); |
1380 visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<'); | 1382 visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<'); |
1381 visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>'); | 1383 visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>'); |
1382 | 1384 |
1383 visitTruncatingDivide(HTruncatingDivide node) { | 1385 visitTruncatingDivide(HTruncatingDivide node) { |
1384 assert(node.isUInt31(compiler)); | 1386 assert(node.isUInt31(closedWorld)); |
1385 // TODO(karlklose): Enable this assertion again when type propagation is | 1387 // TODO(karlklose): Enable this assertion again when type propagation is |
1386 // fixed. Issue 23555. | 1388 // fixed. Issue 23555. |
1387 // assert(node.left.isUInt32(compiler)); | 1389 // assert(node.left.isUInt32(compiler)); |
1388 assert(node.right.isPositiveInteger(compiler)); | 1390 assert(node.right.isPositiveInteger(closedWorld)); |
1389 use(node.left); | 1391 use(node.left); |
1390 js.Expression jsLeft = pop(); | 1392 js.Expression jsLeft = pop(); |
1391 use(node.right); | 1393 use(node.right); |
1392 push(new js.Binary('/', jsLeft, pop()) | 1394 push(new js.Binary('/', jsLeft, pop()) |
1393 .withSourceInformation(node.sourceInformation)); | 1395 .withSourceInformation(node.sourceInformation)); |
1394 push(new js.Binary('|', pop(), new js.LiteralNumber("0")) | 1396 push(new js.Binary('|', pop(), new js.LiteralNumber("0")) |
1395 .withSourceInformation(node.sourceInformation)); | 1397 .withSourceInformation(node.sourceInformation)); |
1396 } | 1398 } |
1397 | 1399 |
1398 visitNegate(HNegate node) => visitInvokeUnary(node, '-'); | 1400 visitNegate(HNegate node) => visitInvokeUnary(node, '-'); |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1702 } | 1704 } |
1703 | 1705 |
1704 TypeMask getOptimizedSelectorFor( | 1706 TypeMask getOptimizedSelectorFor( |
1705 HInvokeDynamic node, Selector selector, TypeMask mask) { | 1707 HInvokeDynamic node, Selector selector, TypeMask mask) { |
1706 if (node.element != null) { | 1708 if (node.element != null) { |
1707 // Create an artificial type mask to make sure only | 1709 // Create an artificial type mask to make sure only |
1708 // [node.element] will be enqueued. We're not using the receiver | 1710 // [node.element] will be enqueued. We're not using the receiver |
1709 // type because our optimizations might end up in a state where the | 1711 // type because our optimizations might end up in a state where the |
1710 // invoke dynamic knows more than the receiver. | 1712 // invoke dynamic knows more than the receiver. |
1711 ClassElement enclosing = node.element.enclosingClass; | 1713 ClassElement enclosing = node.element.enclosingClass; |
1712 if (compiler.closedWorld.isInstantiated(enclosing)) { | 1714 if (closedWorld.isInstantiated(enclosing)) { |
1713 return new TypeMask.nonNullExact( | 1715 return new TypeMask.nonNullExact(enclosing.declaration, closedWorld); |
1714 enclosing.declaration, compiler.closedWorld); | |
1715 } else { | 1716 } else { |
1716 // The element is mixed in so a non-null subtype mask is the most | 1717 // The element is mixed in so a non-null subtype mask is the most |
1717 // precise we have. | 1718 // precise we have. |
1718 assert(invariant(node, compiler.closedWorld.isUsedAsMixin(enclosing), | 1719 assert(invariant(node, closedWorld.isUsedAsMixin(enclosing), |
1719 message: "Element ${node.element} from $enclosing expected " | 1720 message: "Element ${node.element} from $enclosing expected " |
1720 "to be mixed in.")); | 1721 "to be mixed in.")); |
1721 return new TypeMask.nonNullSubtype( | 1722 return new TypeMask.nonNullSubtype(enclosing.declaration, closedWorld); |
1722 enclosing.declaration, compiler.closedWorld); | |
1723 } | 1723 } |
1724 } | 1724 } |
1725 // If [JSInvocationMirror._invokeOn] is enabled, and this call | 1725 // If [JSInvocationMirror._invokeOn] is enabled, and this call |
1726 // might hit a `noSuchMethod`, we register an untyped selector. | 1726 // might hit a `noSuchMethod`, we register an untyped selector. |
1727 return compiler.closedWorld.extendMaskIfReachesAll(selector, mask); | 1727 return closedWorld.extendMaskIfReachesAll(selector, mask); |
1728 } | 1728 } |
1729 | 1729 |
1730 void registerMethodInvoke(HInvokeDynamic node) { | 1730 void registerMethodInvoke(HInvokeDynamic node) { |
1731 Selector selector = node.selector; | 1731 Selector selector = node.selector; |
1732 | 1732 |
1733 // If we don't know what we're calling or if we are calling a getter, | 1733 // If we don't know what we're calling or if we are calling a getter, |
1734 // we need to register that fact that we may be calling a closure | 1734 // we need to register that fact that we may be calling a closure |
1735 // with the same arguments. | 1735 // with the same arguments. |
1736 MemberElement target = node.element; | 1736 MemberElement target = node.element; |
1737 if (target == null || target.isGetter) { | 1737 if (target == null || target.isGetter) { |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2091 } | 2091 } |
2092 | 2092 |
2093 void generateNot(HInstruction input, SourceInformation sourceInformation) { | 2093 void generateNot(HInstruction input, SourceInformation sourceInformation) { |
2094 bool canGenerateOptimizedComparison(HInstruction instruction) { | 2094 bool canGenerateOptimizedComparison(HInstruction instruction) { |
2095 if (instruction is! HRelational) return false; | 2095 if (instruction is! HRelational) return false; |
2096 | 2096 |
2097 HRelational relational = instruction; | 2097 HRelational relational = instruction; |
2098 | 2098 |
2099 HInstruction left = relational.left; | 2099 HInstruction left = relational.left; |
2100 HInstruction right = relational.right; | 2100 HInstruction right = relational.right; |
2101 if (left.isStringOrNull(compiler) && right.isStringOrNull(compiler)) { | 2101 if (left.isStringOrNull(closedWorld) && |
| 2102 right.isStringOrNull(closedWorld)) { |
2102 return true; | 2103 return true; |
2103 } | 2104 } |
2104 | 2105 |
2105 // This optimization doesn't work for NaN, so we only do it if the | 2106 // This optimization doesn't work for NaN, so we only do it if the |
2106 // type is known to be an integer. | 2107 // type is known to be an integer. |
2107 return left.isInteger(compiler) && right.isInteger(compiler); | 2108 return left.isInteger(closedWorld) && right.isInteger(closedWorld); |
2108 } | 2109 } |
2109 | 2110 |
2110 bool handledBySpecialCase = false; | 2111 bool handledBySpecialCase = false; |
2111 if (isGenerateAtUseSite(input)) { | 2112 if (isGenerateAtUseSite(input)) { |
2112 handledBySpecialCase = true; | 2113 handledBySpecialCase = true; |
2113 if (input is HIs) { | 2114 if (input is HIs) { |
2114 emitIs(input, '!==', sourceInformation); | 2115 emitIs(input, '!==', sourceInformation); |
2115 } else if (input is HIsViaInterceptor) { | 2116 } else if (input is HIsViaInterceptor) { |
2116 emitIsViaInterceptor(input, sourceInformation, negative: true); | 2117 emitIsViaInterceptor(input, sourceInformation, negative: true); |
2117 } else if (input is HNot) { | 2118 } else if (input is HNot) { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2233 // e.g., the zero checks can be shared if possible. | 2234 // e.g., the zero checks can be shared if possible. |
2234 | 2235 |
2235 // If the checks always succeeds, we would have removed the bounds check | 2236 // If the checks always succeeds, we would have removed the bounds check |
2236 // completely. | 2237 // completely. |
2237 assert(node.staticChecks != HBoundsCheck.ALWAYS_TRUE); | 2238 assert(node.staticChecks != HBoundsCheck.ALWAYS_TRUE); |
2238 if (node.staticChecks != HBoundsCheck.ALWAYS_FALSE) { | 2239 if (node.staticChecks != HBoundsCheck.ALWAYS_FALSE) { |
2239 js.Expression under; | 2240 js.Expression under; |
2240 js.Expression over; | 2241 js.Expression over; |
2241 if (node.staticChecks != HBoundsCheck.ALWAYS_ABOVE_ZERO) { | 2242 if (node.staticChecks != HBoundsCheck.ALWAYS_ABOVE_ZERO) { |
2242 use(node.index); | 2243 use(node.index); |
2243 if (node.index.isInteger(compiler)) { | 2244 if (node.index.isInteger(closedWorld)) { |
2244 under = js.js("# < 0", pop()); | 2245 under = js.js("# < 0", pop()); |
2245 } else { | 2246 } else { |
2246 js.Expression jsIndex = pop(); | 2247 js.Expression jsIndex = pop(); |
2247 under = js.js("# >>> 0 !== #", [jsIndex, jsIndex]); | 2248 under = js.js("# >>> 0 !== #", [jsIndex, jsIndex]); |
2248 } | 2249 } |
2249 } else if (!node.index.isInteger(compiler)) { | 2250 } else if (!node.index.isInteger(closedWorld)) { |
2250 checkInt(node.index, '!=='); | 2251 checkInt(node.index, '!=='); |
2251 under = pop(); | 2252 under = pop(); |
2252 } | 2253 } |
2253 if (node.staticChecks != HBoundsCheck.ALWAYS_BELOW_LENGTH) { | 2254 if (node.staticChecks != HBoundsCheck.ALWAYS_BELOW_LENGTH) { |
2254 var index = node.index; | 2255 var index = node.index; |
2255 use(index); | 2256 use(index); |
2256 js.Expression jsIndex = pop(); | 2257 js.Expression jsIndex = pop(); |
2257 use(node.length); | 2258 use(node.length); |
2258 over = new js.Binary(">=", jsIndex, pop()); | 2259 over = new js.Binary(">=", jsIndex, pop()); |
2259 } | 2260 } |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2369 void visitStringConcat(HStringConcat node) { | 2370 void visitStringConcat(HStringConcat node) { |
2370 use(node.left); | 2371 use(node.left); |
2371 js.Expression jsLeft = pop(); | 2372 js.Expression jsLeft = pop(); |
2372 use(node.right); | 2373 use(node.right); |
2373 push(new js.Binary('+', jsLeft, pop()) | 2374 push(new js.Binary('+', jsLeft, pop()) |
2374 .withSourceInformation(node.sourceInformation)); | 2375 .withSourceInformation(node.sourceInformation)); |
2375 } | 2376 } |
2376 | 2377 |
2377 void visitStringify(HStringify node) { | 2378 void visitStringify(HStringify node) { |
2378 HInstruction input = node.inputs.first; | 2379 HInstruction input = node.inputs.first; |
2379 if (input.isString(compiler)) { | 2380 if (input.isString(closedWorld)) { |
2380 use(input); | 2381 use(input); |
2381 } else if (input.isInteger(compiler) || input.isBoolean(compiler)) { | 2382 } else if (input.isInteger(closedWorld) || input.isBoolean(closedWorld)) { |
2382 // JavaScript's + operator with a string for the left operand will convert | 2383 // JavaScript's + operator with a string for the left operand will convert |
2383 // the right operand to a string, and the conversion result is correct. | 2384 // the right operand to a string, and the conversion result is correct. |
2384 use(input); | 2385 use(input); |
2385 if (node.usedBy.length == 1 && | 2386 if (node.usedBy.length == 1 && |
2386 node.usedBy[0] is HStringConcat && | 2387 node.usedBy[0] is HStringConcat && |
2387 node.usedBy[0].inputs[1] == node) { | 2388 node.usedBy[0].inputs[1] == node) { |
2388 // The context is already <string> + value. | 2389 // The context is already <string> + value. |
2389 } else { | 2390 } else { |
2390 // Force an empty string for the first operand. | 2391 // Force an empty string for the first operand. |
2391 push(new js.Binary('+', js.string(""), pop()) | 2392 push(new js.Binary('+', js.string(""), pop()) |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2754 } else if (Elements.isStringOnlySupertype(element, compiler)) { | 2755 } else if (Elements.isStringOnlySupertype(element, compiler)) { |
2755 handleStringSupertypeCheck(input, interceptor, type, sourceInformation, | 2756 handleStringSupertypeCheck(input, interceptor, type, sourceInformation, |
2756 negative: negative); | 2757 negative: negative); |
2757 } else if (identical(element, coreClasses.listClass) || | 2758 } else if (identical(element, coreClasses.listClass) || |
2758 Elements.isListSupertype(element, compiler)) { | 2759 Elements.isListSupertype(element, compiler)) { |
2759 handleListOrSupertypeCheck(input, interceptor, type, sourceInformation, | 2760 handleListOrSupertypeCheck(input, interceptor, type, sourceInformation, |
2760 negative: negative); | 2761 negative: negative); |
2761 } else if (type.isFunctionType) { | 2762 } else if (type.isFunctionType) { |
2762 checkType(input, interceptor, type, sourceInformation, | 2763 checkType(input, interceptor, type, sourceInformation, |
2763 negative: negative); | 2764 negative: negative); |
2764 } else if ((input.canBePrimitive(compiler) && | 2765 } else if ((input.canBePrimitive(closedWorld) && |
2765 !input.canBePrimitiveArray(compiler)) || | 2766 !input.canBePrimitiveArray(closedWorld)) || |
2766 input.canBeNull()) { | 2767 input.canBeNull()) { |
2767 checkObject(input, relation, node.sourceInformation); | 2768 checkObject(input, relation, node.sourceInformation); |
2768 js.Expression objectTest = pop(); | 2769 js.Expression objectTest = pop(); |
2769 checkType(input, interceptor, type, sourceInformation, | 2770 checkType(input, interceptor, type, sourceInformation, |
2770 negative: negative); | 2771 negative: negative); |
2771 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()) | 2772 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()) |
2772 .withSourceInformation(sourceInformation)); | 2773 .withSourceInformation(sourceInformation)); |
2773 } else { | 2774 } else { |
2774 checkType(input, interceptor, type, sourceInformation, | 2775 checkType(input, interceptor, type, sourceInformation, |
2775 negative: negative); | 2776 negative: negative); |
2776 } | 2777 } |
2777 } | 2778 } |
2778 } | 2779 } |
2779 | 2780 |
2780 void emitIsViaInterceptor( | 2781 void emitIsViaInterceptor( |
2781 HIsViaInterceptor node, SourceInformation sourceInformation, | 2782 HIsViaInterceptor node, SourceInformation sourceInformation, |
2782 {bool negative: false}) { | 2783 {bool negative: false}) { |
2783 checkTypeViaProperty( | 2784 checkTypeViaProperty( |
2784 node.interceptor, node.typeExpression, sourceInformation, | 2785 node.interceptor, node.typeExpression, sourceInformation, |
2785 negative: negative); | 2786 negative: negative); |
2786 } | 2787 } |
2787 | 2788 |
2788 js.Expression generateReceiverOrArgumentTypeTest( | 2789 js.Expression generateReceiverOrArgumentTypeTest( |
2789 HInstruction input, TypeMask checkedType) { | 2790 HInstruction input, TypeMask checkedType) { |
2790 ClosedWorld closedWorld = compiler.closedWorld; | |
2791 TypeMask inputType = input.instructionType; | 2791 TypeMask inputType = input.instructionType; |
2792 // Figure out if it is beneficial to turn this into a null check. | 2792 // Figure out if it is beneficial to turn this into a null check. |
2793 // V8 generally prefers 'typeof' checks, but for integers and | 2793 // V8 generally prefers 'typeof' checks, but for integers and |
2794 // indexable primitives we cannot compile this test into a single | 2794 // indexable primitives we cannot compile this test into a single |
2795 // typeof check so the null check is cheaper. | 2795 // typeof check so the null check is cheaper. |
2796 bool isIntCheck = checkedType.containsOnlyInt(closedWorld); | 2796 bool isIntCheck = checkedType.containsOnlyInt(closedWorld); |
2797 bool turnIntoNumCheck = isIntCheck && input.isIntegerOrNull(compiler); | 2797 bool turnIntoNumCheck = isIntCheck && input.isIntegerOrNull(closedWorld); |
2798 bool turnIntoNullCheck = !turnIntoNumCheck && | 2798 bool turnIntoNullCheck = !turnIntoNumCheck && |
2799 (checkedType.nullable() == inputType) && | 2799 (checkedType.nullable() == inputType) && |
2800 (isIntCheck || | 2800 (isIntCheck || |
2801 checkedType.satisfies(helpers.jsIndexableClass, closedWorld)); | 2801 checkedType.satisfies(helpers.jsIndexableClass, closedWorld)); |
2802 | 2802 |
2803 if (turnIntoNullCheck) { | 2803 if (turnIntoNullCheck) { |
2804 use(input); | 2804 use(input); |
2805 return new js.Binary("==", pop(), new js.LiteralNull()) | 2805 return new js.Binary("==", pop(), new js.LiteralNull()) |
2806 .withSourceInformation(input.sourceInformation); | 2806 .withSourceInformation(input.sourceInformation); |
2807 } else if (isIntCheck && !turnIntoNumCheck) { | 2807 } else if (isIntCheck && !turnIntoNumCheck) { |
(...skipping 12 matching lines...) Expand all Loading... |
2820 // input is !string | 2820 // input is !string |
2821 checkString(input, '!==', input.sourceInformation); | 2821 checkString(input, '!==', input.sourceInformation); |
2822 return pop(); | 2822 return pop(); |
2823 } | 2823 } |
2824 reporter.internalError(input, 'Unexpected check: $checkedType.'); | 2824 reporter.internalError(input, 'Unexpected check: $checkedType.'); |
2825 return null; | 2825 return null; |
2826 } | 2826 } |
2827 | 2827 |
2828 void visitTypeConversion(HTypeConversion node) { | 2828 void visitTypeConversion(HTypeConversion node) { |
2829 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { | 2829 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { |
2830 ClosedWorld closedWorld = compiler.closedWorld; | |
2831 // An int check if the input is not int or null, is not | 2830 // An int check if the input is not int or null, is not |
2832 // sufficient for doing an argument or receiver check. | 2831 // sufficient for doing an argument or receiver check. |
2833 assert(compiler.options.trustTypeAnnotations || | 2832 assert(compiler.options.trustTypeAnnotations || |
2834 !node.checkedType.containsOnlyInt(closedWorld) || | 2833 !node.checkedType.containsOnlyInt(closedWorld) || |
2835 node.checkedInput.isIntegerOrNull(compiler)); | 2834 node.checkedInput.isIntegerOrNull(closedWorld)); |
2836 js.Expression test = generateReceiverOrArgumentTypeTest( | 2835 js.Expression test = generateReceiverOrArgumentTypeTest( |
2837 node.checkedInput, node.checkedType); | 2836 node.checkedInput, node.checkedType); |
2838 js.Block oldContainer = currentContainer; | 2837 js.Block oldContainer = currentContainer; |
2839 js.Statement body = new js.Block.empty(); | 2838 js.Statement body = new js.Block.empty(); |
2840 currentContainer = body; | 2839 currentContainer = body; |
2841 if (node.isArgumentTypeCheck) { | 2840 if (node.isArgumentTypeCheck) { |
2842 generateThrowWithHelper( | 2841 generateThrowWithHelper( |
2843 helpers.throwIllegalArgumentException, node.checkedInput, | 2842 helpers.throwIllegalArgumentException, node.checkedInput, |
2844 sourceInformation: node.sourceInformation); | 2843 sourceInformation: node.sourceInformation); |
2845 } else if (node.isReceiverTypeCheck) { | 2844 } else if (node.isReceiverTypeCheck) { |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3003 node.dartType == (node.dartType.element as ClassElement).thisType); | 3002 node.dartType == (node.dartType.element as ClassElement).thisType); |
3004 registry.registerInstantiatedClass(coreClasses.listClass); | 3003 registry.registerInstantiatedClass(coreClasses.listClass); |
3005 push(new js.ArrayInitializer(arguments) | 3004 push(new js.ArrayInitializer(arguments) |
3006 .withSourceInformation(node.sourceInformation)); | 3005 .withSourceInformation(node.sourceInformation)); |
3007 } | 3006 } |
3008 } | 3007 } |
3009 | 3008 |
3010 bool typeVariableAccessNeedsSubstitution( | 3009 bool typeVariableAccessNeedsSubstitution( |
3011 TypeVariableElement element, TypeMask receiverMask) { | 3010 TypeVariableElement element, TypeMask receiverMask) { |
3012 ClassElement cls = element.enclosingClass; | 3011 ClassElement cls = element.enclosingClass; |
3013 ClosedWorld closedWorld = compiler.closedWorld; | |
3014 | 3012 |
3015 // See if the receiver type narrows the set of classes to ones that can be | 3013 // See if the receiver type narrows the set of classes to ones that can be |
3016 // indexed. | 3014 // indexed. |
3017 // TODO(sra): Currently the only convenient query is [singleClass]. We | 3015 // TODO(sra): Currently the only convenient query is [singleClass]. We |
3018 // should iterate over all the concrete classes in [receiverMask]. | 3016 // should iterate over all the concrete classes in [receiverMask]. |
3019 ClassElement receiverClass = receiverMask.singleClass(closedWorld); | 3017 ClassElement receiverClass = receiverMask.singleClass(closedWorld); |
3020 if (receiverClass != null) { | 3018 if (receiverClass != null) { |
3021 if (backend.rti.isTrivialSubstitution(receiverClass, cls)) { | 3019 if (backend.rti.isTrivialSubstitution(receiverClass, cls)) { |
3022 return false; | 3020 return false; |
3023 } | 3021 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3096 registry.registerStaticUse(new StaticUse.staticInvoke( | 3094 registry.registerStaticUse(new StaticUse.staticInvoke( |
3097 helper, new CallStructure.unnamed(argumentCount))); | 3095 helper, new CallStructure.unnamed(argumentCount))); |
3098 return backend.emitter.staticFunctionAccess(helper); | 3096 return backend.emitter.staticFunctionAccess(helper); |
3099 } | 3097 } |
3100 | 3098 |
3101 @override | 3099 @override |
3102 void visitRef(HRef node) { | 3100 void visitRef(HRef node) { |
3103 visit(node.value); | 3101 visit(node.value); |
3104 } | 3102 } |
3105 } | 3103 } |
OLD | NEW |