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