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 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 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 /** | 1231 /** |
1232 * Run through the fields of [cls] and add their potential | 1232 * Run through the fields of [cls] and add their potential |
1233 * initializers. | 1233 * initializers. |
1234 * | 1234 * |
1235 * Invariant: [classElement] must be an implementation element. | 1235 * Invariant: [classElement] must be an implementation element. |
1236 */ | 1236 */ |
1237 void buildFieldInitializers(ClassElement classElement, | 1237 void buildFieldInitializers(ClassElement classElement, |
1238 Map<Element, HInstruction> fieldValues) { | 1238 Map<Element, HInstruction> fieldValues) { |
1239 assert(invariant(classElement, classElement.isImplementation)); | 1239 assert(invariant(classElement, classElement.isImplementation)); |
1240 classElement.forEachInstanceField( | 1240 classElement.forEachInstanceField( |
| 1241 (ClassElement enclosingClass, Element member) { |
| 1242 TreeElements definitions = compiler.analyzeElement(member); |
| 1243 Node node = member.parseNode(compiler); |
| 1244 SendSet assignment = node.asSendSet(); |
| 1245 HInstruction value; |
| 1246 if (assignment === null) { |
| 1247 value = graph.addConstantNull(constantSystem); |
| 1248 } else { |
| 1249 Node right = assignment.arguments.head; |
| 1250 TreeElements savedElements = elements; |
| 1251 elements = definitions; |
| 1252 right.accept(this); |
| 1253 elements = savedElements; |
| 1254 value = pop(); |
| 1255 } |
| 1256 fieldValues[member] = value; |
| 1257 }, |
1241 includeBackendMembers: true, | 1258 includeBackendMembers: true, |
1242 includeSuperMembers: false, | 1259 includeSuperMembers: false); |
1243 f: (ClassElement enclosingClass, Element member) { | |
1244 TreeElements definitions = compiler.analyzeElement(member); | |
1245 Node node = member.parseNode(compiler); | |
1246 SendSet assignment = node.asSendSet(); | |
1247 HInstruction value; | |
1248 if (assignment === null) { | |
1249 value = graph.addConstantNull(constantSystem); | |
1250 } else { | |
1251 Node right = assignment.arguments.head; | |
1252 TreeElements savedElements = elements; | |
1253 elements = definitions; | |
1254 right.accept(this); | |
1255 elements = savedElements; | |
1256 value = pop(); | |
1257 } | |
1258 fieldValues[member] = value; | |
1259 }); | |
1260 } | 1260 } |
1261 | 1261 |
1262 | 1262 |
1263 /** | 1263 /** |
1264 * Build the factory function corresponding to the constructor | 1264 * Build the factory function corresponding to the constructor |
1265 * [functionElement]: | 1265 * [functionElement]: |
1266 * - Initialize fields with the values of the field initializers of the | 1266 * - Initialize fields with the values of the field initializers of the |
1267 * current constructor and super constructors or constructors redirected | 1267 * current constructor and super constructors or constructors redirected |
1268 * to, starting from the current constructor. | 1268 * to, starting from the current constructor. |
1269 * - Call the the constructor bodies, starting from the constructor(s) in the | 1269 * - Call the the constructor bodies, starting from the constructor(s) in the |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1303 }); | 1303 }); |
1304 | 1304 |
1305 // Analyze the constructor and all referenced constructors and collect | 1305 // Analyze the constructor and all referenced constructors and collect |
1306 // initializers and constructor bodies. | 1306 // initializers and constructor bodies. |
1307 List<FunctionElement> constructors = <FunctionElement>[functionElement]; | 1307 List<FunctionElement> constructors = <FunctionElement>[functionElement]; |
1308 buildInitializers(functionElement, constructors, fieldValues); | 1308 buildInitializers(functionElement, constructors, fieldValues); |
1309 | 1309 |
1310 // Call the JavaScript constructor with the fields as argument. | 1310 // Call the JavaScript constructor with the fields as argument. |
1311 List<HInstruction> constructorArguments = <HInstruction>[]; | 1311 List<HInstruction> constructorArguments = <HInstruction>[]; |
1312 classElement.forEachInstanceField( | 1312 classElement.forEachInstanceField( |
| 1313 (ClassElement enclosingClass, Element member) { |
| 1314 constructorArguments.add( |
| 1315 potentiallyCheckType(fieldValues[member], member)); |
| 1316 }, |
1313 includeBackendMembers: true, | 1317 includeBackendMembers: true, |
1314 includeSuperMembers: true, | 1318 includeSuperMembers: true); |
1315 f: (ClassElement enclosingClass, Element member) { | |
1316 constructorArguments.add( | |
1317 potentiallyCheckType(fieldValues[member], member)); | |
1318 }); | |
1319 | 1319 |
1320 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); | 1320 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); |
1321 add(newObject); | 1321 add(newObject); |
1322 | 1322 |
1323 // Create the runtime type information, if needed. | 1323 // Create the runtime type information, if needed. |
1324 InterfaceType type = classElement.computeType(compiler); | 1324 InterfaceType type = classElement.computeType(compiler); |
1325 List<HInstruction> inputs = <HInstruction>[]; | 1325 List<HInstruction> inputs = <HInstruction>[]; |
1326 if (compiler.world.needsRti(classElement)) { | 1326 if (compiler.world.needsRti(classElement)) { |
1327 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 1327 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
1328 inputs.add(localsHandler.directLocals[typeVariable.element]); | 1328 inputs.add(localsHandler.directLocals[typeVariable.element]); |
(...skipping 1671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3000 addDynamicSendArgumentsToList(node, inputs); | 3000 addDynamicSendArgumentsToList(node, inputs); |
3001 pushWithPosition(new HInvokeClosure(selector, inputs), node); | 3001 pushWithPosition(new HInvokeClosure(selector, inputs), node); |
3002 } | 3002 } |
3003 } | 3003 } |
3004 | 3004 |
3005 visitGetterSend(Send node) { | 3005 visitGetterSend(Send node) { |
3006 generateGetter(node, elements[node]); | 3006 generateGetter(node, elements[node]); |
3007 } | 3007 } |
3008 | 3008 |
3009 // TODO(antonm): migrate rest of SsaBuilder to internalError. | 3009 // TODO(antonm): migrate rest of SsaBuilder to internalError. |
3010 internalError(String reason, [Node node]) { | 3010 internalError(String reason, {Node node}) { |
3011 compiler.internalError(reason, node: node); | 3011 compiler.internalError(reason, node: node); |
3012 } | 3012 } |
3013 | 3013 |
3014 void generateRuntimeError(Node node, String message) { | 3014 void generateRuntimeError(Node node, String message) { |
3015 DartString messageObject = new DartString.literal(message); | 3015 DartString messageObject = new DartString.literal(message); |
3016 Constant messageConstant = | 3016 Constant messageConstant = |
3017 constantSystem.createString(messageObject, node); | 3017 constantSystem.createString(messageObject, node); |
3018 HInstruction errorMessage = graph.addConstant(messageConstant); | 3018 HInstruction errorMessage = graph.addConstant(messageConstant); |
3019 Element helper = interceptors.getThrowRuntimeError(); | 3019 Element helper = interceptors.getThrowRuntimeError(); |
3020 pushInvokeHelper1(helper, errorMessage); | 3020 pushInvokeHelper1(helper, errorMessage); |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3311 for (Link<Node> link = node.elements.nodes; | 3311 for (Link<Node> link = node.elements.nodes; |
3312 !link.isEmpty(); | 3312 !link.isEmpty(); |
3313 link = link.tail) { | 3313 link = link.tail) { |
3314 visit(link.head); | 3314 visit(link.head); |
3315 inputs.add(pop()); | 3315 inputs.add(pop()); |
3316 } | 3316 } |
3317 push(new HLiteralList(inputs)); | 3317 push(new HLiteralList(inputs)); |
3318 } | 3318 } |
3319 | 3319 |
3320 visitConditional(Conditional node) { | 3320 visitConditional(Conditional node) { |
3321 SsaBranchBuilder brancher = | 3321 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
3322 new SsaBranchBuilder(this, diagnosticNode: node); | |
3323 brancher.handleConditional(() => visit(node.condition), | 3322 brancher.handleConditional(() => visit(node.condition), |
3324 () => visit(node.thenExpression), | 3323 () => visit(node.thenExpression), |
3325 () => visit(node.elseExpression)); | 3324 () => visit(node.elseExpression)); |
3326 } | 3325 } |
3327 | 3326 |
3328 visitStringInterpolation(StringInterpolation node) { | 3327 visitStringInterpolation(StringInterpolation node) { |
3329 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); | 3328 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); |
3330 stringBuilder.visit(node); | 3329 stringBuilder.visit(node); |
3331 stack.add(stringBuilder.result); | 3330 stack.add(stringBuilder.result); |
3332 } | 3331 } |
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4282 | 4281 |
4283 conditionBranch.graph = | 4282 conditionBranch.graph = |
4284 new SubExpression(conditionBranch.block, conditionExitBlock); | 4283 new SubExpression(conditionBranch.block, conditionExitBlock); |
4285 } | 4284 } |
4286 | 4285 |
4287 /** | 4286 /** |
4288 * Returns true if the locals of the [fromBranch] may be reused. A [:true:] | 4287 * Returns true if the locals of the [fromBranch] may be reused. A [:true:] |
4289 * return value implies that [mayReuseFromLocals] was set to [:true:]. | 4288 * return value implies that [mayReuseFromLocals] was set to [:true:]. |
4290 */ | 4289 */ |
4291 bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch, | 4290 bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch, |
4292 [bool mayReuseFromLocals]) { | 4291 {bool mayReuseFromLocals}) { |
4293 LocalsHandler fromLocals = fromBranch.exitLocals; | 4292 LocalsHandler fromLocals = fromBranch.exitLocals; |
4294 if (toBranch.startLocals == null) { | 4293 if (toBranch.startLocals == null) { |
4295 if (mayReuseFromLocals) { | 4294 if (mayReuseFromLocals) { |
4296 toBranch.startLocals = fromLocals; | 4295 toBranch.startLocals = fromLocals; |
4297 return false; | 4296 return false; |
4298 } else { | 4297 } else { |
4299 toBranch.startLocals = new LocalsHandler.from(fromLocals); | 4298 toBranch.startLocals = new LocalsHandler.from(fromLocals); |
4300 return true; | 4299 return true; |
4301 } | 4300 } |
4302 } else { | 4301 } else { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4341 } | 4340 } |
4342 | 4341 |
4343 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); | 4342 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); |
4344 } | 4343 } |
4345 | 4344 |
4346 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { | 4345 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { |
4347 assert(visitElse != null); | 4346 assert(visitElse != null); |
4348 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); | 4347 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); |
4349 } | 4348 } |
4350 | 4349 |
4351 void handleLogicalAndOr(void left(), void right(), [bool isAnd]) { | 4350 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) { |
4352 // x && y is transformed into: | 4351 // x && y is transformed into: |
4353 // t0 = boolify(x); | 4352 // t0 = boolify(x); |
4354 // if (t0) { | 4353 // if (t0) { |
4355 // t1 = boolify(y); | 4354 // t1 = boolify(y); |
4356 // } | 4355 // } |
4357 // result = phi(t1, false); | 4356 // result = phi(t1, false); |
4358 // | 4357 // |
4359 // x || y is transformed into: | 4358 // x || y is transformed into: |
4360 // t0 = boolify(x); | 4359 // t0 = boolify(x); |
4361 // if (not(t0)) { | 4360 // if (not(t0)) { |
(...skipping 21 matching lines...) Expand all Loading... |
4383 HConstant notIsAnd = | 4382 HConstant notIsAnd = |
4384 builder.graph.addConstantBool(!isAnd, builder.constantSystem); | 4383 builder.graph.addConstantBool(!isAnd, builder.constantSystem); |
4385 HPhi result = new HPhi.manyInputs(null, | 4384 HPhi result = new HPhi.manyInputs(null, |
4386 <HInstruction>[boolifiedRight, notIsAnd]); | 4385 <HInstruction>[boolifiedRight, notIsAnd]); |
4387 builder.current.addPhi(result); | 4386 builder.current.addPhi(result); |
4388 builder.stack.add(result); | 4387 builder.stack.add(result); |
4389 } | 4388 } |
4390 | 4389 |
4391 void handleLogicalAndOrWithLeftNode(Node left, | 4390 void handleLogicalAndOrWithLeftNode(Node left, |
4392 void visitRight(), | 4391 void visitRight(), |
4393 [bool isAnd]) { | 4392 {bool isAnd}) { |
4394 // This method is similar to [handleLogicalAndOr] but optimizes the case | 4393 // This method is similar to [handleLogicalAndOr] but optimizes the case |
4395 // where left is a logical "and" or logical "or". | 4394 // where left is a logical "and" or logical "or". |
4396 // | 4395 // |
4397 // For example (x && y) && z is transformed into x && (y && z): | 4396 // For example (x && y) && z is transformed into x && (y && z): |
4398 // t0 = boolify(x); | 4397 // t0 = boolify(x); |
4399 // if (t0) { | 4398 // if (t0) { |
4400 // t1 = boolify(y); | 4399 // t1 = boolify(y); |
4401 // if (t1) { | 4400 // if (t1) { |
4402 // t2 = boolify(z); | 4401 // t2 = boolify(z); |
4403 // } | 4402 // } |
4404 // t3 = phi(t2, false); | 4403 // t3 = phi(t2, false); |
4405 // } | 4404 // } |
4406 // result = phi(t3, false); | 4405 // result = phi(t3, false); |
4407 | 4406 |
4408 Send send = left.asSend(); | 4407 Send send = left.asSend(); |
4409 if (send !== null && | 4408 if (send !== null && |
4410 (isAnd ? send.isLogicalAnd : send.isLogicalOr)) { | 4409 (isAnd ? send.isLogicalAnd : send.isLogicalOr)) { |
4411 Node newLeft = send.receiver; | 4410 Node newLeft = send.receiver; |
4412 Link<Node> link = send.argumentsNode.nodes; | 4411 Link<Node> link = send.argumentsNode.nodes; |
4413 assert(link.tail.isEmpty()); | 4412 assert(link.tail.isEmpty()); |
4414 Node middle = link.head; | 4413 Node middle = link.head; |
4415 handleLogicalAndOrWithLeftNode( | 4414 handleLogicalAndOrWithLeftNode( |
4416 newLeft, | 4415 newLeft, |
4417 () => handleLogicalAndOrWithLeftNode(middle, visitRight, isAnd), | 4416 () => handleLogicalAndOrWithLeftNode(middle, visitRight, |
| 4417 isAnd: isAnd), |
4418 isAnd: isAnd); | 4418 isAnd: isAnd); |
4419 } else { | 4419 } else { |
4420 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd); | 4420 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd); |
4421 } | 4421 } |
4422 } | 4422 } |
4423 | 4423 |
4424 void _handleDiamondBranch(void visitCondition(), | 4424 void _handleDiamondBranch(void visitCondition(), |
4425 void visitThen(), | 4425 void visitThen(), |
4426 void visitElse(), | 4426 void visitElse(), |
4427 bool isExpression) { | 4427 bool isExpression) { |
4428 SsaBranch conditionBranch = new SsaBranch(this); | 4428 SsaBranch conditionBranch = new SsaBranch(this); |
4429 SsaBranch thenBranch = new SsaBranch(this); | 4429 SsaBranch thenBranch = new SsaBranch(this); |
4430 SsaBranch elseBranch = new SsaBranch(this); | 4430 SsaBranch elseBranch = new SsaBranch(this); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4463 new HSubGraphBlockInformation(elseBranch.graph)); | 4463 new HSubGraphBlockInformation(elseBranch.graph)); |
4464 | 4464 |
4465 HBasicBlock conditionStartBlock = conditionBranch.block; | 4465 HBasicBlock conditionStartBlock = conditionBranch.block; |
4466 conditionStartBlock.setBlockFlow(info, joinBlock); | 4466 conditionStartBlock.setBlockFlow(info, joinBlock); |
4467 SubGraph conditionGraph = conditionBranch.graph; | 4467 SubGraph conditionGraph = conditionBranch.graph; |
4468 HIf branch = conditionGraph.end.last; | 4468 HIf branch = conditionGraph.end.last; |
4469 assert(branch is HIf); | 4469 assert(branch is HIf); |
4470 branch.blockInformation = conditionStartBlock.blockFlow; | 4470 branch.blockInformation = conditionStartBlock.blockFlow; |
4471 } | 4471 } |
4472 } | 4472 } |
OLD | NEW |