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 1225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 /** | 1236 /** |
1237 * Run through the fields of [cls] and add their potential | 1237 * Run through the fields of [cls] and add their potential |
1238 * initializers. | 1238 * initializers. |
1239 * | 1239 * |
1240 * Invariant: [classElement] must be an implementation element. | 1240 * Invariant: [classElement] must be an implementation element. |
1241 */ | 1241 */ |
1242 void buildFieldInitializers(ClassElement classElement, | 1242 void buildFieldInitializers(ClassElement classElement, |
1243 Map<Element, HInstruction> fieldValues) { | 1243 Map<Element, HInstruction> fieldValues) { |
1244 assert(invariant(classElement, classElement.isImplementation)); | 1244 assert(invariant(classElement, classElement.isImplementation)); |
1245 classElement.forEachInstanceField( | 1245 classElement.forEachInstanceField( |
| 1246 (ClassElement enclosingClass, Element member) { |
| 1247 TreeElements definitions = compiler.analyzeElement(member); |
| 1248 Node node = member.parseNode(compiler); |
| 1249 SendSet assignment = node.asSendSet(); |
| 1250 HInstruction value; |
| 1251 if (assignment === null) { |
| 1252 value = graph.addConstantNull(constantSystem); |
| 1253 } else { |
| 1254 Node right = assignment.arguments.head; |
| 1255 TreeElements savedElements = elements; |
| 1256 elements = definitions; |
| 1257 right.accept(this); |
| 1258 elements = savedElements; |
| 1259 value = pop(); |
| 1260 } |
| 1261 fieldValues[member] = value; |
| 1262 }, |
1246 includeBackendMembers: true, | 1263 includeBackendMembers: true, |
1247 includeSuperMembers: false, | 1264 includeSuperMembers: false); |
1248 f: (ClassElement enclosingClass, Element member) { | |
1249 TreeElements definitions = compiler.analyzeElement(member); | |
1250 Node node = member.parseNode(compiler); | |
1251 SendSet assignment = node.asSendSet(); | |
1252 HInstruction value; | |
1253 if (assignment === null) { | |
1254 value = graph.addConstantNull(constantSystem); | |
1255 } else { | |
1256 Node right = assignment.arguments.head; | |
1257 TreeElements savedElements = elements; | |
1258 elements = definitions; | |
1259 right.accept(this); | |
1260 elements = savedElements; | |
1261 value = pop(); | |
1262 } | |
1263 fieldValues[member] = value; | |
1264 }); | |
1265 } | 1265 } |
1266 | 1266 |
1267 | 1267 |
1268 /** | 1268 /** |
1269 * Build the factory function corresponding to the constructor | 1269 * Build the factory function corresponding to the constructor |
1270 * [functionElement]: | 1270 * [functionElement]: |
1271 * - Initialize fields with the values of the field initializers of the | 1271 * - Initialize fields with the values of the field initializers of the |
1272 * current constructor and super constructors or constructors redirected | 1272 * current constructor and super constructors or constructors redirected |
1273 * to, starting from the current constructor. | 1273 * to, starting from the current constructor. |
1274 * - Call the the constructor bodies, starting from the constructor(s) in the | 1274 * - 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... |
1308 }); | 1308 }); |
1309 | 1309 |
1310 // Analyze the constructor and all referenced constructors and collect | 1310 // Analyze the constructor and all referenced constructors and collect |
1311 // initializers and constructor bodies. | 1311 // initializers and constructor bodies. |
1312 List<FunctionElement> constructors = <FunctionElement>[functionElement]; | 1312 List<FunctionElement> constructors = <FunctionElement>[functionElement]; |
1313 buildInitializers(functionElement, constructors, fieldValues); | 1313 buildInitializers(functionElement, constructors, fieldValues); |
1314 | 1314 |
1315 // Call the JavaScript constructor with the fields as argument. | 1315 // Call the JavaScript constructor with the fields as argument. |
1316 List<HInstruction> constructorArguments = <HInstruction>[]; | 1316 List<HInstruction> constructorArguments = <HInstruction>[]; |
1317 classElement.forEachInstanceField( | 1317 classElement.forEachInstanceField( |
| 1318 (ClassElement enclosingClass, Element member) { |
| 1319 constructorArguments.add( |
| 1320 potentiallyCheckType(fieldValues[member], member)); |
| 1321 }, |
1318 includeBackendMembers: true, | 1322 includeBackendMembers: true, |
1319 includeSuperMembers: true, | 1323 includeSuperMembers: true); |
1320 f: (ClassElement enclosingClass, Element member) { | |
1321 constructorArguments.add( | |
1322 potentiallyCheckType(fieldValues[member], member)); | |
1323 }); | |
1324 | 1324 |
1325 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); | 1325 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); |
1326 add(newObject); | 1326 add(newObject); |
1327 | 1327 |
1328 // Create the runtime type information, if needed. | 1328 // Create the runtime type information, if needed. |
1329 InterfaceType type = classElement.computeType(compiler); | 1329 InterfaceType type = classElement.computeType(compiler); |
1330 List<HInstruction> inputs = <HInstruction>[]; | 1330 List<HInstruction> inputs = <HInstruction>[]; |
1331 if (compiler.world.needsRti(classElement)) { | 1331 if (compiler.world.needsRti(classElement)) { |
1332 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 1332 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
1333 inputs.add(localsHandler.directLocals[typeVariable.element]); | 1333 inputs.add(localsHandler.directLocals[typeVariable.element]); |
(...skipping 1676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3010 addDynamicSendArgumentsToList(node, inputs); | 3010 addDynamicSendArgumentsToList(node, inputs); |
3011 pushWithPosition(new HInvokeClosure(selector, inputs), node); | 3011 pushWithPosition(new HInvokeClosure(selector, inputs), node); |
3012 } | 3012 } |
3013 } | 3013 } |
3014 | 3014 |
3015 visitGetterSend(Send node) { | 3015 visitGetterSend(Send node) { |
3016 generateGetter(node, elements[node]); | 3016 generateGetter(node, elements[node]); |
3017 } | 3017 } |
3018 | 3018 |
3019 // TODO(antonm): migrate rest of SsaBuilder to internalError. | 3019 // TODO(antonm): migrate rest of SsaBuilder to internalError. |
3020 internalError(String reason, [Node node]) { | 3020 internalError(String reason, {Node node}) { |
3021 compiler.internalError(reason, node: node); | 3021 compiler.internalError(reason, node: node); |
3022 } | 3022 } |
3023 | 3023 |
3024 void generateError(Node node, String message, Element helper) { | 3024 void generateError(Node node, String message, Element helper) { |
3025 DartString messageObject = new DartString.literal(message); | 3025 DartString messageObject = new DartString.literal(message); |
3026 Constant messageConstant = | 3026 Constant messageConstant = |
3027 constantSystem.createString(messageObject, node); | 3027 constantSystem.createString(messageObject, node); |
3028 HInstruction errorMessage = graph.addConstant(messageConstant); | 3028 HInstruction errorMessage = graph.addConstant(messageConstant); |
3029 pushInvokeHelper1(helper, errorMessage); | 3029 pushInvokeHelper1(helper, errorMessage); |
3030 } | 3030 } |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3330 for (Link<Node> link = node.elements.nodes; | 3330 for (Link<Node> link = node.elements.nodes; |
3331 !link.isEmpty(); | 3331 !link.isEmpty(); |
3332 link = link.tail) { | 3332 link = link.tail) { |
3333 visit(link.head); | 3333 visit(link.head); |
3334 inputs.add(pop()); | 3334 inputs.add(pop()); |
3335 } | 3335 } |
3336 push(new HLiteralList(inputs)); | 3336 push(new HLiteralList(inputs)); |
3337 } | 3337 } |
3338 | 3338 |
3339 visitConditional(Conditional node) { | 3339 visitConditional(Conditional node) { |
3340 SsaBranchBuilder brancher = | 3340 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
3341 new SsaBranchBuilder(this, diagnosticNode: node); | |
3342 brancher.handleConditional(() => visit(node.condition), | 3341 brancher.handleConditional(() => visit(node.condition), |
3343 () => visit(node.thenExpression), | 3342 () => visit(node.thenExpression), |
3344 () => visit(node.elseExpression)); | 3343 () => visit(node.elseExpression)); |
3345 } | 3344 } |
3346 | 3345 |
3347 visitStringInterpolation(StringInterpolation node) { | 3346 visitStringInterpolation(StringInterpolation node) { |
3348 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); | 3347 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); |
3349 stringBuilder.visit(node); | 3348 stringBuilder.visit(node); |
3350 stack.add(stringBuilder.result); | 3349 stack.add(stringBuilder.result); |
3351 } | 3350 } |
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4301 | 4300 |
4302 conditionBranch.graph = | 4301 conditionBranch.graph = |
4303 new SubExpression(conditionBranch.block, conditionExitBlock); | 4302 new SubExpression(conditionBranch.block, conditionExitBlock); |
4304 } | 4303 } |
4305 | 4304 |
4306 /** | 4305 /** |
4307 * Returns true if the locals of the [fromBranch] may be reused. A [:true:] | 4306 * Returns true if the locals of the [fromBranch] may be reused. A [:true:] |
4308 * return value implies that [mayReuseFromLocals] was set to [:true:]. | 4307 * return value implies that [mayReuseFromLocals] was set to [:true:]. |
4309 */ | 4308 */ |
4310 bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch, | 4309 bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch, |
4311 [bool mayReuseFromLocals]) { | 4310 {bool mayReuseFromLocals}) { |
4312 LocalsHandler fromLocals = fromBranch.exitLocals; | 4311 LocalsHandler fromLocals = fromBranch.exitLocals; |
4313 if (toBranch.startLocals == null) { | 4312 if (toBranch.startLocals == null) { |
4314 if (mayReuseFromLocals) { | 4313 if (mayReuseFromLocals) { |
4315 toBranch.startLocals = fromLocals; | 4314 toBranch.startLocals = fromLocals; |
4316 return false; | 4315 return false; |
4317 } else { | 4316 } else { |
4318 toBranch.startLocals = new LocalsHandler.from(fromLocals); | 4317 toBranch.startLocals = new LocalsHandler.from(fromLocals); |
4319 return true; | 4318 return true; |
4320 } | 4319 } |
4321 } else { | 4320 } else { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4360 } | 4359 } |
4361 | 4360 |
4362 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); | 4361 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); |
4363 } | 4362 } |
4364 | 4363 |
4365 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { | 4364 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { |
4366 assert(visitElse != null); | 4365 assert(visitElse != null); |
4367 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); | 4366 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); |
4368 } | 4367 } |
4369 | 4368 |
4370 void handleLogicalAndOr(void left(), void right(), [bool isAnd]) { | 4369 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) { |
4371 // x && y is transformed into: | 4370 // x && y is transformed into: |
4372 // t0 = boolify(x); | 4371 // t0 = boolify(x); |
4373 // if (t0) { | 4372 // if (t0) { |
4374 // t1 = boolify(y); | 4373 // t1 = boolify(y); |
4375 // } | 4374 // } |
4376 // result = phi(t1, false); | 4375 // result = phi(t1, false); |
4377 // | 4376 // |
4378 // x || y is transformed into: | 4377 // x || y is transformed into: |
4379 // t0 = boolify(x); | 4378 // t0 = boolify(x); |
4380 // if (not(t0)) { | 4379 // if (not(t0)) { |
(...skipping 21 matching lines...) Expand all Loading... |
4402 HConstant notIsAnd = | 4401 HConstant notIsAnd = |
4403 builder.graph.addConstantBool(!isAnd, builder.constantSystem); | 4402 builder.graph.addConstantBool(!isAnd, builder.constantSystem); |
4404 HPhi result = new HPhi.manyInputs(null, | 4403 HPhi result = new HPhi.manyInputs(null, |
4405 <HInstruction>[boolifiedRight, notIsAnd]); | 4404 <HInstruction>[boolifiedRight, notIsAnd]); |
4406 builder.current.addPhi(result); | 4405 builder.current.addPhi(result); |
4407 builder.stack.add(result); | 4406 builder.stack.add(result); |
4408 } | 4407 } |
4409 | 4408 |
4410 void handleLogicalAndOrWithLeftNode(Node left, | 4409 void handleLogicalAndOrWithLeftNode(Node left, |
4411 void visitRight(), | 4410 void visitRight(), |
4412 [bool isAnd]) { | 4411 {bool isAnd}) { |
4413 // This method is similar to [handleLogicalAndOr] but optimizes the case | 4412 // This method is similar to [handleLogicalAndOr] but optimizes the case |
4414 // where left is a logical "and" or logical "or". | 4413 // where left is a logical "and" or logical "or". |
4415 // | 4414 // |
4416 // For example (x && y) && z is transformed into x && (y && z): | 4415 // For example (x && y) && z is transformed into x && (y && z): |
4417 // t0 = boolify(x); | 4416 // t0 = boolify(x); |
4418 // if (t0) { | 4417 // if (t0) { |
4419 // t1 = boolify(y); | 4418 // t1 = boolify(y); |
4420 // if (t1) { | 4419 // if (t1) { |
4421 // t2 = boolify(z); | 4420 // t2 = boolify(z); |
4422 // } | 4421 // } |
4423 // t3 = phi(t2, false); | 4422 // t3 = phi(t2, false); |
4424 // } | 4423 // } |
4425 // result = phi(t3, false); | 4424 // result = phi(t3, false); |
4426 | 4425 |
4427 Send send = left.asSend(); | 4426 Send send = left.asSend(); |
4428 if (send !== null && | 4427 if (send !== null && |
4429 (isAnd ? send.isLogicalAnd : send.isLogicalOr)) { | 4428 (isAnd ? send.isLogicalAnd : send.isLogicalOr)) { |
4430 Node newLeft = send.receiver; | 4429 Node newLeft = send.receiver; |
4431 Link<Node> link = send.argumentsNode.nodes; | 4430 Link<Node> link = send.argumentsNode.nodes; |
4432 assert(link.tail.isEmpty()); | 4431 assert(link.tail.isEmpty()); |
4433 Node middle = link.head; | 4432 Node middle = link.head; |
4434 handleLogicalAndOrWithLeftNode( | 4433 handleLogicalAndOrWithLeftNode( |
4435 newLeft, | 4434 newLeft, |
4436 () => handleLogicalAndOrWithLeftNode(middle, visitRight, isAnd), | 4435 () => handleLogicalAndOrWithLeftNode(middle, visitRight, |
| 4436 isAnd: isAnd), |
4437 isAnd: isAnd); | 4437 isAnd: isAnd); |
4438 } else { | 4438 } else { |
4439 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd); | 4439 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd); |
4440 } | 4440 } |
4441 } | 4441 } |
4442 | 4442 |
4443 void _handleDiamondBranch(void visitCondition(), | 4443 void _handleDiamondBranch(void visitCondition(), |
4444 void visitThen(), | 4444 void visitThen(), |
4445 void visitElse(), | 4445 void visitElse(), |
4446 bool isExpression) { | 4446 bool isExpression) { |
4447 SsaBranch conditionBranch = new SsaBranch(this); | 4447 SsaBranch conditionBranch = new SsaBranch(this); |
4448 SsaBranch thenBranch = new SsaBranch(this); | 4448 SsaBranch thenBranch = new SsaBranch(this); |
4449 SsaBranch elseBranch = new SsaBranch(this); | 4449 SsaBranch elseBranch = new SsaBranch(this); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4482 new HSubGraphBlockInformation(elseBranch.graph)); | 4482 new HSubGraphBlockInformation(elseBranch.graph)); |
4483 | 4483 |
4484 HBasicBlock conditionStartBlock = conditionBranch.block; | 4484 HBasicBlock conditionStartBlock = conditionBranch.block; |
4485 conditionStartBlock.setBlockFlow(info, joinBlock); | 4485 conditionStartBlock.setBlockFlow(info, joinBlock); |
4486 SubGraph conditionGraph = conditionBranch.graph; | 4486 SubGraph conditionGraph = conditionBranch.graph; |
4487 HIf branch = conditionGraph.end.last; | 4487 HIf branch = conditionGraph.end.last; |
4488 assert(branch is HIf); | 4488 assert(branch is HIf); |
4489 branch.blockInformation = conditionStartBlock.blockFlow; | 4489 branch.blockInformation = conditionStartBlock.blockFlow; |
4490 } | 4490 } |
4491 } | 4491 } |
OLD | NEW |