Chromium Code Reviews| 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 class Interceptors { | 7 class Interceptors { |
| 8 Compiler compiler; | 8 Compiler compiler; |
| 9 Interceptors(Compiler this.compiler); | 9 Interceptors(Compiler this.compiler); |
| 10 | 10 |
| (...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 860 class SsaBuilder extends ResolvedVisitor implements Visitor { | 860 class SsaBuilder extends ResolvedVisitor implements Visitor { |
| 861 final SsaBuilderTask builder; | 861 final SsaBuilderTask builder; |
| 862 final JavaScriptBackend backend; | 862 final JavaScriptBackend backend; |
| 863 final Interceptors interceptors; | 863 final Interceptors interceptors; |
| 864 final WorkItem work; | 864 final WorkItem work; |
| 865 final ConstantSystem constantSystem; | 865 final ConstantSystem constantSystem; |
| 866 bool methodInterceptionEnabled; | 866 bool methodInterceptionEnabled; |
| 867 HGraph graph; | 867 HGraph graph; |
| 868 LocalsHandler localsHandler; | 868 LocalsHandler localsHandler; |
| 869 HInstruction rethrowableException; | 869 HInstruction rethrowableException; |
| 870 Map<Element, HParameterValue> parameters; | 870 Map<Element, HInstruction> parameters; |
| 871 final RuntimeTypeInformation rti; | 871 final RuntimeTypeInformation rti; |
| 872 | 872 |
| 873 Map<TargetElement, JumpHandler> jumpTargets; | 873 Map<TargetElement, JumpHandler> jumpTargets; |
| 874 | 874 |
| 875 /** | 875 /** |
| 876 * Variables stored in the current activation. These variables are | 876 * Variables stored in the current activation. These variables are |
| 877 * being updated in try/catch blocks, and should be | 877 * being updated in try/catch blocks, and should be |
| 878 * accessed indirectly through [HLocalGet] and [HLocalSet]. | 878 * accessed indirectly through [HLocalGet] and [HLocalSet]. |
| 879 */ | 879 */ |
| 880 Map<Element, HLocalValue> activationVariables; | 880 Map<Element, HLocalValue> activationVariables; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 900 SsaBuilder(this.constantSystem, SsaBuilderTask builder, WorkItem work) | 900 SsaBuilder(this.constantSystem, SsaBuilderTask builder, WorkItem work) |
| 901 : this.builder = builder, | 901 : this.builder = builder, |
| 902 this.backend = builder.backend, | 902 this.backend = builder.backend, |
| 903 this.work = work, | 903 this.work = work, |
| 904 interceptors = builder.interceptors, | 904 interceptors = builder.interceptors, |
| 905 methodInterceptionEnabled = true, | 905 methodInterceptionEnabled = true, |
| 906 graph = new HGraph(), | 906 graph = new HGraph(), |
| 907 stack = new List<HInstruction>(), | 907 stack = new List<HInstruction>(), |
| 908 activationVariables = new Map<Element, HLocalValue>(), | 908 activationVariables = new Map<Element, HLocalValue>(), |
| 909 jumpTargets = new Map<TargetElement, JumpHandler>(), | 909 jumpTargets = new Map<TargetElement, JumpHandler>(), |
| 910 parameters = new Map<Element, HParameterValue>(), | 910 parameters = new Map<Element, HInstruction>(), |
| 911 sourceElementStack = <Element>[work.element], | 911 sourceElementStack = <Element>[work.element], |
| 912 inliningStack = <InliningState>[], | 912 inliningStack = <InliningState>[], |
| 913 rti = builder.compiler.codegenWorld.rti, | 913 rti = builder.compiler.codegenWorld.rti, |
| 914 super(work.resolutionTree) { | 914 super(work.resolutionTree) { |
| 915 localsHandler = new LocalsHandler(this); | 915 localsHandler = new LocalsHandler(this); |
| 916 } | 916 } |
| 917 | 917 |
| 918 static const MAX_INLINING_DEPTH = 3; | 918 static const MAX_INLINING_DEPTH = 3; |
| 919 static const MAX_INLINING_SOURCE_SIZE = 100; | 919 static const MAX_INLINING_SOURCE_SIZE = 100; |
| 920 List<InliningState> inliningStack; | 920 List<InliningState> inliningStack; |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1146 | 1146 |
| 1147 sourceElementStack.add(constructor.enclosingElement); | 1147 sourceElementStack.add(constructor.enclosingElement); |
| 1148 buildFieldInitializers(constructor.enclosingElement.implementation, | 1148 buildFieldInitializers(constructor.enclosingElement.implementation, |
| 1149 fieldValues); | 1149 fieldValues); |
| 1150 sourceElementStack.removeLast(); | 1150 sourceElementStack.removeLast(); |
| 1151 | 1151 |
| 1152 int index = 0; | 1152 int index = 0; |
| 1153 FunctionSignature params = constructor.computeSignature(compiler); | 1153 FunctionSignature params = constructor.computeSignature(compiler); |
| 1154 params.orderedForEachParameter((Element parameter) { | 1154 params.orderedForEachParameter((Element parameter) { |
| 1155 HInstruction argument = compiledArguments[index++]; | 1155 HInstruction argument = compiledArguments[index++]; |
| 1156 // Because we are inlining the initializer, we must update | |
| 1157 // what was given as parameter. This will be used in case | |
| 1158 // there is a parameter check expression in the initializer. | |
| 1159 parameters[parameter] = argument; | |
| 1156 localsHandler.updateLocal(parameter, argument); | 1160 localsHandler.updateLocal(parameter, argument); |
| 1157 // Don't forget to update the field, if the parameter is of the | 1161 // Don't forget to update the field, if the parameter is of the |
| 1158 // form [:this.x:]. | 1162 // form [:this.x:]. |
| 1159 if (parameter.kind == ElementKind.FIELD_PARAMETER) { | 1163 if (parameter.kind == ElementKind.FIELD_PARAMETER) { |
| 1160 FieldParameterElement fieldParameterElement = parameter; | 1164 FieldParameterElement fieldParameterElement = parameter; |
| 1161 fieldValues[fieldParameterElement.fieldElement] = argument; | 1165 fieldValues[fieldParameterElement.fieldElement] = argument; |
| 1162 } | 1166 } |
| 1163 }); | 1167 }); |
| 1164 | 1168 |
| 1165 // Build the initializers in the context of the new constructor. | 1169 // Build the initializers in the context of the new constructor. |
| 1166 TreeElements oldElements = elements; | 1170 TreeElements oldElements = elements; |
| 1167 elements = | 1171 elements = |
| 1168 compiler.enqueuer.resolution.getCachedElements(constructor); | 1172 compiler.enqueuer.resolution.getCachedElements(constructor); |
| 1173 | |
| 1174 ClosureClassMap oldClosureData = localsHandler.closureData; | |
| 1175 localsHandler.closureData = | |
| 1176 compiler.closureToClassMapper.computeClosureToClassMapping( | |
| 1177 constructor, constructor.parseNode(compiler), elements); | |
| 1178 | |
| 1179 params.orderedForEachParameter((Element parameterElement) { | |
| 1180 if (elements.isParameterChecked(parameterElement)) { | |
| 1181 addParameterCheckInstruction(parameterElement); | |
| 1182 } | |
| 1183 }); | |
| 1184 | |
| 1169 buildInitializers(constructor, constructors, fieldValues); | 1185 buildInitializers(constructor, constructors, fieldValues); |
| 1186 localsHandler.closureData = oldClosureData; | |
| 1170 elements = oldElements; | 1187 elements = oldElements; |
| 1171 }); | 1188 }); |
| 1172 } | 1189 } |
| 1173 | 1190 |
| 1174 /** | 1191 /** |
| 1175 * Run through the initializers and inline all field initializers. Recursively | 1192 * Run through the initializers and inline all field initializers. Recursively |
| 1176 * inlines super initializers. | 1193 * inlines super initializers. |
| 1177 * | 1194 * |
| 1178 * The constructors of the inlined initializers is added to [constructors] | 1195 * The constructors of the inlined initializers is added to [constructors] |
| 1179 * with sub constructors having a lower index than super constructors. | 1196 * with sub constructors having a lower index than super constructors. |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1349 assert(invariant(functionElement, constructor.isImplementation)); | 1366 assert(invariant(functionElement, constructor.isImplementation)); |
| 1350 ConstructorBodyElement body = getConstructorBody(constructor); | 1367 ConstructorBodyElement body = getConstructorBody(constructor); |
| 1351 if (body == null) continue; | 1368 if (body == null) continue; |
| 1352 List bodyCallInputs = <HInstruction>[]; | 1369 List bodyCallInputs = <HInstruction>[]; |
| 1353 bodyCallInputs.add(newObject); | 1370 bodyCallInputs.add(newObject); |
| 1354 FunctionSignature functionSignature = body.computeSignature(compiler); | 1371 FunctionSignature functionSignature = body.computeSignature(compiler); |
| 1355 int arity = functionSignature.parameterCount; | 1372 int arity = functionSignature.parameterCount; |
| 1356 functionSignature.orderedForEachParameter((parameter) { | 1373 functionSignature.orderedForEachParameter((parameter) { |
| 1357 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 1374 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| 1358 }); | 1375 }); |
| 1376 | |
| 1377 // If parameters are checked, we pass what we already computed | |
|
floitsch
2012/10/29 21:45:45
If parameters are checked, we pass the already com
ngeoffray
2012/10/30 09:34:46
Done.
| |
| 1378 // for checking it to the constructor body. | |
| 1379 TreeElements elements = | |
| 1380 compiler.enqueuer.resolution.getCachedElements(constructor); | |
| 1381 Node node = constructor.parseNode(compiler); | |
| 1382 ClosureClassMap parameterClosureData = | |
| 1383 compiler.closureToClassMapper.getMappingForNestedFunction(node); | |
| 1384 functionSignature.orderedForEachParameter((parameter) { | |
| 1385 if (elements.isParameterChecked(parameter)) { | |
| 1386 Element fieldCheck = | |
| 1387 parameterClosureData.parametersWithSentinel[parameter]; | |
| 1388 bodyCallInputs.add(localsHandler.readLocal(fieldCheck)); | |
| 1389 } | |
| 1390 }); | |
| 1391 | |
| 1359 // TODO(ahe): The constructor name is statically resolved. See | 1392 // TODO(ahe): The constructor name is statically resolved. See |
| 1360 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner | 1393 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner |
| 1361 // way to do this? | 1394 // way to do this? |
| 1362 SourceString name = | 1395 SourceString name = |
| 1363 new SourceString(backend.namer.getName(body.declaration)); | 1396 new SourceString(backend.namer.getName(body.declaration)); |
| 1364 // TODO(kasperl): This seems fishy. We shouldn't be inventing all | 1397 // TODO(kasperl): This seems fishy. We shouldn't be inventing all |
| 1365 // these selectors. Maybe the resolver can do more of the work | 1398 // these selectors. Maybe the resolver can do more of the work |
| 1366 // for us here? | 1399 // for us here? |
| 1367 LibraryElement library = body.getLibrary(); | 1400 LibraryElement library = body.getLibrary(); |
| 1368 Selector selector = new Selector.call(name, library, arity); | 1401 Selector selector = new Selector.call(name, library, arity); |
| 1369 HInvokeDynamic invoke = | 1402 HInvokeDynamic invoke = |
| 1370 new HInvokeDynamicMethod(selector, bodyCallInputs); | 1403 new HInvokeDynamicMethod(selector, bodyCallInputs); |
| 1371 invoke.element = body; | 1404 invoke.element = body; |
| 1372 add(invoke); | 1405 add(invoke); |
| 1373 } | 1406 } |
| 1374 close(new HReturn(newObject)).addSuccessor(graph.exit); | 1407 close(new HReturn(newObject)).addSuccessor(graph.exit); |
| 1375 return closeFunction(); | 1408 return closeFunction(); |
| 1376 } | 1409 } |
| 1377 | 1410 |
| 1378 void addParameterCheckInstruction(Element element) { | 1411 void addParameterCheckInstruction(Element element) { |
| 1379 // This is the code we emit for a parameter that is being checked | 1412 HInstruction check; |
|
floitsch
2012/10/29 21:45:45
Keep the declaration at the use-point. No need to
ngeoffray
2012/10/30 09:34:46
The variable is used outside the if/else (line 146
| |
| 1380 // on whether it was given at value at the call site: | 1413 Element checkResultElement = |
| 1381 // | 1414 localsHandler.closureData.parametersWithSentinel[element]; |
| 1382 // foo([a = 42) { | 1415 if (currentElement.isGenerativeConstructorBody()) { |
| 1383 // if (?a) print('parameter passed $a'); | 1416 // A generative constructor body gets the information that a |
| 1384 // } | 1417 // parameter was passed in extra parameters. |
|
floitsch
2012/10/29 21:45:45
A generative constructor body receives extra param
ngeoffray
2012/10/30 09:34:46
Done.
| |
| 1385 // | 1418 check = new HParameterValue(checkResultElement); |
| 1386 // foo([a = 42]) { | 1419 add(check); |
| 1387 // var t1 = a === sentinel; | 1420 } else { |
|
floitsch
2012/10/29 21:45:45
You could avoid the else (and the indentation) by
ngeoffray
2012/10/30 09:34:46
No, there's a shared updateLocal call line 1462.
| |
| 1388 // if (t1) a = 42; | 1421 // This is the code we emit for a parameter that is being checked |
| 1389 // if (!t1) print('parameter passed ' + a); | 1422 // on whether it was given at value at the call site: |
| 1390 // } | 1423 // |
| 1424 // foo([a = 42) { | |
| 1425 // if (?a) print('parameter passed $a'); | |
| 1426 // } | |
| 1427 // | |
| 1428 // foo([a = 42]) { | |
| 1429 // var t1 = a === sentinel; | |
| 1430 // if (t1) a = 42; | |
| 1431 // if (!t1) print('parameter passed ' + a); | |
| 1432 // } | |
| 1391 | 1433 |
| 1392 // Fetch the original default value of [element]; | 1434 // Fetch the original default value of [element]; |
| 1393 ConstantHandler handler = compiler.constantHandler; | 1435 ConstantHandler handler = compiler.constantHandler; |
| 1394 Constant constant = handler.compileVariable(element); | 1436 Constant constant = handler.compileVariable(element); |
| 1395 HConstant defaultValue = constant == null | 1437 HConstant defaultValue = constant == null |
| 1396 ? graph.addConstantNull(constantSystem) | 1438 ? graph.addConstantNull(constantSystem) |
| 1397 : graph.addConstant(constant); | 1439 : graph.addConstant(constant); |
| 1398 | 1440 |
| 1399 // Emit the equality check with the sentinel. | 1441 // Emit the equality check with the sentinel. |
| 1400 HConstant sentinel = graph.addConstant(SentinelConstant.SENTINEL); | 1442 HConstant sentinel = graph.addConstant(SentinelConstant.SENTINEL); |
| 1401 Element equalsHelper = interceptors.getTripleEqualsInterceptor(); | 1443 Element equalsHelper = interceptors.getTripleEqualsInterceptor(); |
| 1402 HInstruction target = new HStatic(equalsHelper); | 1444 HInstruction target = new HStatic(equalsHelper); |
| 1403 add(target); | 1445 add(target); |
| 1404 HInstruction operand = parameters[element]; | 1446 HInstruction operand = parameters[element]; |
| 1405 HInstruction check = new HIdentity(target, sentinel, operand); | 1447 check = new HIdentity(target, sentinel, operand); |
| 1406 add(check); | 1448 add(check); |
| 1407 | 1449 |
| 1408 // If the check succeeds, we must update the parameter with the | 1450 // If the check succeeds, we must update the parameter with the |
| 1409 // default value. | 1451 // default value. |
| 1410 handleIf(element.parseNode(compiler), | 1452 handleIf(element.parseNode(compiler), |
| 1411 () => stack.add(check), | 1453 () => stack.add(check), |
| 1412 () => localsHandler.updateLocal(element, defaultValue), | 1454 () => localsHandler.updateLocal(element, defaultValue), |
| 1413 null); | 1455 null); |
| 1414 | 1456 |
| 1415 // Create the instruction that parameter checks will use. | 1457 // Create the instruction that parameter checks will use. |
| 1416 check = new HNot(check); | 1458 check = new HNot(check); |
| 1417 add(check); | 1459 add(check); |
| 1460 } | |
| 1418 | 1461 |
| 1419 ClosureClassMap closureData = localsHandler.closureData; | |
| 1420 Element checkResultElement = closureData.parametersWithSentinel[element]; | |
| 1421 localsHandler.updateLocal(checkResultElement, check); | 1462 localsHandler.updateLocal(checkResultElement, check); |
| 1422 } | 1463 } |
| 1423 | 1464 |
| 1424 /** | 1465 /** |
| 1425 * Documentation wanted -- johnniwinther | 1466 * Documentation wanted -- johnniwinther |
| 1426 * | 1467 * |
| 1427 * Invariant: [functionElement] must be the implementation element. | 1468 * Invariant: [functionElement] must be the implementation element. |
| 1428 */ | 1469 */ |
| 1429 void openFunction(Element element, Expression node) { | 1470 void openFunction(Element element, Expression node) { |
| 1430 assert(invariant(element, element.isImplementation)); | 1471 assert(invariant(element, element.isImplementation)); |
| (...skipping 3119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4550 new HSubGraphBlockInformation(elseBranch.graph)); | 4591 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4551 | 4592 |
| 4552 HBasicBlock conditionStartBlock = conditionBranch.block; | 4593 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4553 conditionStartBlock.setBlockFlow(info, joinBlock); | 4594 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4554 SubGraph conditionGraph = conditionBranch.graph; | 4595 SubGraph conditionGraph = conditionBranch.graph; |
| 4555 HIf branch = conditionGraph.end.last; | 4596 HIf branch = conditionGraph.end.last; |
| 4556 assert(branch is HIf); | 4597 assert(branch is HIf); |
| 4557 branch.blockInformation = conditionStartBlock.blockFlow; | 4598 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4558 } | 4599 } |
| 4559 } | 4600 } |
| OLD | NEW |