Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library tree_ir_builder; | 5 library tree_ir_builder; |
| 6 | 6 |
| 7 import '../dart2jslib.dart' as dart2js; | 7 import '../dart2jslib.dart' as dart2js; |
| 8 import '../dart_types.dart'; | 8 import '../dart_types.dart'; |
| 9 import '../elements/elements.dart'; | 9 import '../elements/elements.dart'; |
| 10 import '../cps_ir/cps_ir_nodes.dart' as cps_ir; | 10 import '../cps_ir/cps_ir_nodes.dart' as cps_ir; |
| 11 import 'tree_ir_nodes.dart'; | 11 import 'tree_ir_nodes.dart'; |
| 12 import '../js_backend/js_backend.dart'; | |
| 12 | 13 |
| 13 /** | 14 /** |
| 14 * Builder translates from CPS-based IR to direct-style Tree. | 15 * Builder translates from CPS-based IR to direct-style Tree. |
| 15 * | 16 * |
| 16 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced | 17 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced |
| 17 * non-exit continuation `Cont(v, body)` is translated into a direct-style call | 18 * non-exit continuation `Cont(v, body)` is translated into a direct-style call |
| 18 * whose value is bound in the continuation body: | 19 * whose value is bound in the continuation body: |
| 19 * | 20 * |
| 20 * `LetVal(v, Invoke(fun, args), body)` | 21 * `LetVal(v, Invoke(fun, args), body)` |
| 21 * | 22 * |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 phiTempVar = new Variable(node.element, null); | 156 phiTempVar = new Variable(node.element, null); |
| 156 body = visit(node.body); | 157 body = visit(node.body); |
| 157 } | 158 } |
| 158 | 159 |
| 159 return new FunctionDefinition(node.element, parameters, | 160 return new FunctionDefinition(node.element, parameters, |
| 160 body, node.localConstants, node.defaultParameterValues); | 161 body, node.localConstants, node.defaultParameterValues); |
| 161 } | 162 } |
| 162 | 163 |
| 163 List<Expression> translateArguments(List<cps_ir.Reference> args) { | 164 List<Expression> translateArguments(List<cps_ir.Reference> args) { |
| 164 return new List<Expression>.generate(args.length, | 165 return new List<Expression>.generate(args.length, |
| 165 (int index) => getVariableReference(args[index])); | 166 (int index) => getVariableReference(args[index]), |
| 167 growable: false); | |
| 166 } | 168 } |
| 167 | 169 |
| 168 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) { | 170 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) { |
| 169 return new List<Variable>.generate(args.length, | 171 return new List<Variable>.generate(args.length, |
| 170 (int index) => getVariableReference(args[index])); | 172 (int index) => getVariableReference(args[index])); |
| 171 } | 173 } |
| 172 | 174 |
| 173 Statement buildContinuationAssignment( | 175 Statement buildContinuationAssignment( |
| 174 cps_ir.Parameter parameter, | 176 cps_ir.Parameter parameter, |
| 175 Expression argument, | 177 Expression argument, |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 311 Statement visitInvokeStatic(cps_ir.InvokeStatic node) { | 313 Statement visitInvokeStatic(cps_ir.InvokeStatic node) { |
| 312 // Calls are translated to direct style. | 314 // Calls are translated to direct style. |
| 313 List<Expression> arguments = translateArguments(node.arguments); | 315 List<Expression> arguments = translateArguments(node.arguments); |
| 314 Expression invoke = new InvokeStatic(node.target, node.selector, arguments); | 316 Expression invoke = new InvokeStatic(node.target, node.selector, arguments); |
| 315 return continueWithExpression(node.continuation, invoke); | 317 return continueWithExpression(node.continuation, invoke); |
| 316 } | 318 } |
| 317 | 319 |
| 318 Statement visitInvokeMethod(cps_ir.InvokeMethod node) { | 320 Statement visitInvokeMethod(cps_ir.InvokeMethod node) { |
| 319 Expression receiver = getVariableReference(node.receiver); | 321 Expression receiver = getVariableReference(node.receiver); |
| 320 List<Expression> arguments = translateArguments(node.arguments); | 322 List<Expression> arguments = translateArguments(node.arguments); |
| 323 if (node.isIntercepted) { | |
| 324 // When this call is intercepted, the receiver is not actually an object, | |
| 325 // but a prototype that implements the intercepted data types operations. | |
| 326 // The value must be given as the first argument to the interceptor. | |
| 327 cps_ir.Interceptor interceptor = node.receiver.definition; | |
| 328 Expression target = getVariableReference(interceptor.input); | |
| 329 arguments = new List<Expression>.generate(arguments.length + 1, | |
| 330 (int index) => index == 0 ? target : arguments [index - 1], | |
| 331 growable: false); | |
| 332 } | |
| 321 Expression invoke = new InvokeMethod(receiver, node.selector, arguments); | 333 Expression invoke = new InvokeMethod(receiver, node.selector, arguments); |
| 322 return continueWithExpression(node.continuation, invoke); | 334 return continueWithExpression(node.continuation, invoke); |
| 323 } | 335 } |
| 324 | 336 |
| 325 Statement visitInvokeSuperMethod(cps_ir.InvokeSuperMethod node) { | 337 Statement visitInvokeSuperMethod(cps_ir.InvokeSuperMethod node) { |
| 326 List<Expression> arguments = translateArguments(node.arguments); | 338 List<Expression> arguments = translateArguments(node.arguments); |
| 327 Expression invoke = new InvokeSuperMethod(node.selector, arguments); | 339 Expression invoke = new InvokeSuperMethod(node.selector, arguments); |
| 328 return continueWithExpression(node.continuation, invoke); | 340 return continueWithExpression(node.continuation, invoke); |
| 329 } | 341 } |
| 330 | 342 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 473 // The successor will be filled in by visitLetPrim. | 485 // The successor will be filled in by visitLetPrim. |
| 474 return new FunctionDeclaration(getVariable(node), def, null); | 486 return new FunctionDeclaration(getVariable(node), def, null); |
| 475 } else { | 487 } else { |
| 476 return new FunctionExpression(def); | 488 return new FunctionExpression(def); |
| 477 } | 489 } |
| 478 } | 490 } |
| 479 | 491 |
| 480 Expression visitParameter(cps_ir.Parameter node) { | 492 Expression visitParameter(cps_ir.Parameter node) { |
| 481 // Continuation parameters are not visited (continuations themselves are | 493 // Continuation parameters are not visited (continuations themselves are |
| 482 // not visited yet). | 494 // not visited yet). |
| 483 compiler.internalError(compiler.currentElement, 'Unexpected IR node.'); | 495 compiler.internalError(compiler.currentElement, |
| 496 'Unexpected IR node: $node'); | |
| 484 return null; | 497 return null; |
| 485 } | 498 } |
| 486 | 499 |
| 487 Expression visitContinuation(cps_ir.Continuation node) { | 500 Expression visitContinuation(cps_ir.Continuation node) { |
| 488 // Until continuations with multiple uses are supported, they are not | 501 // Until continuations with multiple uses are supported, they are not |
| 489 // visited. | 502 // visited. |
| 490 compiler.internalError(compiler.currentElement, 'Unexpected IR node.'); | 503 compiler.internalError(compiler.currentElement, |
| 504 'Unexpected IR node: $node.'); | |
| 491 return null; | 505 return null; |
| 492 } | 506 } |
| 493 | 507 |
| 494 Expression visitIsTrue(cps_ir.IsTrue node) { | 508 Expression visitIsTrue(cps_ir.IsTrue node) { |
| 495 return getVariableReference(node.value); | 509 return getVariableReference(node.value); |
| 496 } | 510 } |
| 497 | 511 |
| 498 dart2js.Selector get identicalSelector { | 512 dart2js.Selector get identicalSelector { |
| 499 return new dart2js.Selector.call('identical', null, 2); | 513 return new dart2js.Selector.call('identical', null, 2); |
| 500 } | 514 } |
| 501 | 515 |
| 502 Expression visitIdentical(cps_ir.Identical node) { | 516 Expression visitIdentical(cps_ir.Identical node) { |
| 503 return new InvokeStatic( | 517 return new InvokeStatic( |
| 504 compiler.identicalFunction, | 518 compiler.identicalFunction, |
| 505 identicalSelector, | 519 identicalSelector, |
| 506 <Expression>[getVariableReference(node.left), | 520 <Expression>[getVariableReference(node.left), |
| 507 getVariableReference(node.right)]); | 521 getVariableReference(node.right)]); |
| 508 } | 522 } |
| 523 | |
| 524 Expression visitInterceptor(cps_ir.Interceptor node) { | |
| 525 JavaScriptBackend backend = compiler.backend; | |
| 526 Element getInterceptor = backend.getInterceptorMethod; | |
|
sigurdm
2014/12/16 11:44:56
I think we should go via Glue here.
karlklose
2014/12/16 12:04:03
Done.
| |
| 527 backend.registerUseInterceptor(compiler.enqueuer.codegen); | |
| 528 return new InvokeStatic( | |
| 529 getInterceptor, | |
| 530 new dart2js.Selector.fromElement(getInterceptor), | |
| 531 <Expression>[getVariableReference(node.input)]); | |
| 532 } | |
| 509 } | 533 } |
| 510 | 534 |
| OLD | NEW |