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 part of ssa; | 5 part of ssa; |
6 | 6 |
7 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 void redirectElement(Local from, CapturedVariable to) { | 235 void redirectElement(Local from, CapturedVariable to) { |
236 assert(redirectionMapping[from] == null); | 236 assert(redirectionMapping[from] == null); |
237 redirectionMapping[from] = to; | 237 redirectionMapping[from] = to; |
238 assert(isStoredInClosureField(from) || isBoxed(from)); | 238 assert(isStoredInClosureField(from) || isBoxed(from)); |
239 } | 239 } |
240 | 240 |
241 HInstruction createBox() { | 241 HInstruction createBox() { |
242 // TODO(floitsch): Clean up this hack. Should we create a box-object by | 242 // TODO(floitsch): Clean up this hack. Should we create a box-object by |
243 // just creating an empty object literal? | 243 // just creating an empty object literal? |
244 JavaScriptBackend backend = builder.backend; | 244 JavaScriptBackend backend = builder.backend; |
245 HInstruction box = new HForeignCode(js.js.parseForeignJS('{}'), | 245 HInstruction box = new HForeignCode( |
246 backend.nonNullType, | 246 js.js.parseForeignJS('{}'), |
247 <HInstruction>[]); | 247 backend.nonNullType, |
| 248 <HInstruction>[], |
| 249 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION); |
248 builder.add(box); | 250 builder.add(box); |
249 return box; | 251 return box; |
250 } | 252 } |
251 | 253 |
252 /** | 254 /** |
253 * If the scope (function or loop) [node] has captured variables then this | 255 * If the scope (function or loop) [node] has captured variables then this |
254 * method creates a box and sets up the redirections. | 256 * method creates a box and sets up the redirections. |
255 */ | 257 */ |
256 void enterScope(ast.Node node, Element element) { | 258 void enterScope(ast.Node node, Element element) { |
257 // See if any variable in the top-scope of the function is captured. If yes | 259 // See if any variable in the top-scope of the function is captured. If yes |
(...skipping 3141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3399 localsHandler.updateLocal(local, checkedOrTrusted); | 3401 localsHandler.updateLocal(local, checkedOrTrusted); |
3400 } | 3402 } |
3401 } | 3403 } |
3402 | 3404 |
3403 HInstruction invokeInterceptor(HInstruction receiver) { | 3405 HInstruction invokeInterceptor(HInstruction receiver) { |
3404 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); | 3406 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); |
3405 add(interceptor); | 3407 add(interceptor); |
3406 return interceptor; | 3408 return interceptor; |
3407 } | 3409 } |
3408 | 3410 |
3409 HForeignCode createForeign(js.Template code, | |
3410 TypeMask type, | |
3411 List<HInstruction> inputs) { | |
3412 return new HForeignCode(code, type, inputs); | |
3413 } | |
3414 | |
3415 HLiteralList buildLiteralList(List<HInstruction> inputs) { | 3411 HLiteralList buildLiteralList(List<HInstruction> inputs) { |
3416 return new HLiteralList(inputs, backend.extendableArrayType); | 3412 return new HLiteralList(inputs, backend.extendableArrayType); |
3417 } | 3413 } |
3418 | 3414 |
3419 // TODO(karlklose): change construction of the representations to be GVN'able | 3415 // TODO(karlklose): change construction of the representations to be GVN'able |
3420 // (dartbug.com/7182). | 3416 // (dartbug.com/7182). |
3421 HInstruction buildTypeArgumentRepresentations(DartType type) { | 3417 HInstruction buildTypeArgumentRepresentations(DartType type) { |
3422 // Compute the representation of the type arguments, including access | 3418 // Compute the representation of the type arguments, including access |
3423 // to the runtime type information for type variables as instructions. | 3419 // to the runtime type information for type variables as instructions. |
3424 if (type.isTypeVariable) { | 3420 if (type.isTypeVariable) { |
3425 return buildLiteralList(<HInstruction>[addTypeVariableReference(type)]); | 3421 return buildLiteralList(<HInstruction>[addTypeVariableReference(type)]); |
3426 } else { | 3422 } else { |
3427 assert(type.element.isClass); | 3423 assert(type.element.isClass); |
3428 InterfaceType interface = type; | 3424 InterfaceType interface = type; |
3429 List<HInstruction> inputs = <HInstruction>[]; | 3425 List<HInstruction> inputs = <HInstruction>[]; |
3430 bool first = true; | 3426 bool first = true; |
3431 List<String> templates = <String>[]; | 3427 List<String> templates = <String>[]; |
3432 for (DartType argument in interface.typeArguments) { | 3428 for (DartType argument in interface.typeArguments) { |
3433 templates.add(rti.getTypeRepresentationWithHashes(argument, (variable) { | 3429 templates.add(rti.getTypeRepresentationWithHashes(argument, (variable) { |
3434 HInstruction runtimeType = addTypeVariableReference(variable); | 3430 HInstruction runtimeType = addTypeVariableReference(variable); |
3435 inputs.add(runtimeType); | 3431 inputs.add(runtimeType); |
3436 })); | 3432 })); |
3437 } | 3433 } |
3438 String template = '[${templates.join(', ')}]'; | 3434 String template = '[${templates.join(', ')}]'; |
3439 // TODO(sra): This is a fresh template each time. We can't let the | 3435 // TODO(sra): This is a fresh template each time. We can't let the |
3440 // template manager build them. | 3436 // template manager build them. |
3441 js.Template code = js.js.uncachedExpressionTemplate(template); | 3437 js.Template code = js.js.uncachedExpressionTemplate(template); |
3442 HInstruction representation = | 3438 HInstruction representation = |
3443 createForeign(code, backend.readableArrayType, inputs); | 3439 new HForeignCode(code, backend.readableArrayType, inputs, |
| 3440 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION); |
3444 return representation; | 3441 return representation; |
3445 } | 3442 } |
3446 } | 3443 } |
3447 | 3444 |
3448 visitOperatorSend(ast.Send node) { | 3445 visitOperatorSend(ast.Send node) { |
3449 ast.Operator op = node.selector; | 3446 ast.Operator op = node.selector; |
3450 if ("[]" == op.source) { | 3447 if ("[]" == op.source) { |
3451 visitDynamicSend(node); | 3448 visitDynamicSend(node); |
3452 } else if ("&&" == op.source || | 3449 } else if ("&&" == op.source || |
3453 "||" == op.source) { | 3450 "||" == op.source) { |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3647 inputs.add(closureTarget); | 3644 inputs.add(closureTarget); |
3648 addDynamicSendArgumentsToList(node, inputs); | 3645 addDynamicSendArgumentsToList(node, inputs); |
3649 Selector closureSelector = new Selector.callClosureFrom(selector); | 3646 Selector closureSelector = new Selector.callClosureFrom(selector); |
3650 pushWithPosition( | 3647 pushWithPosition( |
3651 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), | 3648 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), |
3652 node); | 3649 node); |
3653 } | 3650 } |
3654 | 3651 |
3655 void handleForeignJs(ast.Send node) { | 3652 void handleForeignJs(ast.Send node) { |
3656 Link<ast.Node> link = node.arguments; | 3653 Link<ast.Node> link = node.arguments; |
3657 // If the invoke is on foreign code, don't visit the first | 3654 // Don't visit the first argument, which is the type, and the second |
3658 // argument, which is the type, and the second argument, | 3655 // argument, which is the foreign code. |
3659 // which is the foreign code. | |
3660 if (link.isEmpty || link.tail.isEmpty) { | 3656 if (link.isEmpty || link.tail.isEmpty) { |
3661 compiler.internalError(node.argumentsNode, | 3657 compiler.internalError(node.argumentsNode, |
3662 'At least two arguments expected.'); | 3658 'At least two arguments expected.'); |
3663 } | 3659 } |
3664 native.NativeBehavior nativeBehavior = | 3660 native.NativeBehavior nativeBehavior = |
3665 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); | 3661 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
3666 | 3662 |
3667 List<HInstruction> inputs = <HInstruction>[]; | 3663 List<HInstruction> inputs = <HInstruction>[]; |
3668 addGenericSendArgumentsToList(link.tail.tail, inputs); | 3664 addGenericSendArgumentsToList(link.tail.tail, inputs); |
3669 | 3665 |
3670 TypeMask ssaType = | 3666 TypeMask ssaType = |
3671 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); | 3667 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
3672 | 3668 |
3673 if (nativeBehavior.codeTemplate.isExpression) { | 3669 if (nativeBehavior.codeTemplate.isExpression) { |
3674 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs, | 3670 push(new HForeignCode( |
3675 effects: nativeBehavior.sideEffects, | 3671 nativeBehavior.codeTemplate, ssaType, inputs, |
3676 nativeBehavior: nativeBehavior)); | 3672 effects: nativeBehavior.sideEffects, |
| 3673 nativeBehavior: nativeBehavior)); |
3677 } else { | 3674 } else { |
3678 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs, | 3675 push(new HForeignCode( |
3679 isStatement: true, | 3676 nativeBehavior.codeTemplate, ssaType, inputs, |
3680 effects: nativeBehavior.sideEffects, | 3677 isStatement: true, |
3681 nativeBehavior: nativeBehavior, | 3678 effects: nativeBehavior.sideEffects, |
3682 canThrow: true)); | 3679 nativeBehavior: nativeBehavior)); |
3683 } | 3680 } |
3684 } | 3681 } |
3685 | 3682 |
3686 void handleJsStringConcat(ast.Send node) { | 3683 void handleJsStringConcat(ast.Send node) { |
3687 List<HInstruction> inputs = <HInstruction>[]; | 3684 List<HInstruction> inputs = <HInstruction>[]; |
3688 addGenericSendArgumentsToList(node.arguments, inputs); | 3685 addGenericSendArgumentsToList(node.arguments, inputs); |
3689 if (inputs.length != 2) { | 3686 if (inputs.length != 2) { |
3690 compiler.internalError(node.argumentsNode, 'Two arguments expected.'); | 3687 compiler.internalError(node.argumentsNode, 'Two arguments expected.'); |
3691 } | 3688 } |
3692 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); | 3689 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3831 } | 3828 } |
3832 HConstant hConstant = globalNameHNode; | 3829 HConstant hConstant = globalNameHNode; |
3833 StringConstantValue constant = hConstant.constant; | 3830 StringConstantValue constant = hConstant.constant; |
3834 String globalName = constant.primitiveValue.slowToString(); | 3831 String globalName = constant.primitiveValue.slowToString(); |
3835 js.Template expr = js.js.expressionTemplateYielding( | 3832 js.Template expr = js.js.expressionTemplateYielding( |
3836 backend.emitter.generateEmbeddedGlobalAccess(globalName)); | 3833 backend.emitter.generateEmbeddedGlobalAccess(globalName)); |
3837 native.NativeBehavior nativeBehavior = | 3834 native.NativeBehavior nativeBehavior = |
3838 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); | 3835 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
3839 TypeMask ssaType = | 3836 TypeMask ssaType = |
3840 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); | 3837 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
3841 push(new HForeignCode(expr, ssaType, const [])); | 3838 push(new HForeignCode(expr, ssaType, const [], |
| 3839 nativeBehavior: nativeBehavior)); |
3842 } | 3840 } |
3843 | 3841 |
3844 void handleJsInterceptorConstant(ast.Send node) { | 3842 void handleJsInterceptorConstant(ast.Send node) { |
3845 // Single argument must be a TypeConstant which is converted into a | 3843 // Single argument must be a TypeConstant which is converted into a |
3846 // InterceptorConstant. | 3844 // InterceptorConstant. |
3847 if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) { | 3845 if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) { |
3848 ast.Node argument = node.arguments.head; | 3846 ast.Node argument = node.arguments.head; |
3849 visit(argument); | 3847 visit(argument); |
3850 HInstruction argumentInstruction = pop(); | 3848 HInstruction argumentInstruction = pop(); |
3851 if (argumentInstruction is HConstant) { | 3849 if (argumentInstruction is HConstant) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3903 // and implementation signatures. Currently it is need because the | 3901 // and implementation signatures. Currently it is need because the |
3904 // signatures have different elements for parameters. | 3902 // signatures have different elements for parameters. |
3905 FunctionElement implementation = function.implementation; | 3903 FunctionElement implementation = function.implementation; |
3906 FunctionSignature params = implementation.functionSignature; | 3904 FunctionSignature params = implementation.functionSignature; |
3907 if (params.optionalParameterCount != 0) { | 3905 if (params.optionalParameterCount != 0) { |
3908 compiler.internalError(closure, | 3906 compiler.internalError(closure, |
3909 '"$name" does not handle closure with optional parameters.'); | 3907 '"$name" does not handle closure with optional parameters.'); |
3910 } | 3908 } |
3911 | 3909 |
3912 registry.registerStaticUse(element); | 3910 registry.registerStaticUse(element); |
3913 push(new HForeignCode(js.js.expressionTemplateYielding( | 3911 push(new HForeignCode( |
3914 backend.emitter.staticFunctionAccess(element)), | 3912 js.js.expressionTemplateYielding( |
3915 backend.dynamicType, | 3913 backend.emitter.staticFunctionAccess(element)), |
3916 <HInstruction>[])); | 3914 backend.dynamicType, |
| 3915 <HInstruction>[], |
| 3916 nativeBehavior: native.NativeBehavior.PURE)); |
3917 return params; | 3917 return params; |
3918 } | 3918 } |
3919 | 3919 |
3920 void handleForeignDartClosureToJs(ast.Send node, String name) { | 3920 void handleForeignDartClosureToJs(ast.Send node, String name) { |
3921 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take | 3921 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take |
3922 // care to wrap the closure in another closure that saves the current | 3922 // care to wrap the closure in another closure that saves the current |
3923 // isolate. | 3923 // isolate. |
3924 handleForeignRawFunctionRef(node, name); | 3924 handleForeignRawFunctionRef(node, name); |
3925 } | 3925 } |
3926 | 3926 |
3927 void handleForeignSetCurrentIsolate(ast.Send node) { | 3927 void handleForeignSetCurrentIsolate(ast.Send node) { |
3928 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { | 3928 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
3929 compiler.internalError(node.argumentsNode, | 3929 compiler.internalError(node.argumentsNode, |
3930 'Exactly one argument required.'); | 3930 'Exactly one argument required.'); |
3931 } | 3931 } |
3932 visit(node.arguments.head); | 3932 visit(node.arguments.head); |
3933 String isolateName = backend.namer.currentIsolate; | 3933 String isolateName = backend.namer.currentIsolate; |
3934 SideEffects sideEffects = new SideEffects.empty(); | 3934 SideEffects sideEffects = new SideEffects.empty(); |
3935 sideEffects.setAllSideEffects(); | 3935 sideEffects.setAllSideEffects(); |
3936 push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"), | 3936 push(new HForeignCode( |
3937 backend.dynamicType, | 3937 js.js.parseForeignJS("$isolateName = #"), |
3938 <HInstruction>[pop()], | 3938 backend.dynamicType, |
3939 effects: sideEffects)); | 3939 <HInstruction>[pop()], |
| 3940 nativeBehavior: native.NativeBehavior.PURE, |
| 3941 effects: sideEffects)); |
3940 } | 3942 } |
3941 | 3943 |
3942 void handleForeignDartObjectJsConstructorFunction(ast.Send node) { | 3944 void handleForeignDartObjectJsConstructorFunction(ast.Send node) { |
3943 if (!node.arguments.isEmpty) { | 3945 if (!node.arguments.isEmpty) { |
3944 compiler.internalError(node.argumentsNode, 'Too many arguments.'); | 3946 compiler.internalError(node.argumentsNode, 'Too many arguments.'); |
3945 } | 3947 } |
3946 push(new HForeignCode(js.js.expressionTemplateYielding( | 3948 push(new HForeignCode( |
3947 backend.emitter.typeAccess(compiler.objectClass)), | 3949 js.js.expressionTemplateYielding( |
3948 backend.dynamicType, | 3950 backend.emitter.typeAccess(compiler.objectClass)), |
3949 <HInstruction>[])); | 3951 backend.dynamicType, |
| 3952 <HInstruction>[])); |
3950 } | 3953 } |
3951 | 3954 |
3952 void handleForeignJsCurrentIsolate(ast.Send node) { | 3955 void handleForeignJsCurrentIsolate(ast.Send node) { |
3953 if (!node.arguments.isEmpty) { | 3956 if (!node.arguments.isEmpty) { |
3954 compiler.internalError(node.argumentsNode, 'Too many arguments.'); | 3957 compiler.internalError(node.argumentsNode, 'Too many arguments.'); |
3955 } | 3958 } |
3956 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), | 3959 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), |
3957 backend.dynamicType, | 3960 backend.dynamicType, |
3958 <HInstruction>[])); | 3961 <HInstruction>[])); |
3959 } | 3962 } |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4271 return addTypeVariableReference(argument); | 4274 return addTypeVariableReference(argument); |
4272 } | 4275 } |
4273 | 4276 |
4274 List<HInstruction> inputs = <HInstruction>[]; | 4277 List<HInstruction> inputs = <HInstruction>[]; |
4275 | 4278 |
4276 String template = rti.getTypeRepresentationWithHashes(argument, (variable) { | 4279 String template = rti.getTypeRepresentationWithHashes(argument, (variable) { |
4277 inputs.add(addTypeVariableReference(variable)); | 4280 inputs.add(addTypeVariableReference(variable)); |
4278 }); | 4281 }); |
4279 | 4282 |
4280 js.Template code = js.js.uncachedExpressionTemplate(template); | 4283 js.Template code = js.js.uncachedExpressionTemplate(template); |
4281 HInstruction result = createForeign(code, backend.stringType, inputs); | 4284 HInstruction result = new HForeignCode(code, backend.stringType, inputs, |
| 4285 nativeBehavior: native.NativeBehavior.PURE); |
4282 add(result); | 4286 add(result); |
4283 return result; | 4287 return result; |
4284 } | 4288 } |
4285 | 4289 |
4286 HInstruction handleListConstructor(InterfaceType type, | 4290 HInstruction handleListConstructor(InterfaceType type, |
4287 ast.Node currentNode, | 4291 ast.Node currentNode, |
4288 HInstruction newObject) { | 4292 HInstruction newObject) { |
4289 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 4293 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
4290 return newObject; | 4294 return newObject; |
4291 } | 4295 } |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4438 js.Template code = js.js.parseForeignJS('Array(#)'); | 4442 js.Template code = js.js.parseForeignJS('Array(#)'); |
4439 var behavior = new native.NativeBehavior(); | 4443 var behavior = new native.NativeBehavior(); |
4440 behavior.typesReturned.add(expectedType); | 4444 behavior.typesReturned.add(expectedType); |
4441 // The allocation can throw only if the given length is a double | 4445 // The allocation can throw only if the given length is a double |
4442 // or negative. | 4446 // or negative. |
4443 bool canThrow = true; | 4447 bool canThrow = true; |
4444 if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) { | 4448 if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) { |
4445 var constant = inputs[0]; | 4449 var constant = inputs[0]; |
4446 if (constant.constant.primitiveValue >= 0) canThrow = false; | 4450 if (constant.constant.primitiveValue >= 0) canThrow = false; |
4447 } | 4451 } |
4448 HForeignCode foreign = new HForeignCode( | 4452 HForeignCode foreign = new HForeignCode(code, elementType, inputs, |
4449 code, elementType, inputs, nativeBehavior: behavior, | 4453 nativeBehavior: behavior, |
4450 canThrow: canThrow); | 4454 throwBehavior: canThrow |
| 4455 ? native.NativeThrowBehavior.MAY |
| 4456 : native.NativeThrowBehavior.NEVER); |
4451 push(foreign); | 4457 push(foreign); |
4452 TypesInferrer inferrer = compiler.typesTask.typesInferrer; | 4458 TypesInferrer inferrer = compiler.typesTask.typesInferrer; |
4453 if (inferrer.isFixedArrayCheckedForGrowable(send)) { | 4459 if (inferrer.isFixedArrayCheckedForGrowable(send)) { |
4454 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); | 4460 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); |
4455 // We set the instruction as [canThrow] to avoid it being dead code. | 4461 // We set the instruction as [canThrow] to avoid it being dead code. |
4456 // We need a finer grained side effect. | 4462 // We need a finer grained side effect. |
4457 add(new HForeignCode( | 4463 add(new HForeignCode(code, backend.nullType, [stack.last], |
4458 code, backend.nullType, [stack.last], canThrow: true)); | 4464 throwBehavior: native.NativeThrowBehavior.MAY)); |
4459 } | 4465 } |
4460 } else if (isGrowableListConstructorCall) { | 4466 } else if (isGrowableListConstructorCall) { |
4461 push(buildLiteralList(<HInstruction>[])); | 4467 push(buildLiteralList(<HInstruction>[])); |
4462 stack.last.instructionType = elementType; | 4468 stack.last.instructionType = elementType; |
4463 } else { | 4469 } else { |
4464 ClassElement cls = constructor.enclosingClass; | 4470 ClassElement cls = constructor.enclosingClass; |
4465 if (cls.isAbstract && constructor.isGenerativeConstructor) { | 4471 if (cls.isAbstract && constructor.isGenerativeConstructor) { |
4466 generateAbstractClassInstantiationError(send, cls.name); | 4472 generateAbstractClassInstantiationError(send, cls.name); |
4467 return; | 4473 return; |
4468 } | 4474 } |
(...skipping 1423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5892 buildSwitch); | 5898 buildSwitch); |
5893 } | 5899 } |
5894 | 5900 |
5895 if (hasDefault) { | 5901 if (hasDefault) { |
5896 buildLoop(); | 5902 buildLoop(); |
5897 } else { | 5903 } else { |
5898 // If the switch statement has no default case, surround the loop with | 5904 // If the switch statement has no default case, surround the loop with |
5899 // a test of the target. | 5905 // a test of the target. |
5900 void buildCondition() { | 5906 void buildCondition() { |
5901 js.Template code = js.js.parseForeignJS('#'); | 5907 js.Template code = js.js.parseForeignJS('#'); |
5902 push(createForeign(code, | 5908 push(new HForeignCode( |
5903 backend.boolType, | 5909 code, |
5904 [localsHandler.readLocal(switchTarget)])); | 5910 backend.boolType, |
| 5911 [localsHandler.readLocal(switchTarget)], |
| 5912 nativeBehavior: native.NativeBehavior.PURE)); |
5905 } | 5913 } |
5906 handleIf(node, buildCondition, buildLoop, () => {}); | 5914 handleIf(node, buildCondition, buildLoop, () => {}); |
5907 } | 5915 } |
5908 } | 5916 } |
5909 | 5917 |
5910 /** | 5918 /** |
5911 * Creates a switch statement. | 5919 * Creates a switch statement. |
5912 * | 5920 * |
5913 * [jumpHandler] is the [JumpHandler] for the created switch statement. | 5921 * [jumpHandler] is the [JumpHandler] for the created switch statement. |
5914 * [buildExpression] creates the switch expression. | 5922 * [buildExpression] creates the switch expression. |
(...skipping 1058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6973 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6981 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
6974 unaliased.accept(this, builder); | 6982 unaliased.accept(this, builder); |
6975 } | 6983 } |
6976 | 6984 |
6977 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6985 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
6978 JavaScriptBackend backend = builder.compiler.backend; | 6986 JavaScriptBackend backend = builder.compiler.backend; |
6979 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 6987 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
6980 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 6988 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
6981 } | 6989 } |
6982 } | 6990 } |
OLD | NEW |