Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Side by Side Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 1020853003: Split HForeign into HForeignCode and abstract base class. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Formatting Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 void redirectElement(Local from, CapturedVariable to) { 230 void redirectElement(Local from, CapturedVariable to) {
231 assert(redirectionMapping[from] == null); 231 assert(redirectionMapping[from] == null);
232 redirectionMapping[from] = to; 232 redirectionMapping[from] = to;
233 assert(isStoredInClosureField(from) || isBoxed(from)); 233 assert(isStoredInClosureField(from) || isBoxed(from));
234 } 234 }
235 235
236 HInstruction createBox() { 236 HInstruction createBox() {
237 // TODO(floitsch): Clean up this hack. Should we create a box-object by 237 // TODO(floitsch): Clean up this hack. Should we create a box-object by
238 // just creating an empty object literal? 238 // just creating an empty object literal?
239 JavaScriptBackend backend = builder.backend; 239 JavaScriptBackend backend = builder.backend;
240 HInstruction box = new HForeign(js.js.parseForeignJS('{}'), 240 HInstruction box = new HForeignCode(js.js.parseForeignJS('{}'),
241 backend.nonNullType, 241 backend.nonNullType,
242 <HInstruction>[]); 242 <HInstruction>[]);
243 builder.add(box); 243 builder.add(box);
244 return box; 244 return box;
245 } 245 }
246 246
247 /** 247 /**
248 * If the scope (function or loop) [node] has captured variables then this 248 * If the scope (function or loop) [node] has captured variables then this
249 * method creates a box and sets up the redirections. 249 * method creates a box and sets up the redirections.
250 */ 250 */
251 void enterScope(ast.Node node, Element element) { 251 void enterScope(ast.Node node, Element element) {
252 // See if any variable in the top-scope of the function is captured. If yes 252 // See if any variable in the top-scope of the function is captured. If yes
(...skipping 1223 matching lines...) Expand 10 before | Expand all | Expand 10 after
1476 1476
1477 /** 1477 /**
1478 * Returns whether this builder is building code for [element]. 1478 * Returns whether this builder is building code for [element].
1479 */ 1479 */
1480 bool isBuildingFor(Element element) { 1480 bool isBuildingFor(Element element) {
1481 return work.element == element; 1481 return work.element == element;
1482 } 1482 }
1483 1483
1484 /// A stack of [DartType]s the have been seen during inlining of factory 1484 /// A stack of [DartType]s the have been seen during inlining of factory
1485 /// constructors. These types are preserved in [HInvokeStatic]s and 1485 /// constructors. These types are preserved in [HInvokeStatic]s and
1486 /// [HForeignNews] inside the inline code and registered during code 1486 /// [HForeignNew]s inside the inline code and registered during code
1487 /// generation for these nodes. 1487 /// generation for these nodes.
1488 // TODO(karlklose): consider removing this and keeping the (substituted) 1488 // TODO(karlklose): consider removing this and keeping the (substituted)
1489 // types of the type variables in an environment (like the [LocalsHandler]). 1489 // types of the type variables in an environment (like the [LocalsHandler]).
1490 final List<DartType> currentInlinedInstantiations = <DartType>[]; 1490 final List<DartType> currentInlinedInstantiations = <DartType>[];
1491 1491
1492 final List<AstInliningState> inliningStack = <AstInliningState>[]; 1492 final List<AstInliningState> inliningStack = <AstInliningState>[];
1493 1493
1494 Local returnLocal; 1494 Local returnLocal;
1495 DartType returnType; 1495 DartType returnType;
1496 1496
(...skipping 1869 matching lines...) Expand 10 before | Expand all | Expand 10 after
3366 localsHandler.updateLocal(local, checkedOrTrusted); 3366 localsHandler.updateLocal(local, checkedOrTrusted);
3367 } 3367 }
3368 } 3368 }
3369 3369
3370 HInstruction invokeInterceptor(HInstruction receiver) { 3370 HInstruction invokeInterceptor(HInstruction receiver) {
3371 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); 3371 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType);
3372 add(interceptor); 3372 add(interceptor);
3373 return interceptor; 3373 return interceptor;
3374 } 3374 }
3375 3375
3376 HForeign createForeign(js.Template code, 3376 HForeignCode createForeign(js.Template code,
3377 TypeMask type, 3377 TypeMask type,
3378 List<HInstruction> inputs) { 3378 List<HInstruction> inputs) {
3379 return new HForeign(code, type, inputs); 3379 return new HForeignCode(code, type, inputs);
3380 } 3380 }
3381 3381
3382 HLiteralList buildLiteralList(List<HInstruction> inputs) { 3382 HLiteralList buildLiteralList(List<HInstruction> inputs) {
3383 return new HLiteralList(inputs, backend.extendableArrayType); 3383 return new HLiteralList(inputs, backend.extendableArrayType);
3384 } 3384 }
3385 3385
3386 // TODO(karlklose): change construction of the representations to be GVN'able 3386 // TODO(karlklose): change construction of the representations to be GVN'able
3387 // (dartbug.com/7182). 3387 // (dartbug.com/7182).
3388 HInstruction buildTypeArgumentRepresentations(DartType type) { 3388 HInstruction buildTypeArgumentRepresentations(DartType type) {
3389 // Compute the representation of the type arguments, including access 3389 // Compute the representation of the type arguments, including access
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
3630 native.NativeBehavior nativeBehavior = 3630 native.NativeBehavior nativeBehavior =
3631 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); 3631 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
3632 3632
3633 List<HInstruction> inputs = <HInstruction>[]; 3633 List<HInstruction> inputs = <HInstruction>[];
3634 addGenericSendArgumentsToList(link.tail.tail, inputs); 3634 addGenericSendArgumentsToList(link.tail.tail, inputs);
3635 3635
3636 TypeMask ssaType = 3636 TypeMask ssaType =
3637 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); 3637 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler);
3638 3638
3639 if (nativeBehavior.codeTemplate.isExpression) { 3639 if (nativeBehavior.codeTemplate.isExpression) {
3640 push(new HForeign(nativeBehavior.codeTemplate, ssaType, inputs, 3640 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs,
3641 effects: nativeBehavior.sideEffects, 3641 effects: nativeBehavior.sideEffects,
3642 nativeBehavior: nativeBehavior)); 3642 nativeBehavior: nativeBehavior));
3643 } else { 3643 } else {
3644 push(new HForeign(nativeBehavior.codeTemplate, ssaType, inputs, 3644 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs,
3645 isStatement: true, 3645 isStatement: true,
3646 effects: nativeBehavior.sideEffects, 3646 effects: nativeBehavior.sideEffects,
3647 nativeBehavior: nativeBehavior, 3647 nativeBehavior: nativeBehavior,
3648 canThrow: true)); 3648 canThrow: true));
3649 } 3649 }
3650 } 3650 }
3651 3651
3652 void handleJsStringConcat(ast.Send node) { 3652 void handleJsStringConcat(ast.Send node) {
3653 List<HInstruction> inputs = <HInstruction>[]; 3653 List<HInstruction> inputs = <HInstruction>[];
3654 addGenericSendArgumentsToList(node.arguments, inputs); 3654 addGenericSendArgumentsToList(node.arguments, inputs);
3655 if (inputs.length != 2) { 3655 if (inputs.length != 2) {
3656 compiler.internalError(node.argumentsNode, 'Two arguments expected.'); 3656 compiler.internalError(node.argumentsNode, 'Two arguments expected.');
3657 } 3657 }
3658 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); 3658 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType));
3659 } 3659 }
3660 3660
3661 void handleForeignJsCurrentIsolateContext(ast.Send node) { 3661 void handleForeignJsCurrentIsolateContext(ast.Send node) {
3662 if (!node.arguments.isEmpty) { 3662 if (!node.arguments.isEmpty) {
3663 compiler.internalError(node, 3663 compiler.internalError(node,
3664 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.'); 3664 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.');
3665 } 3665 }
3666 3666
3667 if (!compiler.hasIsolateSupport) { 3667 if (!compiler.hasIsolateSupport) {
3668 // If the isolate library is not used, we just generate code 3668 // If the isolate library is not used, we just generate code
3669 // to fetch the current isolate. 3669 // to fetch the current isolate.
3670 String name = backend.namer.currentIsolate; 3670 String name = backend.namer.currentIsolate;
3671 push(new HForeign(js.js.parseForeignJS(name), 3671 push(new HForeignCode(js.js.parseForeignJS(name),
3672 backend.dynamicType, 3672 backend.dynamicType,
3673 <HInstruction>[])); 3673 <HInstruction>[]));
3674 } else { 3674 } else {
3675 // Call a helper method from the isolate library. The isolate 3675 // Call a helper method from the isolate library. The isolate
3676 // library uses its own isolate structure, that encapsulates 3676 // library uses its own isolate structure, that encapsulates
3677 // Leg's isolate. 3677 // Leg's isolate.
3678 Element element = backend.isolateHelperLibrary.find('_currentIsolate'); 3678 Element element = backend.isolateHelperLibrary.find('_currentIsolate');
3679 if (element == null) { 3679 if (element == null) {
3680 compiler.internalError(node, 3680 compiler.internalError(node,
3681 'Isolate library and compiler mismatch.'); 3681 'Isolate library and compiler mismatch.');
3682 } 3682 }
3683 pushInvokeStatic(null, element, [], backend.dynamicType); 3683 pushInvokeStatic(null, element, [], backend.dynamicType);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
3797 } 3797 }
3798 HConstant hConstant = globalNameHNode; 3798 HConstant hConstant = globalNameHNode;
3799 StringConstantValue constant = hConstant.constant; 3799 StringConstantValue constant = hConstant.constant;
3800 String globalName = constant.primitiveValue.slowToString(); 3800 String globalName = constant.primitiveValue.slowToString();
3801 js.Template expr = js.js.expressionTemplateYielding( 3801 js.Template expr = js.js.expressionTemplateYielding(
3802 backend.emitter.generateEmbeddedGlobalAccess(globalName)); 3802 backend.emitter.generateEmbeddedGlobalAccess(globalName));
3803 native.NativeBehavior nativeBehavior = 3803 native.NativeBehavior nativeBehavior =
3804 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); 3804 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
3805 TypeMask ssaType = 3805 TypeMask ssaType =
3806 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); 3806 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler);
3807 push(new HForeign(expr, ssaType, const [])); 3807 push(new HForeignCode(expr, ssaType, const []));
3808 } 3808 }
3809 3809
3810 void handleJsInterceptorConstant(ast.Send node) { 3810 void handleJsInterceptorConstant(ast.Send node) {
3811 // Single argument must be a TypeConstant which is converted into a 3811 // Single argument must be a TypeConstant which is converted into a
3812 // InterceptorConstant. 3812 // InterceptorConstant.
3813 if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) { 3813 if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) {
3814 ast.Node argument = node.arguments.head; 3814 ast.Node argument = node.arguments.head;
3815 visit(argument); 3815 visit(argument);
3816 HInstruction argumentInstruction = pop(); 3816 HInstruction argumentInstruction = pop();
3817 if (argumentInstruction is HConstant) { 3817 if (argumentInstruction is HConstant) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
3869 // and implementation signatures. Currently it is need because the 3869 // and implementation signatures. Currently it is need because the
3870 // signatures have different elements for parameters. 3870 // signatures have different elements for parameters.
3871 FunctionElement implementation = function.implementation; 3871 FunctionElement implementation = function.implementation;
3872 FunctionSignature params = implementation.functionSignature; 3872 FunctionSignature params = implementation.functionSignature;
3873 if (params.optionalParameterCount != 0) { 3873 if (params.optionalParameterCount != 0) {
3874 compiler.internalError(closure, 3874 compiler.internalError(closure,
3875 '"$name" does not handle closure with optional parameters.'); 3875 '"$name" does not handle closure with optional parameters.');
3876 } 3876 }
3877 3877
3878 registry.registerStaticUse(element); 3878 registry.registerStaticUse(element);
3879 push(new HForeign(js.js.expressionTemplateYielding( 3879 push(new HForeignCode(js.js.expressionTemplateYielding(
3880 backend.emitter.staticFunctionAccess(element)), 3880 backend.emitter.staticFunctionAccess(element)),
3881 backend.dynamicType, 3881 backend.dynamicType,
3882 <HInstruction>[])); 3882 <HInstruction>[]));
3883 return params; 3883 return params;
3884 } 3884 }
3885 3885
3886 void handleForeignDartClosureToJs(ast.Send node, String name) { 3886 void handleForeignDartClosureToJs(ast.Send node, String name) {
3887 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take 3887 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take
3888 // care to wrap the closure in another closure that saves the current 3888 // care to wrap the closure in another closure that saves the current
3889 // isolate. 3889 // isolate.
3890 handleForeignRawFunctionRef(node, name); 3890 handleForeignRawFunctionRef(node, name);
3891 } 3891 }
3892 3892
3893 void handleForeignSetCurrentIsolate(ast.Send node) { 3893 void handleForeignSetCurrentIsolate(ast.Send node) {
3894 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { 3894 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) {
3895 compiler.internalError(node.argumentsNode, 3895 compiler.internalError(node.argumentsNode,
3896 'Exactly one argument required.'); 3896 'Exactly one argument required.');
3897 } 3897 }
3898 visit(node.arguments.head); 3898 visit(node.arguments.head);
3899 String isolateName = backend.namer.currentIsolate; 3899 String isolateName = backend.namer.currentIsolate;
3900 SideEffects sideEffects = new SideEffects.empty(); 3900 SideEffects sideEffects = new SideEffects.empty();
3901 sideEffects.setAllSideEffects(); 3901 sideEffects.setAllSideEffects();
3902 push(new HForeign(js.js.parseForeignJS("$isolateName = #"), 3902 push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"),
3903 backend.dynamicType, 3903 backend.dynamicType,
3904 <HInstruction>[pop()], 3904 <HInstruction>[pop()],
3905 effects: sideEffects)); 3905 effects: sideEffects));
3906 } 3906 }
3907 3907
3908 void handleForeignDartObjectJsConstructorFunction(ast.Send node) { 3908 void handleForeignDartObjectJsConstructorFunction(ast.Send node) {
3909 if (!node.arguments.isEmpty) { 3909 if (!node.arguments.isEmpty) {
3910 compiler.internalError(node.argumentsNode, 'Too many arguments.'); 3910 compiler.internalError(node.argumentsNode, 'Too many arguments.');
3911 } 3911 }
3912 push(new HForeign(js.js.expressionTemplateYielding( 3912 push(new HForeignCode(js.js.expressionTemplateYielding(
3913 backend.emitter.typeAccess(compiler.objectClass)), 3913 backend.emitter.typeAccess(compiler.objectClass)),
3914 backend.dynamicType, 3914 backend.dynamicType,
3915 <HInstruction>[])); 3915 <HInstruction>[]));
3916 } 3916 }
3917 3917
3918 void handleForeignJsCurrentIsolate(ast.Send node) { 3918 void handleForeignJsCurrentIsolate(ast.Send node) {
3919 if (!node.arguments.isEmpty) { 3919 if (!node.arguments.isEmpty) {
3920 compiler.internalError(node.argumentsNode, 'Too many arguments.'); 3920 compiler.internalError(node.argumentsNode, 'Too many arguments.');
3921 } 3921 }
3922 push(new HForeign(js.js.parseForeignJS(backend.namer.currentIsolate), 3922 push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate),
3923 backend.dynamicType, 3923 backend.dynamicType,
3924 <HInstruction>[])); 3924 <HInstruction>[]));
3925 } 3925 }
3926 3926
3927 visitForeignSend(ast.Send node) { 3927 visitForeignSend(ast.Send node) {
3928 Selector selector = elements.getSelector(node); 3928 Selector selector = elements.getSelector(node);
3929 String name = selector.name; 3929 String name = selector.name;
3930 if (name == 'JS') { 3930 if (name == 'JS') {
3931 handleForeignJs(node); 3931 handleForeignJs(node);
3932 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { 3932 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') {
3933 handleForeignJsCurrentIsolateContext(node); 3933 handleForeignJsCurrentIsolateContext(node);
3934 } else if (name == 'JS_CALL_IN_ISOLATE') { 3934 } else if (name == 'JS_CALL_IN_ISOLATE') {
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
4404 js.Template code = js.js.parseForeignJS('Array(#)'); 4404 js.Template code = js.js.parseForeignJS('Array(#)');
4405 var behavior = new native.NativeBehavior(); 4405 var behavior = new native.NativeBehavior();
4406 behavior.typesReturned.add(expectedType); 4406 behavior.typesReturned.add(expectedType);
4407 // The allocation can throw only if the given length is a double 4407 // The allocation can throw only if the given length is a double
4408 // or negative. 4408 // or negative.
4409 bool canThrow = true; 4409 bool canThrow = true;
4410 if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) { 4410 if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) {
4411 var constant = inputs[0]; 4411 var constant = inputs[0];
4412 if (constant.constant.primitiveValue >= 0) canThrow = false; 4412 if (constant.constant.primitiveValue >= 0) canThrow = false;
4413 } 4413 }
4414 HForeign foreign = new HForeign( 4414 HForeignCode foreign = new HForeignCode(
4415 code, elementType, inputs, nativeBehavior: behavior, 4415 code, elementType, inputs, nativeBehavior: behavior,
4416 canThrow: canThrow); 4416 canThrow: canThrow);
4417 push(foreign); 4417 push(foreign);
4418 TypesInferrer inferrer = compiler.typesTask.typesInferrer; 4418 TypesInferrer inferrer = compiler.typesTask.typesInferrer;
4419 if (inferrer.isFixedArrayCheckedForGrowable(send)) { 4419 if (inferrer.isFixedArrayCheckedForGrowable(send)) {
4420 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); 4420 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array');
4421 // We set the instruction as [canThrow] to avoid it being dead code. 4421 // We set the instruction as [canThrow] to avoid it being dead code.
4422 // We need a finer grained side effect. 4422 // We need a finer grained side effect.
4423 add(new HForeign( 4423 add(new HForeignCode(
4424 code, backend.nullType, [stack.last], canThrow: true)); 4424 code, backend.nullType, [stack.last], canThrow: true));
4425 } 4425 }
4426 } else if (isGrowableListConstructorCall) { 4426 } else if (isGrowableListConstructorCall) {
4427 push(buildLiteralList(<HInstruction>[])); 4427 push(buildLiteralList(<HInstruction>[]));
4428 stack.last.instructionType = elementType; 4428 stack.last.instructionType = elementType;
4429 } else { 4429 } else {
4430 ClassElement cls = constructor.enclosingClass; 4430 ClassElement cls = constructor.enclosingClass;
4431 if (cls.isAbstract && constructor.isGenerativeConstructor) { 4431 if (cls.isAbstract && constructor.isGenerativeConstructor) {
4432 generateAbstractClassInstantiationError(send, cls.name); 4432 generateAbstractClassInstantiationError(send, cls.name);
4433 return; 4433 return;
(...skipping 2510 matching lines...) Expand 10 before | Expand all | Expand 10 after
6944 if (unaliased is TypedefType) throw 'unable to unalias $type'; 6944 if (unaliased is TypedefType) throw 'unable to unalias $type';
6945 unaliased.accept(this, builder); 6945 unaliased.accept(this, builder);
6946 } 6946 }
6947 6947
6948 void visitDynamicType(DynamicType type, SsaBuilder builder) { 6948 void visitDynamicType(DynamicType type, SsaBuilder builder) {
6949 JavaScriptBackend backend = builder.compiler.backend; 6949 JavaScriptBackend backend = builder.compiler.backend;
6950 ClassElement cls = backend.findHelper('DynamicRuntimeType'); 6950 ClassElement cls = backend.findHelper('DynamicRuntimeType');
6951 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); 6951 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld)));
6952 } 6952 }
6953 } 6953 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698