| 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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 // accessed through a closure-field. | 405 // accessed through a closure-field. |
| 406 // Calling [readLocal] makes sure we generate the correct code to get | 406 // Calling [readLocal] makes sure we generate the correct code to get |
| 407 // the box. | 407 // the box. |
| 408 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); | 408 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); |
| 409 HInstruction box = readLocal(redirect.enclosingElement); | 409 HInstruction box = readLocal(redirect.enclosingElement); |
| 410 HInstruction lookup = new HFieldGet(redirect.name, box); | 410 HInstruction lookup = new HFieldGet(redirect.name, box); |
| 411 builder.add(lookup); | 411 builder.add(lookup); |
| 412 return lookup; | 412 return lookup; |
| 413 } else { | 413 } else { |
| 414 assert(isUsedInTry(element)); | 414 assert(isUsedInTry(element)); |
| 415 HInstruction variable = new HFieldGet.fromActivation(element.name); | 415 HParameterValue parameter = getActivationParameter(element); |
| 416 HInstruction variable = new HFieldGet.fromActivation(parameter); |
| 416 builder.add(variable); | 417 builder.add(variable); |
| 417 return variable; | 418 return variable; |
| 418 } | 419 } |
| 419 } | 420 } |
| 420 | 421 |
| 421 HType cachedTypeOfThis; | 422 HType cachedTypeOfThis; |
| 422 | 423 |
| 423 HInstruction readThis() { | 424 HInstruction readThis() { |
| 424 HInstruction res = readLocal(closureData.thisElement); | 425 HInstruction res = readLocal(closureData.thisElement); |
| 425 if (res.guaranteedType === null) { | 426 if (res.guaranteedType === null) { |
| 426 if (cachedTypeOfThis === null) { | 427 if (cachedTypeOfThis === null) { |
| 427 assert(closureData.isClosure()); | 428 assert(closureData.isClosure()); |
| 428 Element element = closureData.thisElement; | 429 Element element = closureData.thisElement; |
| 429 ClassElement cls = element.enclosingElement.enclosingElement; | 430 ClassElement cls = element.enclosingElement.enclosingElement; |
| 430 Type type = cls.computeType(builder.compiler); | 431 Type type = cls.computeType(builder.compiler); |
| 431 cachedTypeOfThis = new HBoundedType(type); | 432 cachedTypeOfThis = new HBoundedType(type); |
| 432 } | 433 } |
| 433 res.guaranteedType = cachedTypeOfThis; | 434 res.guaranteedType = cachedTypeOfThis; |
| 434 } | 435 } |
| 435 return res; | 436 return res; |
| 436 } | 437 } |
| 437 | 438 |
| 439 HParameterValue getActivationParameter(Element element) { |
| 440 if (element.isParameter()) return directLocals[element]; |
| 441 |
| 442 return builder.activationVariables.putIfAbsent(element, () { |
| 443 HParameterValue parameter = new HParameterValue(element); |
| 444 builder.add(parameter); |
| 445 return parameter; |
| 446 }); |
| 447 } |
| 448 |
| 438 /** | 449 /** |
| 439 * Sets the [element] to [value]. If the element is boxed or stored in a | 450 * Sets the [element] to [value]. If the element is boxed or stored in a |
| 440 * closure then the method generates code to set the value. | 451 * closure then the method generates code to set the value. |
| 441 */ | 452 */ |
| 442 void updateLocal(Element element, HInstruction value) { | 453 void updateLocal(Element element, HInstruction value) { |
| 443 if (isAccessedDirectly(element)) { | 454 if (isAccessedDirectly(element)) { |
| 444 directLocals[element] = value; | 455 directLocals[element] = value; |
| 445 } else if (isStoredInClosureField(element)) { | 456 } else if (isStoredInClosureField(element)) { |
| 446 Element redirect = redirectionMapping[element]; | 457 Element redirect = redirectionMapping[element]; |
| 447 // We must not use the [LocalsHandler.readThis()] since that could | 458 // We must not use the [LocalsHandler.readThis()] since that could |
| 448 // point to a captured this which would be stored in a closure-field | 459 // point to a captured this which would be stored in a closure-field |
| 449 // itself. | 460 // itself. |
| 450 HInstruction receiver = new HThis(); | 461 HInstruction receiver = new HThis(); |
| 451 builder.add(receiver); | 462 builder.add(receiver); |
| 452 builder.add(new HFieldSet(redirect.name, receiver, value)); | 463 builder.add(new HFieldSet(redirect.name, receiver, value)); |
| 453 } else if (isBoxed(element)) { | 464 } else if (isBoxed(element)) { |
| 454 Element redirect = redirectionMapping[element]; | 465 Element redirect = redirectionMapping[element]; |
| 455 // The box itself could be captured, or be local. A local variable that | 466 // The box itself could be captured, or be local. A local variable that |
| 456 // is captured will be boxed, but the box itself will be a local. | 467 // is captured will be boxed, but the box itself will be a local. |
| 457 // Inside the closure the box is stored in a closure-field and cannot | 468 // Inside the closure the box is stored in a closure-field and cannot |
| 458 // be accessed directly. | 469 // be accessed directly. |
| 459 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); | 470 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); |
| 460 HInstruction box = readLocal(redirect.enclosingElement); | 471 HInstruction box = readLocal(redirect.enclosingElement); |
| 461 builder.add(new HFieldSet(redirect.name, box, value)); | 472 builder.add(new HFieldSet(redirect.name, box, value)); |
| 462 } else { | 473 } else { |
| 463 assert(isUsedInTry(element)); | 474 assert(isUsedInTry(element)); |
| 464 builder.add(new HFieldSet.fromActivation(element.name, value)); | 475 HParameterValue parameter = getActivationParameter(element); |
| 476 builder.add(new HFieldSet.fromActivation(parameter, value)); |
| 465 } | 477 } |
| 466 } | 478 } |
| 467 | 479 |
| 468 /** | 480 /** |
| 469 * This function must be called before visiting any children of the loop. In | 481 * This function must be called before visiting any children of the loop. In |
| 470 * particular it needs to be called before executing the initializers. | 482 * particular it needs to be called before executing the initializers. |
| 471 * | 483 * |
| 472 * The [LocalsHandler] will make the boxes and updates at the right moment. | 484 * The [LocalsHandler] will make the boxes and updates at the right moment. |
| 473 * The builder just needs to call [enterLoopBody] and [enterLoopUpdates] (for | 485 * The builder just needs to call [enterLoopBody] and [enterLoopUpdates] (for |
| 474 * [For] loops) at the correct places. For phi-handling [beginLoopHeader] and | 486 * [For] loops) at the correct places. For phi-handling [beginLoopHeader] and |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 TreeElements elements; | 784 TreeElements elements; |
| 773 final Interceptors interceptors; | 785 final Interceptors interceptors; |
| 774 final WorkItem work; | 786 final WorkItem work; |
| 775 bool methodInterceptionEnabled; | 787 bool methodInterceptionEnabled; |
| 776 HGraph graph; | 788 HGraph graph; |
| 777 LocalsHandler localsHandler; | 789 LocalsHandler localsHandler; |
| 778 HInstruction rethrowableException; | 790 HInstruction rethrowableException; |
| 779 | 791 |
| 780 Map<TargetElement, JumpHandler> jumpTargets; | 792 Map<TargetElement, JumpHandler> jumpTargets; |
| 781 | 793 |
| 794 /** |
| 795 * Variables stored in the current activation. These variables are |
| 796 * being updated in try/catch blocks, and should be |
| 797 * accessed indirectly through HFieldGet and HFieldSet. |
| 798 */ |
| 799 Map<Element, HParameterValue> activationVariables; |
| 800 |
| 782 // We build the Ssa graph by simulating a stack machine. | 801 // We build the Ssa graph by simulating a stack machine. |
| 783 List<HInstruction> stack; | 802 List<HInstruction> stack; |
| 784 | 803 |
| 785 // The current block to add instructions to. Might be null, if we are | 804 // The current block to add instructions to. Might be null, if we are |
| 786 // visiting dead code. | 805 // visiting dead code. |
| 787 HBasicBlock current; | 806 HBasicBlock current; |
| 788 // The most recently opened block. Has the same value as [current] while | 807 // The most recently opened block. Has the same value as [current] while |
| 789 // the block is open, but unlike [current], it isn't cleared when the current | 808 // the block is open, but unlike [current], it isn't cleared when the current |
| 790 // block is closed. | 809 // block is closed. |
| 791 HBasicBlock lastOpenedBlock; | 810 HBasicBlock lastOpenedBlock; |
| 792 | 811 |
| 793 LibraryElement get currentLibrary() => work.element.getLibrary(); | 812 LibraryElement get currentLibrary() => work.element.getLibrary(); |
| 794 Compiler get compiler() => builder.compiler; | 813 Compiler get compiler() => builder.compiler; |
| 795 CodeEmitterTask get emitter() => builder.emitter; | 814 CodeEmitterTask get emitter() => builder.emitter; |
| 796 | 815 |
| 797 SsaBuilder(SsaBuilderTask builder, WorkItem work) | 816 SsaBuilder(SsaBuilderTask builder, WorkItem work) |
| 798 : this.builder = builder, | 817 : this.builder = builder, |
| 799 this.work = work, | 818 this.work = work, |
| 800 interceptors = builder.interceptors, | 819 interceptors = builder.interceptors, |
| 801 methodInterceptionEnabled = true, | 820 methodInterceptionEnabled = true, |
| 802 elements = work.resolutionTree, | 821 elements = work.resolutionTree, |
| 803 graph = new HGraph(), | 822 graph = new HGraph(), |
| 804 stack = new List<HInstruction>(), | 823 stack = new List<HInstruction>(), |
| 824 activationVariables = new Map<Element, HParameterValue>(), |
| 805 jumpTargets = new Map<TargetElement, JumpHandler>() { | 825 jumpTargets = new Map<TargetElement, JumpHandler>() { |
| 806 localsHandler = new LocalsHandler(this); | 826 localsHandler = new LocalsHandler(this); |
| 807 } | 827 } |
| 808 | 828 |
| 809 void disableMethodInterception() { | 829 void disableMethodInterception() { |
| 810 assert(methodInterceptionEnabled); | 830 assert(methodInterceptionEnabled); |
| 811 methodInterceptionEnabled = false; | 831 methodInterceptionEnabled = false; |
| 812 } | 832 } |
| 813 | 833 |
| 814 void enableMethodInterception() { | 834 void enableMethodInterception() { |
| (...skipping 2551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3366 <HInstruction>[target, input], | 3386 <HInstruction>[target, input], |
| 3367 HType.STRING)); | 3387 HType.STRING)); |
| 3368 return builder.pop(); | 3388 return builder.pop(); |
| 3369 } | 3389 } |
| 3370 | 3390 |
| 3371 HInstruction result(Node node) { | 3391 HInstruction result(Node node) { |
| 3372 flushLiterals(node); | 3392 flushLiterals(node); |
| 3373 return prefix; | 3393 return prefix; |
| 3374 } | 3394 } |
| 3375 } | 3395 } |
| OLD | NEW |