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

Side by Side Diff: frog/leg/ssa/builder.dart

Issue 9359011: Capture this. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 10 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 | frog/leg/ssa/closure.dart » ('j') | frog/leg/ssa/closure.dart » ('J')
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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 159
160 /** 160 /**
161 * Keeps track of locals (including parameters and phis) when building. The 161 * Keeps track of locals (including parameters and phis) when building. The
162 * 'this' reference is treated as parameter and hence handled by this class, 162 * 'this' reference is treated as parameter and hence handled by this class,
163 * too. 163 * too.
164 */ 164 */
165 class LocalsHandler { 165 class LocalsHandler {
166 // The values of locals that can be directly accessed (without redirections 166 // The values of locals that can be directly accessed (without redirections
167 // to boxes or closure-fields). 167 // to boxes or closure-fields).
168 Map<Element, HInstruction> directLocals; 168 Map<Element, HInstruction> directLocals;
169 HInstruction thisDefinition;
170 Map<Element, Element> redirectionMapping; 169 Map<Element, Element> redirectionMapping;
171 SsaBuilder builder; 170 SsaBuilder builder;
172 ClosureData closureData; 171 ClosureData closureData;
173 172
174 LocalsHandler(this.builder) 173 LocalsHandler(this.builder)
175 : directLocals = new Map<Element, HInstruction>(), 174 : directLocals = new Map<Element, HInstruction>(),
176 redirectionMapping = new Map<Element, Element>(); 175 redirectionMapping = new Map<Element, Element>();
177 176
178 /** 177 /**
179 * Creates a new [LocalsHandler] based on [other]. We only need to 178 * Creates a new [LocalsHandler] based on [other]. We only need to
180 * copy the [directLocals], since the other fields can be shared 179 * copy the [directLocals], since the other fields can be shared
181 * throughout the AST visit. 180 * throughout the AST visit.
182 */ 181 */
183 LocalsHandler.from(LocalsHandler other) 182 LocalsHandler.from(LocalsHandler other)
184 : directLocals = new Map<Element, HInstruction>.from(other.directLocals), 183 : directLocals = new Map<Element, HInstruction>.from(other.directLocals),
185 redirectionMapping = other.redirectionMapping, 184 redirectionMapping = other.redirectionMapping,
186 builder = other.builder, 185 builder = other.builder,
187 thisDefinition = other.thisDefinition,
188 closureData = other.closureData; 186 closureData = other.closureData;
189 187
190 void startFunction(FunctionElement function, 188 void startFunction(FunctionElement function,
191 FunctionExpression node) { 189 FunctionExpression node) {
192 190
193 ClosureTranslator translator = 191 ClosureTranslator translator =
194 new ClosureTranslator(builder.compiler, builder.elements); 192 new ClosureTranslator(builder.compiler, builder.elements);
195 closureData = translator.translate(node); 193 closureData = translator.translate(node);
196 194
197 if (function.isInstanceMember()) { 195 if (function.isInstanceMember()) {
198 thisDefinition = new HThis(); 196 HInstruction thisInstruction = new HThis();
199 builder.add(thisDefinition); 197 updateLocal(closureData.thisElement, thisInstruction);
198 builder.add(thisInstruction);
200 } 199 }
201 200
202 FunctionParameters params = function.computeParameters(builder.compiler); 201 FunctionParameters params = function.computeParameters(builder.compiler);
203 params.forEachParameter((Element element) { 202 params.forEachParameter((Element element) {
204 HParameterValue parameter = new HParameterValue(element); 203 HParameterValue parameter = new HParameterValue(element);
205 builder.add(parameter); 204 builder.add(parameter);
206 // Note that for constructors [element] could be a field-element which we 205 // Note that for constructors [element] could be a field-element which we
207 // treat as if it was a local. 206 // treat as if it was a local.
208 directLocals[element] = parameter; 207 directLocals[element] = parameter;
209 }); 208 });
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 */ 298 */
300 HInstruction readLocal(Element element) { 299 HInstruction readLocal(Element element) {
301 if (isAccessedDirectly(element)) { 300 if (isAccessedDirectly(element)) {
302 if (directLocals[element] == null) { 301 if (directLocals[element] == null) {
303 builder.compiler.internalError( 302 builder.compiler.internalError(
304 "Could not find value", node: element.parseNode(builder.compiler)); 303 "Could not find value", node: element.parseNode(builder.compiler));
305 } 304 }
306 return directLocals[element]; 305 return directLocals[element];
307 } else if (isStoredInClosureField(element)) { 306 } else if (isStoredInClosureField(element)) {
308 Element redirect = redirectionMapping[element]; 307 Element redirect = redirectionMapping[element];
309 // We must not use the [LocalsHandler.thisDefinition] since that could 308 // We must not use the [LocalsHandler.readThis()] since that could
310 // point to a captured this which would be stored in a closure-field 309 // point to a captured this which would be stored in a closure-field
311 // itself. 310 // itself.
312 HInstruction receiver = new HThis(); 311 HInstruction receiver = new HThis();
313 builder.add(receiver); 312 builder.add(receiver);
314 HInstruction fieldGet = new HFieldGet(redirect, receiver); 313 HInstruction fieldGet = new HFieldGet(redirect, receiver);
315 builder.add(fieldGet); 314 builder.add(fieldGet);
316 return fieldGet; 315 return fieldGet;
317 } else if (isBoxed(element)) { 316 } else if (isBoxed(element)) {
318 Element redirect = redirectionMapping[element]; 317 Element redirect = redirectionMapping[element];
319 // In the function that declares the captured variable the box is 318 // In the function that declares the captured variable the box is
320 // accessed as direct local. Inside the nested closure the box is 319 // accessed as direct local. Inside the nested closure the box is
321 // accessed through a closure-field. 320 // accessed through a closure-field.
322 // Calling [readLocal] makes sure we generate the correct code to get 321 // Calling [readLocal] makes sure we generate the correct code to get
323 // the box. 322 // the box.
324 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); 323 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE);
325 HInstruction box = readLocal(redirect.enclosingElement); 324 HInstruction box = readLocal(redirect.enclosingElement);
326 HInstruction lookup = new HFieldGet(redirect, box); 325 HInstruction lookup = new HFieldGet(redirect, box);
327 builder.add(lookup); 326 builder.add(lookup);
328 return lookup; 327 return lookup;
329 } else { 328 } else {
330 assert(isUsedInTry(element)); 329 assert(isUsedInTry(element));
331 HInstruction variable = new HFieldGet.fromActivation(element); 330 HInstruction variable = new HFieldGet.fromActivation(element);
332 builder.add(variable); 331 builder.add(variable);
333 return variable; 332 return variable;
334 } 333 }
335 } 334 }
336 335
336 HInstruction readThis() {
337 return readLocal(closureData.thisElement);
338 }
339
337 /** 340 /**
338 * Sets the [element] to [value]. If the element is boxed or stored in a 341 * Sets the [element] to [value]. If the element is boxed or stored in a
339 * closure then the method generates code to set the value. 342 * closure then the method generates code to set the value.
340 */ 343 */
341 void updateLocal(Element element, HInstruction value) { 344 void updateLocal(Element element, HInstruction value) {
342 // TODO(floitsch): replace the following if with an assert. 345 // TODO(floitsch): replace the following if with an assert.
343 if (element is !VariableElement) { 346 if (element is !VariableElement) {
344 builder.compiler.internalError("expected a variable", 347 builder.compiler.internalError("expected a variable",
345 node: element.parseNode(builder.compiler)); 348 node: element.parseNode(builder.compiler));
346 } 349 }
347 350
348 if (isAccessedDirectly(element)) { 351 if (isAccessedDirectly(element)) {
349 directLocals[element] = value; 352 directLocals[element] = value;
350 } else if (isStoredInClosureField(element)) { 353 } else if (isStoredInClosureField(element)) {
351 Element redirect = redirectionMapping[element]; 354 Element redirect = redirectionMapping[element];
352 // We must not use the [LocalsHandler.thisDefinition] since that could 355 // We must not use the [LocalsHandler.readThis()] since that could
353 // point to a captured this which would be stored in a closure-field 356 // point to a captured this which would be stored in a closure-field
354 // itself. 357 // itself.
355 HInstruction receiver = new HThis(); 358 HInstruction receiver = new HThis();
356 builder.add(receiver); 359 builder.add(receiver);
357 builder.add(new HFieldSet(redirect, receiver, value)); 360 builder.add(new HFieldSet(redirect, receiver, value));
358 } else if (isBoxed(element)) { 361 } else if (isBoxed(element)) {
359 Element redirect = redirectionMapping[element]; 362 Element redirect = redirectionMapping[element];
360 // The box itself could be captured, or be local. A local variable that 363 // The box itself could be captured, or be local. A local variable that
361 // is captured will be boxed, but the box itself will be a local. 364 // is captured will be boxed, but the box itself will be a local.
362 // Inside the closure the box is stored in a closure-field and cannot 365 // Inside the closure the box is stored in a closure-field and cannot
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 assert(capturedLocal != null); 767 assert(capturedLocal != null);
765 capturedVariables.add(localsHandler.readLocal(capturedLocal)); 768 capturedVariables.add(localsHandler.readLocal(capturedLocal));
766 } 769 }
767 } 770 }
768 771
769 push(new HForeignNew(globalizedClosureElement, capturedVariables)); 772 push(new HForeignNew(globalizedClosureElement, capturedVariables));
770 } 773 }
771 774
772 visitIdentifier(Identifier node) { 775 visitIdentifier(Identifier node) {
773 if (node.isThis()) { 776 if (node.isThis()) {
774 if (localsHandler.thisDefinition === null) { 777 stack.add(localsHandler.readThis());
775 compiler.unimplemented("Ssa.visitIdentifier.", node: node);
776 }
777 stack.add(localsHandler.thisDefinition);
778 } else { 778 } else {
779 compiler.internalError("SsaBuilder.visitIdentifier on non-this", 779 compiler.internalError("SsaBuilder.visitIdentifier on non-this",
780 node: node); 780 node: node);
781 } 781 }
782 } 782 }
783 783
784 visitIf(If node) { 784 visitIf(If node) {
785 // Add the condition to the current block. 785 // Add the condition to the current block.
786 bool hasElse = node.hasElsePart; 786 bool hasElse = node.hasElsePart;
787 visit(node.condition); 787 visit(node.condition);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 void generateGetter(Send send, Element element) { 991 void generateGetter(Send send, Element element) {
992 Selector selector = elements.getSelector(send); 992 Selector selector = elements.getSelector(send);
993 if (Elements.isStaticOrTopLevelField(element)) { 993 if (Elements.isStaticOrTopLevelField(element)) {
994 push(new HStatic(element)); 994 push(new HStatic(element));
995 if (element.kind == ElementKind.GETTER) { 995 if (element.kind == ElementKind.GETTER) {
996 push(new HInvokeStatic(selector, <HInstruction>[pop()])); 996 push(new HInvokeStatic(selector, <HInstruction>[pop()]));
997 } 997 }
998 } else if (element === null || Elements.isInstanceField(element)) { 998 } else if (element === null || Elements.isInstanceField(element)) {
999 HInstruction receiver; 999 HInstruction receiver;
1000 if (send.receiver == null) { 1000 if (send.receiver == null) {
1001 receiver = localsHandler.thisDefinition; 1001 receiver = localsHandler.readThis();
1002 if (receiver === null) {
1003 compiler.unimplemented("SsaBuilder.generateGetter.", node: send);
1004 }
1005 } else { 1002 } else {
1006 visit(send.receiver); 1003 visit(send.receiver);
1007 receiver = pop(); 1004 receiver = pop();
1008 } 1005 }
1009 SourceString getterName = send.selector.asIdentifier().source; 1006 SourceString getterName = send.selector.asIdentifier().source;
1010 Element staticInterceptor = null; 1007 Element staticInterceptor = null;
1011 if (methodInterceptionEnabled) { 1008 if (methodInterceptionEnabled) {
1012 staticInterceptor = interceptors.getStaticGetInterceptor(getterName); 1009 staticInterceptor = interceptors.getStaticGetInterceptor(getterName);
1013 } 1010 }
1014 if (staticInterceptor != null) { 1011 if (staticInterceptor != null) {
(...skipping 19 matching lines...) Expand all
1034 add(target); 1031 add(target);
1035 add(new HInvokeStatic(selector, <HInstruction>[target, value])); 1032 add(new HInvokeStatic(selector, <HInstruction>[target, value]));
1036 } else { 1033 } else {
1037 add(new HStaticStore(element, value)); 1034 add(new HStaticStore(element, value));
1038 } 1035 }
1039 stack.add(value); 1036 stack.add(value);
1040 } else if (element === null || Elements.isInstanceField(element)) { 1037 } else if (element === null || Elements.isInstanceField(element)) {
1041 SourceString dartSetterName = send.selector.asIdentifier().source; 1038 SourceString dartSetterName = send.selector.asIdentifier().source;
1042 HInstruction receiver; 1039 HInstruction receiver;
1043 if (send.receiver == null) { 1040 if (send.receiver == null) {
1044 receiver = localsHandler.thisDefinition; 1041 receiver = localsHandler.readThis();
1045 if (receiver === null) {
1046 compiler.unimplemented("Ssa.generateSetter.", node: send);
1047 }
1048 } else { 1042 } else {
1049 visit(send.receiver); 1043 visit(send.receiver);
1050 receiver = pop(); 1044 receiver = pop();
1051 } 1045 }
1052 add(new HInvokeDynamicSetter( 1046 add(new HInvokeDynamicSetter(
1053 selector, null, dartSetterName, receiver, value)); 1047 selector, null, dartSetterName, receiver, value));
1054 stack.add(value); 1048 stack.add(value);
1055 } else { 1049 } else {
1056 localsHandler.updateLocal(element, value); 1050 localsHandler.updateLocal(element, value);
1057 stack.add(value); 1051 stack.add(value);
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1229 add(target); 1223 add(target);
1230 inputs.add(target); 1224 inputs.add(target);
1231 visit(node.receiver); 1225 visit(node.receiver);
1232 inputs.add(pop()); 1226 inputs.add(pop());
1233 addGenericSendArgumentsToList(node.arguments, inputs); 1227 addGenericSendArgumentsToList(node.arguments, inputs);
1234 push(new HInvokeInterceptor(selector, dartMethodName, false, inputs)); 1228 push(new HInvokeInterceptor(selector, dartMethodName, false, inputs));
1235 return; 1229 return;
1236 } 1230 }
1237 1231
1238 if (node.receiver === null) { 1232 if (node.receiver === null) {
1239 HThis receiver = localsHandler.thisDefinition; 1233 HThis receiver = localsHandler.readThis;
1240 if (receiver === null) {
1241 compiler.unimplemented("Ssa.visitDynamicSend.", node: node);
1242 }
1243 inputs.add(receiver); 1234 inputs.add(receiver);
1244 } else { 1235 } else {
1245 visit(node.receiver); 1236 visit(node.receiver);
1246 inputs.add(pop()); 1237 inputs.add(pop());
1247 } 1238 }
1248 1239
1249 addDynamicSendArgumentsToList(node, inputs); 1240 addDynamicSendArgumentsToList(node, inputs);
1250 1241
1251 // The first entry in the inputs list is the receiver. 1242 // The first entry in the inputs list is the receiver.
1252 push(new HInvokeDynamicMethod(selector, dartMethodName, inputs)); 1243 push(new HInvokeDynamicMethod(selector, dartMethodName, inputs));
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1317 break; 1308 break;
1318 default: 1309 default:
1319 throw "Unknown foreign: ${node.selector}"; 1310 throw "Unknown foreign: ${node.selector}";
1320 } 1311 }
1321 } 1312 }
1322 1313
1323 visitSuperSend(Send node) { 1314 visitSuperSend(Send node) {
1324 Selector selector = elements.getSelector(node); 1315 Selector selector = elements.getSelector(node);
1325 Element element = elements[node]; 1316 Element element = elements[node];
1326 HStatic target = new HStatic(element); 1317 HStatic target = new HStatic(element);
1327 HThis context = localsHandler.thisDefinition; 1318 HThis context = localsHandler.readThis;
1328 if (context === null) {
1329 compiler.unimplemented("Ssa.visitSuperSend without thisDefinition.",
1330 node: node);
1331 }
1332 add(target); 1319 add(target);
1333 var inputs = <HInstruction>[target, context]; 1320 var inputs = <HInstruction>[target, context];
1334 addStaticSendArgumentsToList(node, element, inputs); 1321 addStaticSendArgumentsToList(node, element, inputs);
1335 push(new HInvokeSuper(selector, inputs)); 1322 push(new HInvokeSuper(selector, inputs));
1336 } 1323 }
1337 1324
1338 visitStaticSend(Send node) { 1325 visitStaticSend(Send node) {
1339 Selector selector = elements.getSelector(node); 1326 Selector selector = elements.getSelector(node);
1340 Element element = elements[node]; 1327 Element element = elements[node];
1341 HStatic target = new HStatic(element); 1328 HStatic target = new HStatic(element);
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
1773 if (exception.type != null) { 1760 if (exception.type != null) {
1774 compiler.unimplemented('SsaBuilder catch with type', node: node); 1761 compiler.unimplemented('SsaBuilder catch with type', node: node);
1775 } 1762 }
1776 visit(node.block); 1763 visit(node.block);
1777 } 1764 }
1778 1765
1779 visitTypedef(Typedef node) { 1766 visitTypedef(Typedef node) {
1780 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); 1767 compiler.unimplemented('SsaBuilder.visitTypedef', node: node);
1781 } 1768 }
1782 } 1769 }
OLDNEW
« no previous file with comments | « no previous file | frog/leg/ssa/closure.dart » ('j') | frog/leg/ssa/closure.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698