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

Side by Side Diff: pkg/compiler/lib/src/ssa/locals_handler.dart

Issue 2936693002: Reapply "Separate out loop closure information." (Closed)
Patch Set: call with ast.node instead of ir.Node until we update that path. Created 3 years, 6 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
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 import '../closure.dart'; 5 import '../closure.dart';
6 import '../common.dart'; 6 import '../common.dart';
7 import '../elements/elements.dart'; 7 import '../elements/elements.dart';
8 import '../elements/entities.dart'; 8 import '../elements/entities.dart';
9 import '../elements/types.dart'; 9 import '../elements/types.dart';
10 import '../io/source_information.dart'; 10 import '../io/source_information.dart';
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 } 129 }
130 130
131 HInstruction createBox() { 131 HInstruction createBox() {
132 HInstruction box = new HCreateBox(commonMasks.nonNullType); 132 HInstruction box = new HCreateBox(commonMasks.nonNullType);
133 builder.add(box); 133 builder.add(box);
134 return box; 134 return box;
135 } 135 }
136 136
137 /// If the scope (function or loop) [node] has captured variables then this 137 /// If the scope (function or loop) [node] has captured variables then this
138 /// method creates a box and sets up the redirections. 138 /// method creates a box and sets up the redirections.
139 void enterScope(ClosureScope scopeData, 139 void enterScope(ClosureAnalysisInfo closureInfo,
140 {bool forGenerativeConstructorBody: false}) { 140 {bool forGenerativeConstructorBody: false}) {
141 // See if any variable in the top-scope of the function is captured. If yes 141 // See if any variable in the top-scope of the function is captured. If yes
142 // we need to create a box-object. 142 // we need to create a box-object.
143 if (scopeData == null) return; 143 if (!closureInfo.requiresContextBox()) return;
144 HInstruction box; 144 HInstruction box;
145 // The scope has captured variables. 145 // The scope has captured variables.
146 if (forGenerativeConstructorBody) { 146 if (forGenerativeConstructorBody) {
147 // The box is passed as a parameter to a generative 147 // The box is passed as a parameter to a generative
148 // constructor body. 148 // constructor body.
149 box = builder.addParameter(scopeData.boxElement, commonMasks.nonNullType); 149 box = builder.addParameter(closureInfo.context, commonMasks.nonNullType);
150 } else { 150 } else {
151 box = createBox(); 151 box = createBox();
152 } 152 }
153 // Add the box to the known locals. 153 // Add the box to the known locals.
154 directLocals[scopeData.boxElement] = box; 154 directLocals[closureInfo.context] = box;
155 // Make sure that accesses to the boxed locals go into the box. We also 155 // Make sure that accesses to the boxed locals go into the box. We also
156 // need to make sure that parameters are copied into the box if necessary. 156 // need to make sure that parameters are copied into the box if necessary.
157 scopeData.forEachCapturedVariable( 157 closureInfo.forEachCapturedVariable(
158 (LocalVariableElement from, BoxFieldElement to) { 158 (LocalVariableElement from, BoxFieldElement to) {
159 // The [from] can only be a parameter for function-scopes and not 159 // The [from] can only be a parameter for function-scopes and not
160 // loop scopes. 160 // loop scopes.
161 if (from.isRegularParameter && !forGenerativeConstructorBody) { 161 if (from.isRegularParameter && !forGenerativeConstructorBody) {
162 // Now that the redirection is set up, the update to the local will 162 // Now that the redirection is set up, the update to the local will
163 // write the parameter value into the box. 163 // write the parameter value into the box.
164 // Store the captured parameter in the box. Get the current value 164 // Store the captured parameter in the box. Get the current value
165 // before we put the redirection in place. 165 // before we put the redirection in place.
166 // We don't need to update the local for a generative 166 // We don't need to update the local for a generative
167 // constructor body, because it receives a box that already 167 // constructor body, because it receives a box that already
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 // The parameter will be a field in the box passed as the 209 // The parameter will be a field in the box passed as the
210 // last parameter. So no need to have it. 210 // last parameter. So no need to have it.
211 return; 211 return;
212 } 212 }
213 } 213 }
214 HInstruction parameter = builder.addParameter(local, typeMask); 214 HInstruction parameter = builder.addParameter(local, typeMask);
215 builder.parameters[local] = parameter; 215 builder.parameters[local] = parameter;
216 directLocals[local] = parameter; 216 directLocals[local] = parameter;
217 }); 217 });
218 218
219 enterScope(scopeData, 219 if (scopeData != null) {
220 forGenerativeConstructorBody: isGenerativeConstructorBody); 220 // TODO(efortuna): Remove the above if wrapper (always execute this step)
221 // when the switch away from ClosureClassMap is complete (prior behavior
222 // in enterScope it was acceptable to pass in a null scopeData, but no
223 // longer).
224 enterScope(scopeData,
225 forGenerativeConstructorBody: isGenerativeConstructorBody);
226 }
221 227
222 // If the freeVariableMapping is not empty, then this function was a 228 // If the freeVariableMapping is not empty, then this function was a
223 // nested closure that captures variables. Redirect the captured 229 // nested closure that captures variables. Redirect the captured
224 // variables to fields in the closure. 230 // variables to fields in the closure.
225 closureData.forEachFreeVariable((Local from, FieldEntity to) { 231 closureData.forEachFreeVariable((Local from, FieldEntity to) {
226 redirectElement(from, to); 232 redirectElement(from, to);
227 }); 233 });
228 if (closureData.isClosure) { 234 if (closureData.isClosure) {
229 // Inside closure redirect references to itself to [:this:]. 235 // Inside closure redirect references to itself to [:this:].
230 HThis thisInstruction = 236 HThis thisInstruction =
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 /// We solve this by emitting the following code (only for [ast.For] loops): 472 /// We solve this by emitting the following code (only for [ast.For] loops):
467 /// <Create box> <== move the first box creation outside the loop. 473 /// <Create box> <== move the first box creation outside the loop.
468 /// <initializer>; 474 /// <initializer>;
469 /// loop-entry: 475 /// loop-entry:
470 /// if (!<condition>) goto loop-exit; 476 /// if (!<condition>) goto loop-exit;
471 /// <body> 477 /// <body>
472 /// <update box> // create a new box and copy the captured loop-variables. 478 /// <update box> // create a new box and copy the captured loop-variables.
473 /// <updates> 479 /// <updates>
474 /// goto loop-entry; 480 /// goto loop-entry;
475 /// loop-exit: 481 /// loop-exit:
476 void startLoop(ast.Node node) { 482 void startLoop(LoopClosureRepresentationInfo loopInfo) {
477 ClosureScope scopeData = closureData.capturingScopes[node]; 483 if (loopInfo.hasBoxedVariables) {
478 if (scopeData == null) return;
479 if (scopeData.hasBoxedLoopVariables()) {
480 // If there are boxed loop variables then we set up the box and 484 // If there are boxed loop variables then we set up the box and
481 // redirections already now. This way the initializer can write its 485 // redirections already now. This way the initializer can write its
482 // values into the box. 486 // values into the box.
483 // For other loops the box will be created when entering the body. 487 // For other loops the box will be created when entering the body.
484 enterScope(scopeData); 488 enterScope(loopInfo);
485 } 489 }
486 } 490 }
487 491
488 /// Create phis at the loop entry for local variables (ready for the values 492 /// Create phis at the loop entry for local variables (ready for the values
489 /// from the back edge). Populate the phis with the current values. 493 /// from the back edge). Populate the phis with the current values.
490 void beginLoopHeader(HBasicBlock loopEntry) { 494 void beginLoopHeader(HBasicBlock loopEntry) {
491 // Create a copy because we modify the map while iterating over it. 495 // Create a copy because we modify the map while iterating over it.
492 Map<Local, HInstruction> savedDirectLocals = 496 Map<Local, HInstruction> savedDirectLocals =
493 new Map<Local, HInstruction>.from(directLocals); 497 new Map<Local, HInstruction>.from(directLocals);
494 498
495 // Create phis for all elements in the definitions environment. 499 // Create phis for all elements in the definitions environment.
496 savedDirectLocals.forEach((Local local, HInstruction instruction) { 500 savedDirectLocals.forEach((Local local, HInstruction instruction) {
497 if (isAccessedDirectly(local)) { 501 if (isAccessedDirectly(local)) {
498 // We know 'this' cannot be modified. 502 // We know 'this' cannot be modified.
499 if (local != closureData.thisLocal) { 503 if (local != closureData.thisLocal) {
500 HPhi phi = 504 HPhi phi =
501 new HPhi.singleInput(local, instruction, commonMasks.dynamicType); 505 new HPhi.singleInput(local, instruction, commonMasks.dynamicType);
502 loopEntry.addPhi(phi); 506 loopEntry.addPhi(phi);
503 directLocals[local] = phi; 507 directLocals[local] = phi;
504 } else { 508 } else {
505 directLocals[local] = instruction; 509 directLocals[local] = instruction;
506 } 510 }
507 } 511 }
508 }); 512 });
509 } 513 }
510 514
511 void enterLoopBody(ast.Node node) { 515 void enterLoopBody(LoopClosureRepresentationInfo loopInfo) {
512 ClosureScope scopeData = closureData.capturingScopes[node];
513 if (scopeData == null) return;
514 // If there are no declared boxed loop variables then we did not create the 516 // If there are no declared boxed loop variables then we did not create the
515 // box before the initializer and we have to create the box now. 517 // box before the initializer and we have to create the box now.
516 if (!scopeData.hasBoxedLoopVariables()) { 518 if (!loopInfo.hasBoxedVariables) {
517 enterScope(scopeData); 519 enterScope(loopInfo);
518 } 520 }
519 } 521 }
520 522
521 void enterLoopUpdates(ast.Node node) { 523 void enterLoopUpdates(LoopClosureRepresentationInfo loopInfo) {
522 // If there are declared boxed loop variables then the updates might have 524 // If there are declared boxed loop variables then the updates might have
523 // access to the box and we must switch to a new box before executing the 525 // access to the box and we must switch to a new box before executing the
524 // updates. 526 // updates.
525 // In all other cases a new box will be created when entering the body of 527 // In all other cases a new box will be created when entering the body of
526 // the next iteration. 528 // the next iteration.
527 ClosureScope scopeData = closureData.capturingScopes[node]; 529 if (loopInfo.hasBoxedVariables) {
528 if (scopeData == null) return; 530 updateCaptureBox(loopInfo.context, loopInfo.boxedVariables);
529 if (scopeData.hasBoxedLoopVariables()) {
530 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables);
531 } 531 }
532 } 532 }
533 533
534 /// Goes through the phis created in beginLoopHeader entry and adds the 534 /// Goes through the phis created in beginLoopHeader entry and adds the
535 /// input from the back edge (from the current value of directLocals) to them. 535 /// input from the back edge (from the current value of directLocals) to them.
536 void endLoop(HBasicBlock loopEntry) { 536 void endLoop(HBasicBlock loopEntry) {
537 // If the loop has an aborting body, we don't update the loop 537 // If the loop has an aborting body, we don't update the loop
538 // phis. 538 // phis.
539 if (loopEntry.predecessors.length == 1) return; 539 if (loopEntry.predecessors.length == 1) return;
540 loopEntry.forEachPhi((HPhi phi) { 540 loopEntry.forEachPhi((HPhi phi) {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 final MemberEntity memberContext; 676 final MemberEntity memberContext;
677 677
678 // Avoid slow Object.hashCode. 678 // Avoid slow Object.hashCode.
679 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); 679 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30);
680 static int _nextHashCode = 0; 680 static int _nextHashCode = 0;
681 681
682 SyntheticLocal(this.name, this.executableContext, this.memberContext); 682 SyntheticLocal(this.name, this.executableContext, this.memberContext);
683 683
684 toString() => 'SyntheticLocal($name)'; 684 toString() => 'SyntheticLocal($name)';
685 } 685 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder_kernel.dart ('k') | pkg/compiler/lib/src/ssa/loop_handler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698