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 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 void redirectElement(Local from, CapturedVariable to) { | 233 void redirectElement(Local from, CapturedVariable to) { |
234 assert(redirectionMapping[from] == null); | 234 assert(redirectionMapping[from] == null); |
235 redirectionMapping[from] = to; | 235 redirectionMapping[from] = to; |
236 assert(isStoredInClosureField(from) || isBoxed(from)); | 236 assert(isStoredInClosureField(from) || isBoxed(from)); |
237 } | 237 } |
238 | 238 |
239 HInstruction createBox() { | 239 HInstruction createBox() { |
240 // TODO(floitsch): Clean up this hack. Should we create a box-object by | 240 // TODO(floitsch): Clean up this hack. Should we create a box-object by |
241 // just creating an empty object literal? | 241 // just creating an empty object literal? |
242 JavaScriptBackend backend = builder.backend; | 242 JavaScriptBackend backend = builder.backend; |
243 HInstruction box = new HForeignCode(js.js.parseForeignJS('{}'), | 243 HInstruction box = new HForeignCode( |
244 backend.nonNullType, | 244 js.js.parseForeignJS('{}'), |
245 <HInstruction>[]); | 245 backend.nonNullType, |
| 246 <HInstruction>[], |
| 247 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION); |
246 builder.add(box); | 248 builder.add(box); |
247 return box; | 249 return box; |
248 } | 250 } |
249 | 251 |
250 /** | 252 /** |
251 * If the scope (function or loop) [node] has captured variables then this | 253 * If the scope (function or loop) [node] has captured variables then this |
252 * method creates a box and sets up the redirections. | 254 * method creates a box and sets up the redirections. |
253 */ | 255 */ |
254 void enterScope(ast.Node node, Element element) { | 256 void enterScope(ast.Node node, Element element) { |
255 // See if any variable in the top-scope of the function is captured. If yes | 257 // See if any variable in the top-scope of the function is captured. If yes |
(...skipping 3114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3370 localsHandler.updateLocal(local, checkedOrTrusted); | 3372 localsHandler.updateLocal(local, checkedOrTrusted); |
3371 } | 3373 } |
3372 } | 3374 } |
3373 | 3375 |
3374 HInstruction invokeInterceptor(HInstruction receiver) { | 3376 HInstruction invokeInterceptor(HInstruction receiver) { |
3375 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); | 3377 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); |
3376 add(interceptor); | 3378 add(interceptor); |
3377 return interceptor; | 3379 return interceptor; |
3378 } | 3380 } |
3379 | 3381 |
3380 HForeignCode createForeign(js.Template code, | |
3381 TypeMask type, | |
3382 List<HInstruction> inputs) { | |
3383 return new HForeignCode(code, type, inputs); | |
3384 } | |
3385 | |
3386 HLiteralList buildLiteralList(List<HInstruction> inputs) { | 3382 HLiteralList buildLiteralList(List<HInstruction> inputs) { |
3387 return new HLiteralList(inputs, backend.extendableArrayType); | 3383 return new HLiteralList(inputs, backend.extendableArrayType); |
3388 } | 3384 } |
3389 | 3385 |
3390 // TODO(karlklose): change construction of the representations to be GVN'able | 3386 // TODO(karlklose): change construction of the representations to be GVN'able |
3391 // (dartbug.com/7182). | 3387 // (dartbug.com/7182). |
3392 HInstruction buildTypeArgumentRepresentations(DartType type) { | 3388 HInstruction buildTypeArgumentRepresentations(DartType type) { |
3393 // Compute the representation of the type arguments, including access | 3389 // Compute the representation of the type arguments, including access |
3394 // to the runtime type information for type variables as instructions. | 3390 // to the runtime type information for type variables as instructions. |
3395 if (type.isTypeVariable) { | 3391 if (type.isTypeVariable) { |
3396 return buildLiteralList(<HInstruction>[addTypeVariableReference(type)]); | 3392 return buildLiteralList(<HInstruction>[addTypeVariableReference(type)]); |
3397 } else { | 3393 } else { |
3398 assert(type.element.isClass); | 3394 assert(type.element.isClass); |
3399 InterfaceType interface = type; | 3395 InterfaceType interface = type; |
3400 List<HInstruction> inputs = <HInstruction>[]; | 3396 List<HInstruction> inputs = <HInstruction>[]; |
3401 bool first = true; | 3397 bool first = true; |
3402 List<String> templates = <String>[]; | 3398 List<String> templates = <String>[]; |
3403 for (DartType argument in interface.typeArguments) { | 3399 for (DartType argument in interface.typeArguments) { |
3404 templates.add(rti.getTypeRepresentationWithHashes(argument, (variable) { | 3400 templates.add(rti.getTypeRepresentationWithHashes(argument, (variable) { |
3405 HInstruction runtimeType = addTypeVariableReference(variable); | 3401 HInstruction runtimeType = addTypeVariableReference(variable); |
3406 inputs.add(runtimeType); | 3402 inputs.add(runtimeType); |
3407 })); | 3403 })); |
3408 } | 3404 } |
3409 String template = '[${templates.join(', ')}]'; | 3405 String template = '[${templates.join(', ')}]'; |
3410 // TODO(sra): This is a fresh template each time. We can't let the | 3406 // TODO(sra): This is a fresh template each time. We can't let the |
3411 // template manager build them. | 3407 // template manager build them. |
3412 js.Template code = js.js.uncachedExpressionTemplate(template); | 3408 js.Template code = js.js.uncachedExpressionTemplate(template); |
3413 HInstruction representation = | 3409 HInstruction representation = |
3414 createForeign(code, backend.readableArrayType, inputs); | 3410 new HForeignCode(code, backend.readableArrayType, inputs, |
| 3411 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION); |
3415 return representation; | 3412 return representation; |
3416 } | 3413 } |
3417 } | 3414 } |
3418 | 3415 |
3419 visitOperatorSend(ast.Send node) { | 3416 visitOperatorSend(ast.Send node) { |
3420 ast.Operator op = node.selector; | 3417 ast.Operator op = node.selector; |
3421 if ("[]" == op.source) { | 3418 if ("[]" == op.source) { |
3422 visitDynamicSend(node); | 3419 visitDynamicSend(node); |
3423 } else if ("&&" == op.source || | 3420 } else if ("&&" == op.source || |
3424 "||" == op.source) { | 3421 "||" == op.source) { |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3618 inputs.add(closureTarget); | 3615 inputs.add(closureTarget); |
3619 addDynamicSendArgumentsToList(node, inputs); | 3616 addDynamicSendArgumentsToList(node, inputs); |
3620 Selector closureSelector = new Selector.callClosureFrom(selector); | 3617 Selector closureSelector = new Selector.callClosureFrom(selector); |
3621 pushWithPosition( | 3618 pushWithPosition( |
3622 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), | 3619 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), |
3623 node); | 3620 node); |
3624 } | 3621 } |
3625 | 3622 |
3626 void handleForeignJs(ast.Send node) { | 3623 void handleForeignJs(ast.Send node) { |
3627 Link<ast.Node> link = node.arguments; | 3624 Link<ast.Node> link = node.arguments; |
3628 // If the invoke is on foreign code, don't visit the first | 3625 // Don't visit the first argument, which is the type, and the second |
3629 // argument, which is the type, and the second argument, | 3626 // argument, which is the foreign code. |
3630 // which is the foreign code. | |
3631 if (link.isEmpty || link.tail.isEmpty) { | 3627 if (link.isEmpty || link.tail.isEmpty) { |
3632 compiler.internalError(node.argumentsNode, | 3628 compiler.internalError(node.argumentsNode, |
3633 'At least two arguments expected.'); | 3629 'At least two arguments expected.'); |
3634 } | 3630 } |
3635 native.NativeBehavior nativeBehavior = | 3631 native.NativeBehavior nativeBehavior = |
3636 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); | 3632 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
3637 | 3633 |
3638 List<HInstruction> inputs = <HInstruction>[]; | 3634 List<HInstruction> inputs = <HInstruction>[]; |
3639 addGenericSendArgumentsToList(link.tail.tail, inputs); | 3635 addGenericSendArgumentsToList(link.tail.tail, inputs); |
3640 | 3636 |
3641 TypeMask ssaType = | 3637 TypeMask ssaType = |
3642 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); | 3638 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
3643 | 3639 |
3644 if (nativeBehavior.codeTemplate.isExpression) { | 3640 if (nativeBehavior.codeTemplate.isExpression) { |
3645 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs, | 3641 push(new HForeignCode( |
3646 effects: nativeBehavior.sideEffects, | 3642 nativeBehavior.codeTemplate, ssaType, inputs, |
3647 nativeBehavior: nativeBehavior)); | 3643 effects: nativeBehavior.sideEffects, |
| 3644 nativeBehavior: nativeBehavior)); |
3648 } else { | 3645 } else { |
3649 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs, | 3646 push(new HForeignCode( |
3650 isStatement: true, | 3647 nativeBehavior.codeTemplate, ssaType, inputs, |
3651 effects: nativeBehavior.sideEffects, | 3648 isStatement: true, |
3652 nativeBehavior: nativeBehavior, | 3649 effects: nativeBehavior.sideEffects, |
3653 canThrow: true)); | 3650 nativeBehavior: nativeBehavior)); |
3654 } | 3651 } |
3655 } | 3652 } |
3656 | 3653 |
3657 void handleJsStringConcat(ast.Send node) { | 3654 void handleJsStringConcat(ast.Send node) { |
3658 List<HInstruction> inputs = <HInstruction>[]; | 3655 List<HInstruction> inputs = <HInstruction>[]; |
3659 addGenericSendArgumentsToList(node.arguments, inputs); | 3656 addGenericSendArgumentsToList(node.arguments, inputs); |
3660 if (inputs.length != 2) { | 3657 if (inputs.length != 2) { |
3661 compiler.internalError(node.argumentsNode, 'Two arguments expected.'); | 3658 compiler.internalError(node.argumentsNode, 'Two arguments expected.'); |
3662 } | 3659 } |
3663 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); | 3660 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3802 } | 3799 } |
3803 HConstant hConstant = globalNameHNode; | 3800 HConstant hConstant = globalNameHNode; |
3804 StringConstantValue constant = hConstant.constant; | 3801 StringConstantValue constant = hConstant.constant; |
3805 String globalName = constant.primitiveValue.slowToString(); | 3802 String globalName = constant.primitiveValue.slowToString(); |
3806 js.Template expr = js.js.expressionTemplateYielding( | 3803 js.Template expr = js.js.expressionTemplateYielding( |
3807 backend.emitter.generateEmbeddedGlobalAccess(globalName)); | 3804 backend.emitter.generateEmbeddedGlobalAccess(globalName)); |
3808 native.NativeBehavior nativeBehavior = | 3805 native.NativeBehavior nativeBehavior = |
3809 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); | 3806 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
3810 TypeMask ssaType = | 3807 TypeMask ssaType = |
3811 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); | 3808 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
3812 push(new HForeignCode(expr, ssaType, const [])); | 3809 push(new HForeignCode(expr, ssaType, const [], |
| 3810 nativeBehavior: nativeBehavior)); |
3813 } | 3811 } |
3814 | 3812 |
3815 void handleJsInterceptorConstant(ast.Send node) { | 3813 void handleJsInterceptorConstant(ast.Send node) { |
3816 // Single argument must be a TypeConstant which is converted into a | 3814 // Single argument must be a TypeConstant which is converted into a |
3817 // InterceptorConstant. | 3815 // InterceptorConstant. |
3818 if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) { | 3816 if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) { |
3819 ast.Node argument = node.arguments.head; | 3817 ast.Node argument = node.arguments.head; |
3820 visit(argument); | 3818 visit(argument); |
3821 HInstruction argumentInstruction = pop(); | 3819 HInstruction argumentInstruction = pop(); |
3822 if (argumentInstruction is HConstant) { | 3820 if (argumentInstruction is HConstant) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3874 // and implementation signatures. Currently it is need because the | 3872 // and implementation signatures. Currently it is need because the |
3875 // signatures have different elements for parameters. | 3873 // signatures have different elements for parameters. |
3876 FunctionElement implementation = function.implementation; | 3874 FunctionElement implementation = function.implementation; |
3877 FunctionSignature params = implementation.functionSignature; | 3875 FunctionSignature params = implementation.functionSignature; |
3878 if (params.optionalParameterCount != 0) { | 3876 if (params.optionalParameterCount != 0) { |
3879 compiler.internalError(closure, | 3877 compiler.internalError(closure, |
3880 '"$name" does not handle closure with optional parameters.'); | 3878 '"$name" does not handle closure with optional parameters.'); |
3881 } | 3879 } |
3882 | 3880 |
3883 registry.registerStaticUse(element); | 3881 registry.registerStaticUse(element); |
3884 push(new HForeignCode(js.js.expressionTemplateYielding( | 3882 push(new HForeignCode( |
3885 backend.emitter.staticFunctionAccess(element)), | 3883 js.js.expressionTemplateYielding( |
3886 backend.dynamicType, | 3884 backend.emitter.staticFunctionAccess(element)), |
3887 <HInstruction>[])); | 3885 backend.dynamicType, |
| 3886 <HInstruction>[], |
| 3887 nativeBehavior: native.NativeBehavior.PURE)); |
3888 return params; | 3888 return params; |
3889 } | 3889 } |
3890 | 3890 |
3891 void handleForeignDartClosureToJs(ast.Send node, String name) { | 3891 void handleForeignDartClosureToJs(ast.Send node, String name) { |
3892 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take | 3892 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take |
3893 // care to wrap the closure in another closure that saves the current | 3893 // care to wrap the closure in another closure that saves the current |
3894 // isolate. | 3894 // isolate. |
3895 handleForeignRawFunctionRef(node, name); | 3895 handleForeignRawFunctionRef(node, name); |
3896 } | 3896 } |
3897 | 3897 |
3898 void handleForeignSetCurrentIsolate(ast.Send node) { | 3898 void handleForeignSetCurrentIsolate(ast.Send node) { |
3899 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { | 3899 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
3900 compiler.internalError(node.argumentsNode, | 3900 compiler.internalError(node.argumentsNode, |
3901 'Exactly one argument required.'); | 3901 'Exactly one argument required.'); |
3902 } | 3902 } |
3903 visit(node.arguments.head); | 3903 visit(node.arguments.head); |
3904 String isolateName = backend.namer.currentIsolate; | 3904 String isolateName = backend.namer.currentIsolate; |
3905 SideEffects sideEffects = new SideEffects.empty(); | 3905 SideEffects sideEffects = new SideEffects.empty(); |
3906 sideEffects.setAllSideEffects(); | 3906 sideEffects.setAllSideEffects(); |
3907 push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"), | 3907 push(new HForeignCode( |
3908 backend.dynamicType, | 3908 js.js.parseForeignJS("$isolateName = #"), |
3909 <HInstruction>[pop()], | 3909 backend.dynamicType, |
3910 effects: sideEffects)); | 3910 <HInstruction>[pop()], |
| 3911 nativeBehavior: native.NativeBehavior.PURE, |
| 3912 effects: sideEffects)); |
3911 } | 3913 } |
3912 | 3914 |
3913 void handleForeignDartObjectJsConstructorFunction(ast.Send node) { | 3915 void handleForeignDartObjectJsConstructorFunction(ast.Send node) { |
3914 if (!node.arguments.isEmpty) { | 3916 if (!node.arguments.isEmpty) { |
3915 compiler.internalError(node.argumentsNode, 'Too many arguments.'); | 3917 compiler.internalError(node.argumentsNode, 'Too many arguments.'); |
3916 } | 3918 } |
3917 push(new HForeignCode(js.js.expressionTemplateYielding( | 3919 push(new HForeignCode( |
3918 backend.emitter.typeAccess(compiler.objectClass)), | 3920 js.js.expressionTemplateYielding( |
3919 backend.dynamicType, | 3921 backend.emitter.typeAccess(compiler.objectClass)), |
3920 <HInstruction>[])); | 3922 backend.dynamicType, |
| 3923 <HInstruction>[])); |
3921 } | 3924 } |
3922 | 3925 |
3923 void handleForeignJsCurrentIsolate(ast.Send node) { | 3926 void handleForeignJsCurrentIsolate(ast.Send node) { |
3924 if (!node.arguments.isEmpty) { | 3927 if (!node.arguments.isEmpty) { |
3925 compiler.internalError(node.argumentsNode, 'Too many arguments.'); | 3928 compiler.internalError(node.argumentsNode, 'Too many arguments.'); |
3926 } | 3929 } |
3927 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), | 3930 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate), |
3928 backend.dynamicType, | 3931 backend.dynamicType, |
3929 <HInstruction>[])); | 3932 <HInstruction>[])); |
3930 } | 3933 } |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4242 return addTypeVariableReference(argument); | 4245 return addTypeVariableReference(argument); |
4243 } | 4246 } |
4244 | 4247 |
4245 List<HInstruction> inputs = <HInstruction>[]; | 4248 List<HInstruction> inputs = <HInstruction>[]; |
4246 | 4249 |
4247 String template = rti.getTypeRepresentationWithHashes(argument, (variable) { | 4250 String template = rti.getTypeRepresentationWithHashes(argument, (variable) { |
4248 inputs.add(addTypeVariableReference(variable)); | 4251 inputs.add(addTypeVariableReference(variable)); |
4249 }); | 4252 }); |
4250 | 4253 |
4251 js.Template code = js.js.uncachedExpressionTemplate(template); | 4254 js.Template code = js.js.uncachedExpressionTemplate(template); |
4252 HInstruction result = createForeign(code, backend.stringType, inputs); | 4255 HInstruction result = new HForeignCode(code, backend.stringType, inputs, |
| 4256 nativeBehavior: native.NativeBehavior.PURE); |
4253 add(result); | 4257 add(result); |
4254 return result; | 4258 return result; |
4255 } | 4259 } |
4256 | 4260 |
4257 HInstruction handleListConstructor(InterfaceType type, | 4261 HInstruction handleListConstructor(InterfaceType type, |
4258 ast.Node currentNode, | 4262 ast.Node currentNode, |
4259 HInstruction newObject) { | 4263 HInstruction newObject) { |
4260 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 4264 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
4261 return newObject; | 4265 return newObject; |
4262 } | 4266 } |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4409 js.Template code = js.js.parseForeignJS('Array(#)'); | 4413 js.Template code = js.js.parseForeignJS('Array(#)'); |
4410 var behavior = new native.NativeBehavior(); | 4414 var behavior = new native.NativeBehavior(); |
4411 behavior.typesReturned.add(expectedType); | 4415 behavior.typesReturned.add(expectedType); |
4412 // The allocation can throw only if the given length is a double | 4416 // The allocation can throw only if the given length is a double |
4413 // or negative. | 4417 // or negative. |
4414 bool canThrow = true; | 4418 bool canThrow = true; |
4415 if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) { | 4419 if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) { |
4416 var constant = inputs[0]; | 4420 var constant = inputs[0]; |
4417 if (constant.constant.primitiveValue >= 0) canThrow = false; | 4421 if (constant.constant.primitiveValue >= 0) canThrow = false; |
4418 } | 4422 } |
4419 HForeignCode foreign = new HForeignCode( | 4423 HForeignCode foreign = new HForeignCode(code, elementType, inputs, |
4420 code, elementType, inputs, nativeBehavior: behavior, | 4424 nativeBehavior: behavior, |
4421 canThrow: canThrow); | 4425 throwBehavior: canThrow |
| 4426 ? native.NativeThrowBehavior.MAY |
| 4427 : native.NativeThrowBehavior.NEVER); |
4422 push(foreign); | 4428 push(foreign); |
4423 TypesInferrer inferrer = compiler.typesTask.typesInferrer; | 4429 TypesInferrer inferrer = compiler.typesTask.typesInferrer; |
4424 if (inferrer.isFixedArrayCheckedForGrowable(send)) { | 4430 if (inferrer.isFixedArrayCheckedForGrowable(send)) { |
4425 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); | 4431 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); |
4426 // We set the instruction as [canThrow] to avoid it being dead code. | 4432 // We set the instruction as [canThrow] to avoid it being dead code. |
4427 // We need a finer grained side effect. | 4433 // We need a finer grained side effect. |
4428 add(new HForeignCode( | 4434 add(new HForeignCode(code, backend.nullType, [stack.last], |
4429 code, backend.nullType, [stack.last], canThrow: true)); | 4435 throwBehavior: native.NativeThrowBehavior.MAY)); |
4430 } | 4436 } |
4431 } else if (isGrowableListConstructorCall) { | 4437 } else if (isGrowableListConstructorCall) { |
4432 push(buildLiteralList(<HInstruction>[])); | 4438 push(buildLiteralList(<HInstruction>[])); |
4433 stack.last.instructionType = elementType; | 4439 stack.last.instructionType = elementType; |
4434 } else { | 4440 } else { |
4435 ClassElement cls = constructor.enclosingClass; | 4441 ClassElement cls = constructor.enclosingClass; |
4436 if (cls.isAbstract && constructor.isGenerativeConstructor) { | 4442 if (cls.isAbstract && constructor.isGenerativeConstructor) { |
4437 generateAbstractClassInstantiationError(send, cls.name); | 4443 generateAbstractClassInstantiationError(send, cls.name); |
4438 return; | 4444 return; |
4439 } | 4445 } |
(...skipping 1428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5868 buildSwitch); | 5874 buildSwitch); |
5869 } | 5875 } |
5870 | 5876 |
5871 if (hasDefault) { | 5877 if (hasDefault) { |
5872 buildLoop(); | 5878 buildLoop(); |
5873 } else { | 5879 } else { |
5874 // If the switch statement has no default case, surround the loop with | 5880 // If the switch statement has no default case, surround the loop with |
5875 // a test of the target. | 5881 // a test of the target. |
5876 void buildCondition() { | 5882 void buildCondition() { |
5877 js.Template code = js.js.parseForeignJS('#'); | 5883 js.Template code = js.js.parseForeignJS('#'); |
5878 push(createForeign(code, | 5884 push(new HForeignCode( |
5879 backend.boolType, | 5885 code, |
5880 [localsHandler.readLocal(switchTarget)])); | 5886 backend.boolType, |
| 5887 [localsHandler.readLocal(switchTarget)], |
| 5888 nativeBehavior: native.NativeBehavior.PURE)); |
5881 } | 5889 } |
5882 handleIf(node, buildCondition, buildLoop, () => {}); | 5890 handleIf(node, buildCondition, buildLoop, () => {}); |
5883 } | 5891 } |
5884 } | 5892 } |
5885 | 5893 |
5886 /** | 5894 /** |
5887 * Creates a switch statement. | 5895 * Creates a switch statement. |
5888 * | 5896 * |
5889 * [jumpHandler] is the [JumpHandler] for the created switch statement. | 5897 * [jumpHandler] is the [JumpHandler] for the created switch statement. |
5890 * [buildExpression] creates the switch expression. | 5898 * [buildExpression] creates the switch expression. |
(...skipping 1058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6949 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6957 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
6950 unaliased.accept(this, builder); | 6958 unaliased.accept(this, builder); |
6951 } | 6959 } |
6952 | 6960 |
6953 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6961 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
6954 JavaScriptBackend backend = builder.compiler.backend; | 6962 JavaScriptBackend backend = builder.compiler.backend; |
6955 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 6963 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
6956 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 6964 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
6957 } | 6965 } |
6958 } | 6966 } |
OLD | NEW |