Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10452029: Fix bug when a variable is used in try/catch and accessed trough HFieldGet and HFieldSet: reference… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698