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 /** | 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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |