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

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

Issue 12389046: Re-apply: Inside a generative constructor, "this" is created at the very end. So we have to use the… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 /** 7 /**
8 * A special element for the extra parameter taken by intercepted 8 * A special element for the extra parameter taken by intercepted
9 * methods. We need to override [Element.computeType] because our 9 * methods. We need to override [Element.computeType] because our
10 * optimizers may look at its declared type. 10 * optimizers may look at its declared type.
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 } 178 }
179 179
180 /** 180 /**
181 * If the scope (function or loop) [node] has captured variables then this 181 * If the scope (function or loop) [node] has captured variables then this
182 * method creates a box and sets up the redirections. 182 * method creates a box and sets up the redirections.
183 */ 183 */
184 void enterScope(Node node, Element element) { 184 void enterScope(Node node, Element element) {
185 // See if any variable in the top-scope of the function is captured. If yes 185 // See if any variable in the top-scope of the function is captured. If yes
186 // we need to create a box-object. 186 // we need to create a box-object.
187 ClosureScope scopeData = closureData.capturingScopes[node]; 187 ClosureScope scopeData = closureData.capturingScopes[node];
188 if (scopeData != null) { 188 if (scopeData == null) return;
189 HInstruction box; 189 HInstruction box;
190 // The scope has captured variables. 190 // The scope has captured variables.
191 if (element != null && element.isGenerativeConstructorBody()) { 191 if (element != null && element.isGenerativeConstructorBody()) {
192 // The box is passed as a parameter to a generative 192 // The box is passed as a parameter to a generative
193 // constructor body. 193 // constructor body.
194 box = builder.addParameter(scopeData.boxElement); 194 box = builder.addParameter(scopeData.boxElement);
195 } else {
196 box = createBox();
197 }
198 // Add the box to the known locals.
199 directLocals[scopeData.boxElement] = box;
200 // Make sure that accesses to the boxed locals go into the box. We also
201 // need to make sure that parameters are copied into the box if necessary.
202 scopeData.capturedVariableMapping.forEach((Element from, Element to) {
203 // The [from] can only be a parameter for function-scopes and not
204 // loop scopes.
205 if (from.isParameter() && !element.isGenerativeConstructorBody()) {
206 // Now that the redirection is set up, the update to the local will
207 // write the parameter value into the box.
208 // Store the captured parameter in the box. Get the current value
209 // before we put the redirection in place.
210 // We don't need to update the local for a generative
211 // constructor body, because it receives a box that already
212 // contains the updates as the last parameter.
213 HInstruction instruction = readLocal(from);
214 redirectElement(from, to);
215 updateLocal(from, instruction);
195 } else { 216 } else {
196 box = createBox(); 217 redirectElement(from, to);
197 } 218 }
198 // Add the box to the known locals. 219 });
199 directLocals[scopeData.boxElement] = box;
200 // Make sure that accesses to the boxed locals go into the box. We also
201 // need to make sure that parameters are copied into the box if necessary.
202 scopeData.capturedVariableMapping.forEach((Element from, Element to) {
203 // The [from] can only be a parameter for function-scopes and not
204 // loop scopes.
205 if (from.isParameter() && !element.isGenerativeConstructorBody()) {
206 // Now that the redirection is set up, the update to the local will
207 // write the parameter value into the box.
208 // Store the captured parameter in the box. Get the current value
209 // before we put the redirection in place.
210 // We don't need to update the local for a generative
211 // constructor body, because it receives a box that already
212 // contains the updates as the last parameter.
213 HInstruction instruction = readLocal(from);
214 redirectElement(from, to);
215 updateLocal(from, instruction);
216 } else {
217 redirectElement(from, to);
218 }
219 });
220 }
221 } 220 }
222 221
223 /** 222 /**
224 * Replaces the current box with a new box and copies over the given list 223 * Replaces the current box with a new box and copies over the given list
225 * of elements from the old box into the new box. 224 * of elements from the old box into the new box.
226 */ 225 */
227 void updateCaptureBox(Element boxElement, List<Element> toBeCopiedElements) { 226 void updateCaptureBox(Element boxElement, List<Element> toBeCopiedElements) {
228 // Create a new box and copy over the values from the old box into the 227 // Create a new box and copy over the values from the old box into the
229 // new one. 228 // new one.
230 HInstruction oldBox = readLocal(boxElement); 229 HInstruction oldBox = readLocal(boxElement);
(...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after
1137 * Documentation wanted -- johnniwinther 1136 * Documentation wanted -- johnniwinther
1138 * 1137 *
1139 * Invariant: [constructor] and [constructors] must all be implementation 1138 * Invariant: [constructor] and [constructors] must all be implementation
1140 * elements. 1139 * elements.
1141 */ 1140 */
1142 void inlineSuperOrRedirect(FunctionElement constructor, 1141 void inlineSuperOrRedirect(FunctionElement constructor,
1143 Selector selector, 1142 Selector selector,
1144 Link<Node> arguments, 1143 Link<Node> arguments,
1145 List<FunctionElement> constructors, 1144 List<FunctionElement> constructors,
1146 Map<Element, HInstruction> fieldValues, 1145 Map<Element, HInstruction> fieldValues,
1147 FunctionElement inlinedFromElement) { 1146 FunctionElement inlinedFromElement,
1147 Node callNode) {
1148 compiler.withCurrentElement(constructor, () { 1148 compiler.withCurrentElement(constructor, () {
1149 assert(invariant(constructor, constructor.isImplementation)); 1149 assert(invariant(constructor, constructor.isImplementation));
1150 constructors.addLast(constructor); 1150 constructors.addLast(constructor);
1151 1151
1152 List<HInstruction> compiledArguments = new List<HInstruction>(); 1152 List<HInstruction> compiledArguments = new List<HInstruction>();
1153 bool succeeded = 1153 bool succeeded =
1154 inlinedFrom(inlinedFromElement, 1154 inlinedFrom(inlinedFromElement,
1155 () => addStaticSendArgumentsToList(selector, 1155 () => addStaticSendArgumentsToList(selector,
1156 arguments, 1156 arguments,
1157 constructor, 1157 constructor,
1158 compiledArguments)); 1158 compiledArguments));
1159 if (!succeeded) { 1159 if (!succeeded) {
1160 // Non-matching super and redirects are compile-time errors and thus 1160 // Non-matching super and redirects are compile-time errors and thus
1161 // checked by the resolver. 1161 // checked by the resolver.
1162 compiler.internalError( 1162 compiler.internalError(
1163 "Parameters and arguments didn't match for super/redirect call", 1163 "Parameters and arguments didn't match for super/redirect call",
1164 element: constructor); 1164 element: constructor);
1165 } 1165 }
1166 1166
1167 ClassElement superclass = constructor.getEnclosingClass();
1168 if (compiler.world.needsRti(superclass)) {
1169 // If [superclass] needs RTI, we have to give a value to its
1170 // type parameters. Those values are in the [supertype]
1171 // declaration of [subclass].
1172 ClassElement subclass = inlinedFromElement.getEnclosingClass();
1173 DartType supertype = subclass.supertype;
1174 Link<DartType> typeVariables = superclass.typeVariables;
1175 supertype.typeArguments.forEach((DartType argument) {
1176 localsHandler.updateLocal(typeVariables.head.element,
1177 analyzeTypeArgument(argument, callNode));
1178 typeVariables = typeVariables.tail;
1179 });
1180 // If the supertype is a raw type, we need to set to null the
1181 // type variables.
1182 assert(typeVariables.isEmpty
1183 || superclass.typeVariables == typeVariables);
1184 while (!typeVariables.isEmpty) {
1185 localsHandler.updateLocal(typeVariables.head.element,
1186 graph.addConstantNull(constantSystem));
1187 typeVariables = typeVariables.tail;
1188 }
1189 }
1190
1167 inlinedFrom(constructor, () { 1191 inlinedFrom(constructor, () {
1168 buildFieldInitializers(constructor.enclosingElement.implementation, 1192 buildFieldInitializers(constructor.enclosingElement.implementation,
1169 fieldValues); 1193 fieldValues);
1170 }); 1194 });
1171 1195
1172 int index = 0; 1196 int index = 0;
1173 FunctionSignature params = constructor.computeSignature(compiler); 1197 FunctionSignature params = constructor.computeSignature(compiler);
1174 params.orderedForEachParameter((Element parameter) { 1198 params.orderedForEachParameter((Element parameter) {
1175 HInstruction argument = compiledArguments[index++]; 1199 HInstruction argument = compiledArguments[index++];
1176 // Because we are inlining the initializer, we must update 1200 // Because we are inlining the initializer, we must update
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 assert(link.head is Send); 1263 assert(link.head is Send);
1240 if (link.head is !SendSet) { 1264 if (link.head is !SendSet) {
1241 // A super initializer or constructor redirection. 1265 // A super initializer or constructor redirection.
1242 Send call = link.head; 1266 Send call = link.head;
1243 assert(Initializers.isSuperConstructorCall(call) || 1267 assert(Initializers.isSuperConstructorCall(call) ||
1244 Initializers.isConstructorRedirect(call)); 1268 Initializers.isConstructorRedirect(call));
1245 FunctionElement target = elements[call]; 1269 FunctionElement target = elements[call];
1246 Selector selector = elements.getSelector(call); 1270 Selector selector = elements.getSelector(call);
1247 Link<Node> arguments = call.arguments; 1271 Link<Node> arguments = call.arguments;
1248 inlineSuperOrRedirect(target, selector, arguments, constructors, 1272 inlineSuperOrRedirect(target, selector, arguments, constructors,
1249 fieldValues, constructor); 1273 fieldValues, constructor, call);
1250 foundSuperOrRedirect = true; 1274 foundSuperOrRedirect = true;
1251 } else { 1275 } else {
1252 // A field initializer. 1276 // A field initializer.
1253 SendSet init = link.head; 1277 SendSet init = link.head;
1254 Link<Node> arguments = init.arguments; 1278 Link<Node> arguments = init.arguments;
1255 assert(!arguments.isEmpty && arguments.tail.isEmpty); 1279 assert(!arguments.isEmpty && arguments.tail.isEmpty);
1256 inlinedFrom(constructor, () { 1280 inlinedFrom(constructor, () {
1257 visit(arguments.head); 1281 visit(arguments.head);
1258 }); 1282 });
1259 fieldValues[elements[init]] = pop(); 1283 fieldValues[elements[init]] = pop();
(...skipping 14 matching lines...) Expand all
1274 // TODO(johnniwinther): Should we find injected constructors as well? 1298 // TODO(johnniwinther): Should we find injected constructors as well?
1275 FunctionElement target = superClass.lookupConstructor(selector); 1299 FunctionElement target = superClass.lookupConstructor(selector);
1276 if (target == null) { 1300 if (target == null) {
1277 compiler.internalError("no default constructor available"); 1301 compiler.internalError("no default constructor available");
1278 } 1302 }
1279 inlineSuperOrRedirect(target.implementation, 1303 inlineSuperOrRedirect(target.implementation,
1280 selector, 1304 selector,
1281 const Link<Node>(), 1305 const Link<Node>(),
1282 constructors, 1306 constructors,
1283 fieldValues, 1307 fieldValues,
1284 constructor); 1308 constructor,
1309 functionNode);
1285 } 1310 }
1286 } 1311 }
1287 } 1312 }
1288 1313
1289 /** 1314 /**
1290 * Run through the fields of [cls] and add their potential 1315 * Run through the fields of [cls] and add their potential
1291 * initializers. 1316 * initializers.
1292 * 1317 *
1293 * Invariant: [classElement] must be an implementation element. 1318 * Invariant: [classElement] must be an implementation element.
1294 */ 1319 */
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1382 includeSuperMembers: true); 1407 includeSuperMembers: true);
1383 1408
1384 InterfaceType type = classElement.computeType(compiler); 1409 InterfaceType type = classElement.computeType(compiler);
1385 HType ssaType = new HType.nonNullExactClass(type, compiler); 1410 HType ssaType = new HType.nonNullExactClass(type, compiler);
1386 HForeignNew newObject = new HForeignNew(classElement, 1411 HForeignNew newObject = new HForeignNew(classElement,
1387 ssaType, 1412 ssaType,
1388 constructorArguments); 1413 constructorArguments);
1389 add(newObject); 1414 add(newObject);
1390 1415
1391 // Create the runtime type information, if needed. 1416 // Create the runtime type information, if needed.
1392 List<HInstruction> inputs = <HInstruction>[];
1393 if (compiler.world.needsRti(classElement)) { 1417 if (compiler.world.needsRti(classElement)) {
1418 List<HInstruction> rtiInputs = <HInstruction>[];
1394 classElement.typeVariables.forEach((TypeVariableType typeVariable) { 1419 classElement.typeVariables.forEach((TypeVariableType typeVariable) {
1395 inputs.add(localsHandler.directLocals[typeVariable.element]); 1420 rtiInputs.add(localsHandler.readLocal(typeVariable.element));
1396 }); 1421 });
1397 callSetRuntimeTypeInfo(classElement, inputs, newObject); 1422 callSetRuntimeTypeInfo(classElement, rtiInputs, newObject);
1398 } 1423 }
1399 1424
1400 // Generate calls to the constructor bodies. 1425 // Generate calls to the constructor bodies.
1401 for (int index = constructors.length - 1; index >= 0; index--) { 1426 for (int index = constructors.length - 1; index >= 0; index--) {
1402 FunctionElement constructor = constructors[index]; 1427 FunctionElement constructor = constructors[index];
1403 assert(invariant(functionElement, constructor.isImplementation)); 1428 assert(invariant(functionElement, constructor.isImplementation));
1404 ConstructorBodyElement body = getConstructorBody(constructor); 1429 ConstructorBodyElement body = getConstructorBody(constructor);
1405 if (body == null) continue; 1430 if (body == null) continue;
1406 List bodyCallInputs = <HInstruction>[]; 1431 List bodyCallInputs = <HInstruction>[];
1407 bodyCallInputs.add(newObject); 1432 bodyCallInputs.add(newObject);
1408 FunctionSignature functionSignature = body.computeSignature(compiler);
1409 functionSignature.orderedForEachParameter((parameter) {
1410 if (!localsHandler.isBoxed(parameter)) {
1411 // The parameter will be a field in the box passed as the
1412 // last parameter. So no need to pass it.
1413 bodyCallInputs.add(localsHandler.readLocal(parameter));
1414 }
1415 });
1416
1417 // If parameters are checked, we pass the already computed
1418 // boolean to the constructor body.
1419 TreeElements elements = 1433 TreeElements elements =
1420 compiler.enqueuer.resolution.getCachedElements(constructor); 1434 compiler.enqueuer.resolution.getCachedElements(constructor);
1421 Node node = constructor.parseNode(compiler); 1435 Node node = constructor.parseNode(compiler);
1422 ClosureClassMap parameterClosureData = 1436 ClosureClassMap parameterClosureData =
1423 compiler.closureToClassMapper.getMappingForNestedFunction(node); 1437 compiler.closureToClassMapper.getMappingForNestedFunction(node);
1438
1439
1440 FunctionSignature functionSignature = body.computeSignature(compiler);
1424 functionSignature.orderedForEachParameter((parameter) { 1441 functionSignature.orderedForEachParameter((parameter) {
1442 // if [parameter] is boxed, it will be a field in the box passed as the
1443 // last parameter. So no need to direclty pass it.
1444 if (!localsHandler.isBoxed(parameter)) {
1445 bodyCallInputs.add(localsHandler.readLocal(parameter));
1446 }
1447 // If [parameter] is checked, we pass the already computed
1448 // boolean to the constructor body.
1425 if (elements.isParameterChecked(parameter)) { 1449 if (elements.isParameterChecked(parameter)) {
1426 Element fieldCheck = 1450 Element fieldCheck =
1427 parameterClosureData.parametersWithSentinel[parameter]; 1451 parameterClosureData.parametersWithSentinel[parameter];
1428 bodyCallInputs.add(localsHandler.readLocal(fieldCheck)); 1452 bodyCallInputs.add(localsHandler.readLocal(fieldCheck));
1429 } 1453 }
1430 }); 1454 });
1431 1455
1432 // If there are locals that escape (ie used in closures), we 1456 ClassElement currentClass = constructor.getEnclosingClass();
1457 if (compiler.world.needsRti(currentClass)) {
1458 // If [currentClass] needs RTI, we add the type variables as
1459 // parameters of the generative constructor body.
1460 currentClass.typeVariables.forEach((DartType argument) {
1461 bodyCallInputs.add(localsHandler.readLocal(argument.element));
1462 });
1463 }
1464
1465 // If there are locals that escape (ie mutated in closures), we
1433 // pass the box to the constructor. 1466 // pass the box to the constructor.
1434 ClosureScope scopeData = parameterClosureData.capturingScopes[node]; 1467 ClosureScope scopeData = parameterClosureData.capturingScopes[node];
1435 if (scopeData != null) { 1468 if (scopeData != null) {
1436 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement)); 1469 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement));
1437 } 1470 }
1438 1471
1439 // TODO(ahe): The constructor name is statically resolved. See 1472 // TODO(ahe): The constructor name is statically resolved. See
1440 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner 1473 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner
1441 // way to do this? 1474 // way to do this?
1442 SourceString name = 1475 SourceString name =
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1553 1586
1554 returnType = signature.returnType; 1587 returnType = signature.returnType;
1555 } else { 1588 } else {
1556 // Otherwise it is a lazy initializer which does not have parameters. 1589 // Otherwise it is a lazy initializer which does not have parameters.
1557 assert(element is VariableElement); 1590 assert(element is VariableElement);
1558 } 1591 }
1559 1592
1560 // Add the type parameters of the class as parameters of this 1593 // Add the type parameters of the class as parameters of this
1561 // method. 1594 // method.
1562 var enclosing = element.enclosingElement; 1595 var enclosing = element.enclosingElement;
1563 if (element.isConstructor() && compiler.world.needsRti(enclosing)) { 1596 if ((element.isConstructor() || element.isGenerativeConstructorBody())
1597 && compiler.world.needsRti(enclosing)) {
1564 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { 1598 enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
1565 HParameterValue param = addParameter(typeVariable.element); 1599 HParameterValue param = addParameter(typeVariable.element);
1566 localsHandler.directLocals[typeVariable.element] = param; 1600 localsHandler.directLocals[typeVariable.element] = param;
1567 }); 1601 });
1568 } 1602 }
1569 } 1603 }
1570 1604
1571 HInstruction potentiallyCheckType( 1605 HInstruction potentiallyCheckType(
1572 HInstruction original, DartType type, 1606 HInstruction original, DartType type,
1573 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { 1607 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) {
(...skipping 1523 matching lines...) Expand 10 before | Expand all | Expand 10 after
3097 /** 3131 /**
3098 * Helper to create an instruction that gets the value of a type variable. 3132 * Helper to create an instruction that gets the value of a type variable.
3099 */ 3133 */
3100 HInstruction addTypeVariableReference(TypeVariableType type) { 3134 HInstruction addTypeVariableReference(TypeVariableType type) {
3101 Element member = currentElement; 3135 Element member = currentElement;
3102 if (member.enclosingElement.isClosure()) { 3136 if (member.enclosingElement.isClosure()) {
3103 ClosureClassElement closureClass = member.enclosingElement; 3137 ClosureClassElement closureClass = member.enclosingElement;
3104 member = closureClass.methodElement; 3138 member = closureClass.methodElement;
3105 member = member.getOutermostEnclosingMemberOrTopLevel(); 3139 member = member.getOutermostEnclosingMemberOrTopLevel();
3106 } 3140 }
3107 if (member.isFactoryConstructor()) { 3141 if (member.isConstructor() || member.isGenerativeConstructorBody()) {
3108 // The type variable is stored in a parameter of the method. 3142 // The type variable is stored in a parameter of the method.
3109 return localsHandler.readLocal(type.element); 3143 return localsHandler.readLocal(type.element);
3110 } else if (member.isInstanceMember() || 3144 } else if (member.isInstanceMember()) {
3111 member.isGenerativeConstructor()) {
3112 // The type variable is stored on the object. Generate code to extract 3145 // The type variable is stored on the object. Generate code to extract
3113 // the type arguments from the object, substitute them as an instance 3146 // the type arguments from the object, substitute them as an instance
3114 // of the type we are testing against (if necessary), and extract the 3147 // of the type we are testing against (if necessary), and extract the
3115 // type argument by the index of the variable in the list of type 3148 // type argument by the index of the variable in the list of type
3116 // variables for that class. 3149 // variables for that class.
3117 int index = RuntimeTypeInformation.getTypeVariableIndex(type); 3150 int index = RuntimeTypeInformation.getTypeVariableIndex(type);
3118 HInstruction thisObject = localsHandler.readThis(); 3151 HInstruction thisObject = localsHandler.readThis();
3119 String substitutionNameString = 3152 String substitutionNameString =
3120 backend.namer.substitutionName(member.getEnclosingClass()); 3153 backend.namer.substitutionName(member.getEnclosingClass());
3121 HInstruction substitutionName = graph.addConstantString( 3154 HInstruction substitutionName = graph.addConstantString(
(...skipping 1855 matching lines...) Expand 10 before | Expand all | Expand 10 after
4977 new HSubGraphBlockInformation(elseBranch.graph)); 5010 new HSubGraphBlockInformation(elseBranch.graph));
4978 5011
4979 HBasicBlock conditionStartBlock = conditionBranch.block; 5012 HBasicBlock conditionStartBlock = conditionBranch.block;
4980 conditionStartBlock.setBlockFlow(info, joinBlock); 5013 conditionStartBlock.setBlockFlow(info, joinBlock);
4981 SubGraph conditionGraph = conditionBranch.graph; 5014 SubGraph conditionGraph = conditionBranch.graph;
4982 HIf branch = conditionGraph.end.last; 5015 HIf branch = conditionGraph.end.last;
4983 assert(branch is HIf); 5016 assert(branch is HIf);
4984 branch.blockInformation = conditionStartBlock.blockFlow; 5017 branch.blockInformation = conditionStartBlock.blockFlow;
4985 } 5018 }
4986 } 5019 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/closure.dart ('k') | sdk/lib/_internal/compiler/implementation/world.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698