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

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

Issue 1127363003: Insert the right checks for redirecting factories to deferred constructors. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: update to status-file rebase Created 5 years, 7 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 3209 matching lines...) Expand 10 before | Expand all | Expand 10 after
3220 * [selector]. 3220 * [selector].
3221 */ 3221 */
3222 void generateInstanceGetterWithCompiledReceiver(ast.Send send, 3222 void generateInstanceGetterWithCompiledReceiver(ast.Send send,
3223 Selector selector, 3223 Selector selector,
3224 HInstruction receiver) { 3224 HInstruction receiver) {
3225 assert(Elements.isInstanceSend(send, elements)); 3225 assert(Elements.isInstanceSend(send, elements));
3226 assert(selector.isGetter); 3226 assert(selector.isGetter);
3227 pushInvokeDynamic(send, selector, [receiver]); 3227 pushInvokeDynamic(send, selector, [receiver]);
3228 } 3228 }
3229 3229
3230 /// Inserts a call to checkDeferredIsLoaded for [prefixElement].
3231 /// If [prefixElement] is [null] ndo nothing.
3232 void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement,
3233 ast.Node location) {
3234 if (prefixElement == null) return;
3235 String loadId =
3236 compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport];
3237 HInstruction loadIdConstant = addConstantString(loadId);
3238 String uri = prefixElement.deferredImport.uri.dartString.slowToString();
3239 HInstruction uriConstant = addConstantString(uri);
3240 Element helper = backend.getCheckDeferredIsLoaded();
3241 pushInvokeStatic(location, helper, [loadIdConstant, uriConstant]);
3242 pop();
3243 }
3244
3230 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that 3245 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that
3231 /// resolves to a deferred library. 3246 /// resolves to a deferred library.
3232 void generateIsDeferredLoadedCheckIfNeeded(ast.Send node) { 3247 void generateIsDeferredLoadedCheckOfSend(ast.Send node) {
3233 DeferredLoadTask deferredTask = compiler.deferredLoadTask; 3248 generateIsDeferredLoadedCheckIfNeeded(
3234 PrefixElement prefixElement = 3249 compiler.deferredLoadTask.deferredPrefixElement(node, elements),
3235 deferredTask.deferredPrefixElement(node, elements); 3250 node);
3236 if (prefixElement != null) {
3237 String loadId =
3238 deferredTask.importDeferName[prefixElement.deferredImport];
3239 HInstruction loadIdConstant = addConstantString(loadId);
3240 String uri = prefixElement.deferredImport.uri.dartString.slowToString();
3241 HInstruction uriConstant = addConstantString(uri);
3242 Element helper = backend.getCheckDeferredIsLoaded();
3243 pushInvokeStatic(node, helper, [loadIdConstant, uriConstant]);
3244 pop();
3245 }
3246 } 3251 }
3247 3252
3248 /// Generate read access of an unresolved static or top level entity. 3253 /// Generate read access of an unresolved static or top level entity.
3249 void generateStaticUnresolvedGet(ast.Send node, Element element) { 3254 void generateStaticUnresolvedGet(ast.Send node, Element element) {
3250 if (element is ErroneousElement) { 3255 if (element is ErroneousElement) {
3251 // An erroneous element indicates an unresolved static getter. 3256 // An erroneous element indicates an unresolved static getter.
3252 generateThrowNoSuchMethod( 3257 generateThrowNoSuchMethod(
3253 node, 3258 node,
3254 noSuchMethodTargetSymbolString(element, 'get'), 3259 noSuchMethodTargetSymbolString(element, 'get'),
3255 argumentNodes: const Link<ast.Node>()); 3260 argumentNodes: const Link<ast.Node>());
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3287 if (!type.containsAll(compiler.world) && 3292 if (!type.containsAll(compiler.world) &&
3288 !instruction.isConstantNull()) { 3293 !instruction.isConstantNull()) {
3289 // TODO(13429): The inferrer should know that an element 3294 // TODO(13429): The inferrer should know that an element
3290 // cannot be null. 3295 // cannot be null.
3291 instruction.instructionType = type.nonNullable(); 3296 instruction.instructionType = type.nonNullable();
3292 } 3297 }
3293 } 3298 }
3294 3299
3295 /// Read a static or top level [field]. 3300 /// Read a static or top level [field].
3296 void generateStaticFieldGet(ast.Send node, FieldElement field) { 3301 void generateStaticFieldGet(ast.Send node, FieldElement field) {
3297 generateIsDeferredLoadedCheckIfNeeded(node); 3302 generateIsDeferredLoadedCheckOfSend(node);
3298 3303
3299 ConstantExpression constant = 3304 ConstantExpression constant =
3300 backend.constants.getConstantForVariable(field); 3305 backend.constants.getConstantForVariable(field);
3301 if (constant != null) { 3306 if (constant != null) {
3302 if (!field.isAssignable) { 3307 if (!field.isAssignable) {
3303 // A static final or const. Get its constant value and inline it if 3308 // A static final or const. Get its constant value and inline it if
3304 // the value can be compiled eagerly. 3309 // the value can be compiled eagerly.
3305 generateStaticConstGet(node, field, constant); 3310 generateStaticConstGet(node, field, constant);
3306 } else { 3311 } else {
3307 // TODO(5346): Try to avoid the need for calling [declaration] before 3312 // TODO(5346): Try to avoid the need for calling [declaration] before
3308 // creating an [HStatic]. 3313 // creating an [HStatic].
3309 HInstruction instruction = new HStatic( 3314 HInstruction instruction = new HStatic(
3310 field.declaration, 3315 field.declaration,
3311 TypeMaskFactory.inferredTypeForElement(field, compiler)); 3316 TypeMaskFactory.inferredTypeForElement(field, compiler));
3312 push(instruction); 3317 push(instruction);
3313 } 3318 }
3314 } else { 3319 } else {
3315 HInstruction instruction = new HLazyStatic( 3320 HInstruction instruction = new HLazyStatic(
3316 field, 3321 field,
3317 TypeMaskFactory.inferredTypeForElement(field, compiler)); 3322 TypeMaskFactory.inferredTypeForElement(field, compiler));
3318 push(instruction); 3323 push(instruction);
3319 } 3324 }
3320 } 3325 }
3321 3326
3322 /// Generate a getter invocation of the static or top level [getter]. 3327 /// Generate a getter invocation of the static or top level [getter].
3323 void generateStaticGetterGet(ast.Send node, MethodElement getter) { 3328 void generateStaticGetterGet(ast.Send node, MethodElement getter) {
3324 if (getter.isDeferredLoaderGetter) { 3329 if (getter.isDeferredLoaderGetter) {
3325 generateDeferredLoaderGet(node, getter); 3330 generateDeferredLoaderGet(node, getter);
3326 } else { 3331 } else {
3327 generateIsDeferredLoadedCheckIfNeeded(node); 3332 generateIsDeferredLoadedCheckOfSend(node);
3328 pushInvokeStatic(node, getter, <HInstruction>[]); 3333 pushInvokeStatic(node, getter, <HInstruction>[]);
3329 } 3334 }
3330 } 3335 }
3331 3336
3332 /// Generate a dynamic getter invocation. 3337 /// Generate a dynamic getter invocation.
3333 void generateDynamicGet(ast.Send node) { 3338 void generateDynamicGet(ast.Send node) {
3334 HInstruction receiver = generateInstanceSendReceiver(node); 3339 HInstruction receiver = generateInstanceSendReceiver(node);
3335 generateInstanceGetterWithCompiledReceiver( 3340 generateInstanceGetterWithCompiledReceiver(
3336 node, elements.getSelector(node), receiver); 3341 node, elements.getSelector(node), receiver);
3337 } 3342 }
3338 3343
3339 /// Generate a closurization of the static or top level [function]. 3344 /// Generate a closurization of the static or top level [function].
3340 void generateStaticFunctionGet(ast.Send node, MethodElement function) { 3345 void generateStaticFunctionGet(ast.Send node, MethodElement function) {
3341 generateIsDeferredLoadedCheckIfNeeded(node); 3346 generateIsDeferredLoadedCheckOfSend(node);
3342 // TODO(5346): Try to avoid the need for calling [declaration] before 3347 // TODO(5346): Try to avoid the need for calling [declaration] before
3343 // creating an [HStatic]. 3348 // creating an [HStatic].
3344 push(new HStatic(function.declaration, backend.nonNullType)); 3349 push(new HStatic(function.declaration, backend.nonNullType));
3345 // TODO(ahe): This should be registered in codegen. 3350 // TODO(ahe): This should be registered in codegen.
3346 registry.registerGetOfStaticFunction(function.declaration); 3351 registry.registerGetOfStaticFunction(function.declaration);
3347 } 3352 }
3348 3353
3349 /// Read a local variable, function or parameter. 3354 /// Read a local variable, function or parameter.
3350 void handleLocalGet(LocalElement local) { 3355 void handleLocalGet(LocalElement local) {
3351 stack.add(localsHandler.readLocal(local)); 3356 stack.add(localsHandler.readLocal(local));
(...skipping 1291 matching lines...) Expand 10 before | Expand all | Expand 10 after
4643 // The new object will now be referenced through the 4648 // The new object will now be referenced through the
4644 // `setRuntimeTypeInfo` call. We therefore set the type of that 4649 // `setRuntimeTypeInfo` call. We therefore set the type of that
4645 // instruction to be of the object's type. 4650 // instruction to be of the object's type.
4646 assert(stack.last is HInvokeStatic || stack.last == newObject); 4651 assert(stack.last is HInvokeStatic || stack.last == newObject);
4647 stack.last.instructionType = newObject.instructionType; 4652 stack.last.instructionType = newObject.instructionType;
4648 return pop(); 4653 return pop();
4649 } 4654 }
4650 4655
4651 handleNewSend(ast.NewExpression node) { 4656 handleNewSend(ast.NewExpression node) {
4652 ast.Send send = node.send; 4657 ast.Send send = node.send;
4653 generateIsDeferredLoadedCheckIfNeeded(send); 4658 generateIsDeferredLoadedCheckOfSend(send);
4654 4659
4655 bool isFixedList = false; 4660 bool isFixedList = false;
4656 bool isFixedListConstructorCall = 4661 bool isFixedListConstructorCall =
4657 Elements.isFixedListConstructorCall(elements[send], send, compiler); 4662 Elements.isFixedListConstructorCall(elements[send], send, compiler);
4658 bool isGrowableListConstructorCall = 4663 bool isGrowableListConstructorCall =
4659 Elements.isGrowableListConstructorCall(elements[send], send, compiler); 4664 Elements.isGrowableListConstructorCall(elements[send], send, compiler);
4660 4665
4661 TypeMask computeType(element) { 4666 TypeMask computeType(element) {
4662 Element originalElement = elements[send]; 4667 Element originalElement = elements[send];
4663 if (isFixedListConstructorCall 4668 if (isFixedListConstructorCall
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
4708 if (isSymbolConstructor) { 4713 if (isSymbolConstructor) {
4709 constructor = compiler.symbolValidatedConstructor; 4714 constructor = compiler.symbolValidatedConstructor;
4710 assert(invariant(send, constructor != null, 4715 assert(invariant(send, constructor != null,
4711 message: 'Constructor Symbol.validated is missing')); 4716 message: 'Constructor Symbol.validated is missing'));
4712 callStructure = compiler.symbolValidatedConstructorSelector.callStructure; 4717 callStructure = compiler.symbolValidatedConstructorSelector.callStructure;
4713 assert(invariant(send, callStructure != null, 4718 assert(invariant(send, callStructure != null,
4714 message: 'Constructor Symbol.validated is missing')); 4719 message: 'Constructor Symbol.validated is missing'));
4715 } 4720 }
4716 4721
4717 bool isRedirected = constructorDeclaration.isRedirectingFactory; 4722 bool isRedirected = constructorDeclaration.isRedirectingFactory;
4723 if (!constructorDeclaration.isCyclicRedirection) {
4724 // Insert a check for every deferred redirection on the path to the
4725 // final target.
4726 ConstructorElement target = constructorDeclaration;
4727 while (target.isRedirectingFactory) {
4728 if (constructorDeclaration.redirectionDeferredPrefix != null) {
4729 generateIsDeferredLoadedCheckIfNeeded(
4730 target.redirectionDeferredPrefix,
4731 node);
4732 }
4733 target = target.immediateRedirectionTarget;
4734 }
4735 }
4718 InterfaceType type = elements.getType(node); 4736 InterfaceType type = elements.getType(node);
4719 InterfaceType expectedType = 4737 InterfaceType expectedType =
4720 constructorDeclaration.computeEffectiveTargetType(type); 4738 constructorDeclaration.computeEffectiveTargetType(type);
4721 expectedType = localsHandler.substInContext(expectedType); 4739 expectedType = localsHandler.substInContext(expectedType);
4722 4740
4723 if (compiler.elementHasCompileTimeError(constructor)) { 4741 if (compiler.elementHasCompileTimeError(constructor)) {
4724 // TODO(ahe): Do something like [generateWrongArgumentCountError]. 4742 // TODO(ahe): Do something like [generateWrongArgumentCountError].
4725 stack.add(graph.addConstantNull(compiler)); 4743 stack.add(graph.addConstantNull(compiler));
4726 return; 4744 return;
4727 } 4745 }
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
4901 4919
4902 visitStaticSend(ast.Send node) { 4920 visitStaticSend(ast.Send node) {
4903 internalError(node, "Unexpected visitStaticSend"); 4921 internalError(node, "Unexpected visitStaticSend");
4904 } 4922 }
4905 4923
4906 /// Generate an invocation to the static or top level [function]. 4924 /// Generate an invocation to the static or top level [function].
4907 void generateStaticFunctionInvoke( 4925 void generateStaticFunctionInvoke(
4908 ast.Send node, 4926 ast.Send node,
4909 FunctionElement function, 4927 FunctionElement function,
4910 CallStructure callStructure) { 4928 CallStructure callStructure) {
4911 generateIsDeferredLoadedCheckIfNeeded(node); 4929 generateIsDeferredLoadedCheckOfSend(node);
4912 4930
4913 List<HInstruction> inputs = makeStaticArgumentList( 4931 List<HInstruction> inputs = makeStaticArgumentList(
4914 callStructure, 4932 callStructure,
4915 node.arguments, 4933 node.arguments,
4916 function.implementation); 4934 function.implementation);
4917 4935
4918 if (function == compiler.identicalFunction) { 4936 if (function == compiler.identicalFunction) {
4919 pushWithPosition( 4937 pushWithPosition(
4920 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); 4938 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node);
4921 return; 4939 return;
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
5116 ConstantExpression constant, 5134 ConstantExpression constant,
5117 ast.NodeList arguments, 5135 ast.NodeList arguments,
5118 CallStructure callStructure, 5136 CallStructure callStructure,
5119 _) { 5137 _) {
5120 generateConstantTypeLiteral(node); 5138 generateConstantTypeLiteral(node);
5121 generateTypeLiteralCall(node); 5139 generateTypeLiteralCall(node);
5122 } 5140 }
5123 5141
5124 /// Generate the constant value for a constant type literal. 5142 /// Generate the constant value for a constant type literal.
5125 void generateConstantTypeLiteral(ast.Send node) { 5143 void generateConstantTypeLiteral(ast.Send node) {
5126 generateIsDeferredLoadedCheckIfNeeded(node); 5144 generateIsDeferredLoadedCheckOfSend(node);
5127 // TODO(karlklose): add type representation 5145 // TODO(karlklose): add type representation
5128 if (node.isCall) { 5146 if (node.isCall) {
5129 // The node itself is not a constant but we register the selector (the 5147 // The node itself is not a constant but we register the selector (the
5130 // identifier that refers to the class/typedef) as a constant. 5148 // identifier that refers to the class/typedef) as a constant.
5131 stack.add(addConstant(node.selector)); 5149 stack.add(addConstant(node.selector));
5132 } else { 5150 } else {
5133 stack.add(addConstant(node)); 5151 stack.add(addConstant(node));
5134 } 5152 }
5135 } 5153 }
5136 5154
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
5440 rhs = pop(); 5458 rhs = pop();
5441 } 5459 }
5442 visitBinarySend(receiver, rhs, 5460 visitBinarySend(receiver, rhs,
5443 elements.getOperatorSelectorInComplexSendSet(node), 5461 elements.getOperatorSelectorInComplexSendSet(node),
5444 node, 5462 node,
5445 location: node.assignmentOperator); 5463 location: node.assignmentOperator);
5446 } 5464 }
5447 5465
5448 @override 5466 @override
5449 handleSendSet(ast.SendSet node) { 5467 handleSendSet(ast.SendSet node) {
5450 generateIsDeferredLoadedCheckIfNeeded(node); 5468 generateIsDeferredLoadedCheckOfSend(node);
5451 Element element = elements[node]; 5469 Element element = elements[node];
5452 if (!Elements.isUnresolved(element) && element.impliesType) { 5470 if (!Elements.isUnresolved(element) && element.impliesType) {
5453 ast.Identifier selector = node.selector; 5471 ast.Identifier selector = node.selector;
5454 generateThrowNoSuchMethod(node, selector.source, 5472 generateThrowNoSuchMethod(node, selector.source,
5455 argumentNodes: node.arguments); 5473 argumentNodes: node.arguments);
5456 return; 5474 return;
5457 } 5475 }
5458 ast.Operator op = node.assignmentOperator; 5476 ast.Operator op = node.assignmentOperator;
5459 if (node.isSuperCall) { 5477 if (node.isSuperCall) {
5460 HInstruction result; 5478 HInstruction result;
(...skipping 2152 matching lines...) Expand 10 before | Expand all | Expand 10 after
7613 if (unaliased is TypedefType) throw 'unable to unalias $type'; 7631 if (unaliased is TypedefType) throw 'unable to unalias $type';
7614 unaliased.accept(this, builder); 7632 unaliased.accept(this, builder);
7615 } 7633 }
7616 7634
7617 void visitDynamicType(DynamicType type, SsaBuilder builder) { 7635 void visitDynamicType(DynamicType type, SsaBuilder builder) {
7618 JavaScriptBackend backend = builder.compiler.backend; 7636 JavaScriptBackend backend = builder.compiler.backend;
7619 ClassElement cls = backend.findHelper('DynamicRuntimeType'); 7637 ClassElement cls = backend.findHelper('DynamicRuntimeType');
7620 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); 7638 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld)));
7621 } 7639 }
7622 } 7640 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/resolution/members.dart ('k') | tests/language/deferred_inheritance_constraints_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698