| 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 |