| 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 |