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

Side by Side Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10913133: Allow closures inside lazy initializers. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 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 class Interceptors { 5 class Interceptors {
6 Compiler compiler; 6 Compiler compiler;
7 Interceptors(Compiler this.compiler); 7 Interceptors(Compiler this.compiler);
8 8
9 SourceString mapOperatorToMethodName(Operator op) { 9 SourceString mapOperatorToMethodName(Operator op) {
10 String name = op.source.stringValue; 10 String name = op.source.stringValue;
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY || 166 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
167 kind === ElementKind.FUNCTION || 167 kind === ElementKind.FUNCTION ||
168 kind === ElementKind.GETTER || 168 kind === ElementKind.GETTER ||
169 kind === ElementKind.SETTER) { 169 kind === ElementKind.SETTER) {
170 graph = builder.buildMethod(work.element); 170 graph = builder.buildMethod(work.element);
171 } else if (kind === ElementKind.FIELD) { 171 } else if (kind === ElementKind.FIELD) {
172 graph = builder.buildLazyInitializer(work.element); 172 graph = builder.buildLazyInitializer(work.element);
173 } 173 }
174 assert(graph.isValid()); 174 assert(graph.isValid());
175 if (kind !== ElementKind.FIELD) { 175 if (kind !== ElementKind.FIELD) {
176 FunctionElement functionElement = element;
176 bool inLoop = functionsCalledInLoop.contains(element); 177 bool inLoop = functionsCalledInLoop.contains(element);
177 if (!inLoop) { 178 if (!inLoop) {
178 Selector selector = selectorsCalledInLoop[element.name]; 179 Selector selector = selectorsCalledInLoop[element.name];
179 inLoop = selector !== null && selector.applies(element, compiler); 180 inLoop = selector !== null && selector.applies(element, compiler);
180 } 181 }
181 graph.calledInLoop = inLoop; 182 graph.calledInLoop = inLoop;
182 183
183 // If there is an estimate of the parameter types assume these types whe n 184 // If there is an estimate of the parameter types assume these types whe n
kasperl 2012/09/10 13:44:29 Long line. NYF.
floitsch 2012/10/09 16:06:44 Has been fixed in the mean-time.
184 // compiling. 185 // compiling.
185 OptionalParameterTypes defaultValueTypes = null; 186 OptionalParameterTypes defaultValueTypes = null;
186 FunctionSignature signature = element.computeSignature(compiler); 187 FunctionSignature signature =
188 functionElement.computeSignature(compiler);
187 if (signature.optionalParameterCount > 0) { 189 if (signature.optionalParameterCount > 0) {
188 defaultValueTypes = 190 defaultValueTypes =
189 new OptionalParameterTypes(signature.optionalParameterCount); 191 new OptionalParameterTypes(signature.optionalParameterCount);
190 int index = 0; 192 int index = 0;
191 signature.forEachOptionalParameter((Element parameter) { 193 signature.forEachOptionalParameter((Element parameter) {
192 Constant defaultValue = compiler.compileVariable(parameter); 194 Constant defaultValue = compiler.compileVariable(parameter);
193 HType type = HGraph.mapConstantTypeToSsaType(defaultValue); 195 HType type = HGraph.mapConstantTypeToSsaType(defaultValue);
194 defaultValueTypes.update(index, parameter.name, type); 196 defaultValueTypes.update(index, parameter.name, type);
195 index++; 197 index++;
196 }); 198 });
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 // [readLocal] uses the [boxElement] to find its box. By replacing it 335 // [readLocal] uses the [boxElement] to find its box. By replacing it
334 // behind its back we can still get to the old values. 336 // behind its back we can still get to the old values.
335 updateLocal(boxElement, oldBox); 337 updateLocal(boxElement, oldBox);
336 HInstruction oldValue = readLocal(boxedVariable); 338 HInstruction oldValue = readLocal(boxedVariable);
337 updateLocal(boxElement, newBox); 339 updateLocal(boxElement, newBox);
338 updateLocal(boxedVariable, oldValue); 340 updateLocal(boxedVariable, oldValue);
339 } 341 }
340 updateLocal(boxElement, newBox); 342 updateLocal(boxElement, newBox);
341 } 343 }
342 344
343 void startFunction(FunctionElement function, 345 void startFunction(Element element, Expression node) {
344 FunctionExpression node) {
345 Compiler compiler = builder.compiler; 346 Compiler compiler = builder.compiler;
346 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( 347 closureData = compiler.closureToClassMapper.computeClosureToClassMapping(
347 node, builder.elements); 348 element, node, builder.elements);
348 FunctionSignature signature = function.computeSignature(compiler); 349
349 signature.forEachParameter((Element element) { 350 if (element is FunctionElement) {
350 HInstruction parameter = new HParameterValue(element); 351 FunctionElement functionElement = element;
351 builder.add(parameter); 352 FunctionSignature params = functionElement.computeSignature(compiler);
352 builder.parameters[element] = parameter; 353 params.forEachParameter((Element parameterElement) {
353 directLocals[element] = parameter; 354 HInstruction parameter = new HParameterValue(parameterElement);
354 parameter.guaranteedType = 355 builder.add(parameter);
355 builder.mapInferredType(typesTask.getGuaranteedTypeOfElement(element)); 356 builder.parameters[parameterElement] = parameter;
356 }); 357 directLocals[parameterElement] = parameter;
358 parameter.guaranteedType =
359 builder.mapInferredType(
360 typesTask.getGuaranteedTypeOfElement(parameterElement));
361 });
362 }
357 363
358 enterScope(node); 364 enterScope(node);
359 365
360 // If the freeVariableMapping is not empty, then this function was a 366 // If the freeVariableMapping is not empty, then this function was a
361 // nested closure that captures variables. Redirect the captured 367 // nested closure that captures variables. Redirect the captured
362 // variables to fields in the closure. 368 // variables to fields in the closure.
363 closureData.freeVariableMapping.forEach((Element from, Element to) { 369 closureData.freeVariableMapping.forEach((Element from, Element to) {
364 redirectElement(from, to); 370 redirectElement(from, to);
365 }); 371 });
366 if (closureData.isClosure()) { 372 if (closureData.isClosure()) {
367 // Inside closure redirect references to itself to [:this:]. 373 // Inside closure redirect references to itself to [:this:].
368 HInstruction thisInstruction = new HThis(); 374 HInstruction thisInstruction = new HThis();
369 builder.add(thisInstruction); 375 builder.add(thisInstruction);
370 updateLocal(closureData.closureElement, thisInstruction); 376 updateLocal(closureData.closureElement, thisInstruction);
371 } else if (function.isInstanceMember() 377 } else if (element.isInstanceMember()
372 || function.isGenerativeConstructor()) { 378 || element.isGenerativeConstructor()) {
373 // Once closures have been mapped to classes their instance members might 379 // Once closures have been mapped to classes their instance members might
374 // not have any thisElement if the closure was created inside a static 380 // not have any thisElement if the closure was created inside a static
375 // context. 381 // context.
376 ClassElement cls = function.getEnclosingClass(); 382 ClassElement cls = element.getEnclosingClass();
377 DartType type = cls.computeType(builder.compiler); 383 DartType type = cls.computeType(builder.compiler);
378 HInstruction thisInstruction = new HThis(new HBoundedType.nonNull(type)); 384 HInstruction thisInstruction = new HThis(new HBoundedType.nonNull(type));
379 builder.add(thisInstruction); 385 builder.add(thisInstruction);
380 directLocals[closureData.thisElement] = thisInstruction; 386 directLocals[closureData.thisElement] = thisInstruction;
381 } 387 }
382 } 388 }
383 389
384 bool hasValueForDirectLocal(Element element) { 390 bool hasValueForDirectLocal(Element element) {
385 assert(element !== null); 391 assert(element !== null);
386 assert(isAccessedDirectly(element)); 392 assert(isAccessedDirectly(element));
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 } 889 }
884 890
885 HGraph buildMethod(FunctionElement functionElement) { 891 HGraph buildMethod(FunctionElement functionElement) {
886 FunctionExpression function = functionElement.parseNode(compiler); 892 FunctionExpression function = functionElement.parseNode(compiler);
887 openFunction(functionElement, function); 893 openFunction(functionElement, function);
888 function.body.accept(this); 894 function.body.accept(this);
889 return closeFunction(); 895 return closeFunction();
890 } 896 }
891 897
892 HGraph buildLazyInitializer(VariableElement variable) { 898 HGraph buildLazyInitializer(VariableElement variable) {
893 HBasicBlock block = graph.addNewBlock();
894 open(graph.entry);
895 close(new HGoto()).addSuccessor(block);
896 open(block);
897 SendSet node = variable.parseNode(compiler); 899 SendSet node = variable.parseNode(compiler);
900 openFunction(variable, node);
898 Link<Node> link = node.arguments; 901 Link<Node> link = node.arguments;
899 assert(!link.isEmpty() && link.tail.isEmpty()); 902 assert(!link.isEmpty() && link.tail.isEmpty());
900 visit(link.head); 903 visit(link.head);
901 close(new HReturn(pop())).addSuccessor(graph.exit); 904 close(new HReturn(pop())).addSuccessor(graph.exit);
902 graph.finalize(); 905 return closeFunction();
903 return graph;
904 } 906 }
905 907
906 /** 908 /**
907 * Returns the constructor body associated with the given constructor or 909 * Returns the constructor body associated with the given constructor or
908 * creates a new constructor body, if none can be found. 910 * creates a new constructor body, if none can be found.
909 * 911 *
910 * Returns [:null:] if the constructor does not have a body. 912 * Returns [:null:] if the constructor does not have a body.
911 */ 913 */
912 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { 914 ConstructorBodyElement getConstructorBody(FunctionElement constructor) {
913 assert(constructor.isGenerativeConstructor()); 915 assert(constructor.isGenerativeConstructor());
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
1306 1308
1307 // Create the instruction that parameter checks will use. 1309 // Create the instruction that parameter checks will use.
1308 check = new HNot(check); 1310 check = new HNot(check);
1309 add(check); 1311 add(check);
1310 1312
1311 ClosureClassMap closureData = localsHandler.closureData; 1313 ClosureClassMap closureData = localsHandler.closureData;
1312 Element checkResultElement = closureData.parametersWithSentinel[element]; 1314 Element checkResultElement = closureData.parametersWithSentinel[element];
1313 localsHandler.updateLocal(checkResultElement, check); 1315 localsHandler.updateLocal(checkResultElement, check);
1314 } 1316 }
1315 1317
1316 void openFunction(FunctionElement functionElement, 1318 void openFunction(Element element, Expression node) {
1317 FunctionExpression node) {
1318 HBasicBlock block = graph.addNewBlock(); 1319 HBasicBlock block = graph.addNewBlock();
1319 open(graph.entry); 1320 open(graph.entry);
1320 1321
1321 localsHandler.startFunction(functionElement, node); 1322 localsHandler.startFunction(element, node);
1322 close(new HGoto()).addSuccessor(block); 1323 close(new HGoto()).addSuccessor(block);
1323 1324
1324 open(block); 1325 open(block);
1325 1326
1326 FunctionSignature params = functionElement.computeSignature(compiler); 1327 if (element is FunctionElement) {
1327 params.forEachParameter((Element element) { 1328 FunctionElement functionElement = element;
1328 if (elements.isParameterChecked(element)) { 1329 FunctionSignature params = functionElement.computeSignature(compiler);
1329 addParameterCheckInstruction(element); 1330 params.forEachParameter((Element parameterElement) {
1330 } 1331 if (elements.isParameterChecked(parameterElement)) {
1331 }); 1332 addParameterCheckInstruction(parameterElement);
1333 }
1334 });
1332 1335
1333 // Put the type checks in the first successor of the entry, 1336 // Put the type checks in the first successor of the entry,
1334 // because that is where the type guards will also be inserted. 1337 // because that is where the type guards will also be inserted.
1335 // This way we ensure that a type guard will dominate the type 1338 // This way we ensure that a type guard will dominate the type
1336 // check. 1339 // check.
1337 params.forEachParameter((Element element) { 1340 params.forEachParameter((Element element) {
1338 HInstruction newParameter = potentiallyCheckType( 1341 HInstruction newParameter = potentiallyCheckType(
1339 localsHandler.directLocals[element], element); 1342 localsHandler.directLocals[element], element);
1340 localsHandler.directLocals[element] = newParameter; 1343 localsHandler.directLocals[element] = newParameter;
1341 }); 1344 });
1345 } else {
1346 // Otherwise it is a lazy initializer which does not have parameters.
1347 assert(element is VariableElement);
1348 }
1342 1349
1343 // Add the type parameters of the class as parameters of this 1350 // Add the type parameters of the class as parameters of this
1344 // method. 1351 // method.
1345 if (functionElement.isFactoryConstructor() 1352 if (element.isFactoryConstructor()
1346 || functionElement.isGenerativeConstructor()) { 1353 || element.isGenerativeConstructor()) {
1347 ClassElement cls = functionElement.enclosingElement; 1354 ClassElement cls = element.enclosingElement;
1348 cls.typeVariables.forEach((TypeVariableType typeVariable) { 1355 cls.typeVariables.forEach((TypeVariableType typeVariable) {
1349 HParameterValue param = new HParameterValue(typeVariable.element); 1356 HParameterValue param = new HParameterValue(typeVariable.element);
1350 add(param); 1357 add(param);
1351 localsHandler.directLocals[typeVariable.element] = param; 1358 localsHandler.directLocals[typeVariable.element] = param;
1352 }); 1359 });
1353 } 1360 }
1354 } 1361 }
1355 1362
1356 HInstruction potentiallyCheckType(HInstruction original, 1363 HInstruction potentiallyCheckType(HInstruction original,
1357 Element sourceElement) { 1364 Element sourceElement) {
(...skipping 1352 matching lines...) Expand 10 before | Expand all | Expand 10 after
2710 Element helper = interceptors.getThrowRuntimeError(); 2717 Element helper = interceptors.getThrowRuntimeError();
2711 pushInvokeHelper1(helper, errorMessage); 2718 pushInvokeHelper1(helper, errorMessage);
2712 } 2719 }
2713 2720
2714 void generateThrowNoSuchMethod(Node diagnosticNode, 2721 void generateThrowNoSuchMethod(Node diagnosticNode,
2715 String methodName, 2722 String methodName,
2716 [Link<Node> argumentNodes, 2723 [Link<Node> argumentNodes,
2717 List<HInstruction> argumentValues]) { 2724 List<HInstruction> argumentValues]) {
2718 Element helper = 2725 Element helper =
2719 compiler.findHelper(const SourceString('throwNoSuchMethod')); 2726 compiler.findHelper(const SourceString('throwNoSuchMethod'));
2720 Constant receiverConstant = 2727 Constant receiverConstant =
2721 constantSystem.createString(new DartString.empty(), diagnosticNode); 2728 constantSystem.createString(new DartString.empty(), diagnosticNode);
2722 HInstruction receiver = graph.addConstant(receiverConstant); 2729 HInstruction receiver = graph.addConstant(receiverConstant);
2723 DartString dartString = new DartString.literal(methodName); 2730 DartString dartString = new DartString.literal(methodName);
2724 Constant nameConstant = 2731 Constant nameConstant =
2725 constantSystem.createString(dartString, diagnosticNode); 2732 constantSystem.createString(dartString, diagnosticNode);
2726 HInstruction name = graph.addConstant(nameConstant); 2733 HInstruction name = graph.addConstant(nameConstant);
2727 if (argumentValues == null) { 2734 if (argumentValues == null) {
2728 argumentValues = <HInstruction>[]; 2735 argumentValues = <HInstruction>[];
2729 argumentNodes.forEach((argumentNode) { 2736 argumentNodes.forEach((argumentNode) {
2730 visit(argumentNode); 2737 visit(argumentNode);
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after
4072 new HSubGraphBlockInformation(elseBranch.graph)); 4079 new HSubGraphBlockInformation(elseBranch.graph));
4073 4080
4074 HBasicBlock conditionStartBlock = conditionBranch.block; 4081 HBasicBlock conditionStartBlock = conditionBranch.block;
4075 conditionStartBlock.setBlockFlow(info, joinBlock); 4082 conditionStartBlock.setBlockFlow(info, joinBlock);
4076 SubGraph conditionGraph = conditionBranch.graph; 4083 SubGraph conditionGraph = conditionBranch.graph;
4077 HIf branch = conditionGraph.end.last; 4084 HIf branch = conditionGraph.end.last;
4078 assert(branch is HIf); 4085 assert(branch is HIf);
4079 branch.blockInformation = conditionStartBlock.blockFlow; 4086 branch.blockInformation = conditionStartBlock.blockFlow;
4080 } 4087 }
4081 } 4088 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698