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

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: Make this-capture work in the context of constructors. 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 | « frog/leg/elements/elements.dart ('k') | frog/leg/ssa/closure.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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 135
136 /** 136 /**
137 * Keeps track of locals (including parameters and phis) when building. The 137 * Keeps track of locals (including parameters and phis) when building. The
138 * 'this' reference is treated as parameter and hence handled by this class, 138 * 'this' reference is treated as parameter and hence handled by this class,
139 * too. 139 * too.
140 */ 140 */
141 class LocalsHandler { 141 class LocalsHandler {
142 // The values of locals that can be directly accessed (without redirections 142 // The values of locals that can be directly accessed (without redirections
143 // to boxes or closure-fields). 143 // to boxes or closure-fields).
144 Map<Element, HInstruction> directLocals; 144 Map<Element, HInstruction> directLocals;
145 HInstruction thisDefinition;
146 Map<Element, Element> redirectionMapping; 145 Map<Element, Element> redirectionMapping;
147 SsaBuilder builder; 146 SsaBuilder builder;
148 ClosureData closureData; 147 ClosureData closureData;
149 148
150 LocalsHandler(this.builder) 149 LocalsHandler(this.builder)
151 : directLocals = new Map<Element, HInstruction>(), 150 : directLocals = new Map<Element, HInstruction>(),
152 redirectionMapping = new Map<Element, Element>(); 151 redirectionMapping = new Map<Element, Element>();
153 152
154 /** 153 /**
155 * Creates a new [LocalsHandler] based on [other]. We only need to 154 * Creates a new [LocalsHandler] based on [other]. We only need to
156 * copy the [directLocals], since the other fields can be shared 155 * copy the [directLocals], since the other fields can be shared
157 * throughout the AST visit. 156 * throughout the AST visit.
158 */ 157 */
159 LocalsHandler.from(LocalsHandler other) 158 LocalsHandler.from(LocalsHandler other)
160 : directLocals = new Map<Element, HInstruction>.from(other.directLocals), 159 : directLocals = new Map<Element, HInstruction>.from(other.directLocals),
161 redirectionMapping = other.redirectionMapping, 160 redirectionMapping = other.redirectionMapping,
162 builder = other.builder, 161 builder = other.builder,
163 thisDefinition = other.thisDefinition,
164 closureData = other.closureData; 162 closureData = other.closureData;
165 163
166 void startFunction(FunctionElement function, 164 void startFunction(FunctionElement function,
167 FunctionExpression node) { 165 FunctionExpression node) {
168 166
169 ClosureTranslator translator = 167 ClosureTranslator translator =
170 new ClosureTranslator(builder.compiler, builder.elements); 168 new ClosureTranslator(builder.compiler, builder.elements);
171 closureData = translator.translate(node); 169 closureData = translator.translate(node);
172 170
173 if (function.isInstanceMember()) { 171 if (closureData.thisElement !== null &&
174 thisDefinition = new HThis(); 172 isAccessedDirectly(closureData.thisElement)) {
175 builder.add(thisDefinition); 173 HInstruction thisInstruction = new HThis();
174 updateLocal(closureData.thisElement, thisInstruction);
175 builder.add(thisInstruction);
176 } 176 }
177 177
178 FunctionParameters params = function.computeParameters(builder.compiler); 178 FunctionParameters params = function.computeParameters(builder.compiler);
179 params.forEachParameter((Element element) { 179 params.forEachParameter((Element element) {
180 HParameterValue parameter = new HParameterValue(element); 180 HParameterValue parameter = new HParameterValue(element);
181 builder.add(parameter); 181 builder.add(parameter);
182 // Note that for constructors [element] could be a field-element which we 182 // Note that for constructors [element] could be a field-element which we
183 // treat as if it was a local. 183 // treat as if it was a local.
184 directLocals[element] = parameter; 184 directLocals[element] = parameter;
185 }); 185 });
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 */ 275 */
276 HInstruction readLocal(Element element) { 276 HInstruction readLocal(Element element) {
277 if (isAccessedDirectly(element)) { 277 if (isAccessedDirectly(element)) {
278 if (directLocals[element] == null) { 278 if (directLocals[element] == null) {
279 builder.compiler.internalError( 279 builder.compiler.internalError(
280 "Could not find value", node: element.parseNode(builder.compiler)); 280 "Could not find value", node: element.parseNode(builder.compiler));
281 } 281 }
282 return directLocals[element]; 282 return directLocals[element];
283 } else if (isStoredInClosureField(element)) { 283 } else if (isStoredInClosureField(element)) {
284 Element redirect = redirectionMapping[element]; 284 Element redirect = redirectionMapping[element];
285 // We must not use the [LocalsHandler.thisDefinition] since that could 285 // We must not use the [LocalsHandler.readThis()] since that could
286 // point to a captured this which would be stored in a closure-field 286 // point to a captured this which would be stored in a closure-field
287 // itself. 287 // itself.
288 HInstruction receiver = new HThis(); 288 HInstruction receiver = new HThis();
289 builder.add(receiver); 289 builder.add(receiver);
290 HInstruction fieldGet = new HFieldGet(redirect, receiver); 290 HInstruction fieldGet = new HFieldGet(redirect, receiver);
291 builder.add(fieldGet); 291 builder.add(fieldGet);
292 return fieldGet; 292 return fieldGet;
293 } else if (isBoxed(element)) { 293 } else if (isBoxed(element)) {
294 Element redirect = redirectionMapping[element]; 294 Element redirect = redirectionMapping[element];
295 // In the function that declares the captured variable the box is 295 // In the function that declares the captured variable the box is
296 // accessed as direct local. Inside the nested closure the box is 296 // accessed as direct local. Inside the nested closure the box is
297 // accessed through a closure-field. 297 // accessed through a closure-field.
298 // Calling [readLocal] makes sure we generate the correct code to get 298 // Calling [readLocal] makes sure we generate the correct code to get
299 // the box. 299 // the box.
300 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); 300 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE);
301 HInstruction box = readLocal(redirect.enclosingElement); 301 HInstruction box = readLocal(redirect.enclosingElement);
302 HInstruction lookup = new HFieldGet(redirect, box); 302 HInstruction lookup = new HFieldGet(redirect, box);
303 builder.add(lookup); 303 builder.add(lookup);
304 return lookup; 304 return lookup;
305 } else { 305 } else {
306 assert(isUsedInTry(element)); 306 assert(isUsedInTry(element));
307 HInstruction variable = new HFieldGet.fromActivation(element); 307 HInstruction variable = new HFieldGet.fromActivation(element);
308 builder.add(variable); 308 builder.add(variable);
309 return variable; 309 return variable;
310 } 310 }
311 } 311 }
312 312
313 HInstruction readThis() {
314 return readLocal(closureData.thisElement);
315 }
316
313 /** 317 /**
314 * Sets the [element] to [value]. If the element is boxed or stored in a 318 * Sets the [element] to [value]. If the element is boxed or stored in a
315 * closure then the method generates code to set the value. 319 * closure then the method generates code to set the value.
316 */ 320 */
317 void updateLocal(Element element, HInstruction value) { 321 void updateLocal(Element element, HInstruction value) {
318 // TODO(floitsch): replace the following if with an assert.
319 if (element is !VariableElement) {
320 builder.compiler.internalError("expected a variable",
321 node: element.parseNode(builder.compiler));
322 }
323
324 if (isAccessedDirectly(element)) { 322 if (isAccessedDirectly(element)) {
325 directLocals[element] = value; 323 directLocals[element] = value;
326 } else if (isStoredInClosureField(element)) { 324 } else if (isStoredInClosureField(element)) {
327 Element redirect = redirectionMapping[element]; 325 Element redirect = redirectionMapping[element];
328 // We must not use the [LocalsHandler.thisDefinition] since that could 326 // We must not use the [LocalsHandler.readThis()] since that could
329 // point to a captured this which would be stored in a closure-field 327 // point to a captured this which would be stored in a closure-field
330 // itself. 328 // itself.
331 HInstruction receiver = new HThis(); 329 HInstruction receiver = new HThis();
332 builder.add(receiver); 330 builder.add(receiver);
333 builder.add(new HFieldSet(redirect, receiver, value)); 331 builder.add(new HFieldSet(redirect, receiver, value));
334 } else if (isBoxed(element)) { 332 } else if (isBoxed(element)) {
335 Element redirect = redirectionMapping[element]; 333 Element redirect = redirectionMapping[element];
336 // The box itself could be captured, or be local. A local variable that 334 // The box itself could be captured, or be local. A local variable that
337 // is captured will be boxed, but the box itself will be a local. 335 // is captured will be boxed, but the box itself will be a local.
338 // Inside the closure the box is stored in a closure-field and cannot 336 // Inside the closure the box is stored in a closure-field and cannot
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 assert(capturedLocal != null); 855 assert(capturedLocal != null);
858 capturedVariables.add(localsHandler.readLocal(capturedLocal)); 856 capturedVariables.add(localsHandler.readLocal(capturedLocal));
859 } 857 }
860 } 858 }
861 859
862 push(new HForeignNew(globalizedClosureElement, capturedVariables)); 860 push(new HForeignNew(globalizedClosureElement, capturedVariables));
863 } 861 }
864 862
865 visitIdentifier(Identifier node) { 863 visitIdentifier(Identifier node) {
866 if (node.isThis()) { 864 if (node.isThis()) {
867 if (localsHandler.thisDefinition === null) { 865 stack.add(localsHandler.readThis());
868 compiler.unimplemented("Ssa.visitIdentifier.", node: node);
869 }
870 stack.add(localsHandler.thisDefinition);
871 } else { 866 } else {
872 compiler.internalError("SsaBuilder.visitIdentifier on non-this", 867 compiler.internalError("SsaBuilder.visitIdentifier on non-this",
873 node: node); 868 node: node);
874 } 869 }
875 } 870 }
876 871
877 visitIf(If node) { 872 visitIf(If node) {
878 // Add the condition to the current block. 873 // Add the condition to the current block.
879 bool hasElse = node.hasElsePart; 874 bool hasElse = node.hasElsePart;
880 visit(node.condition); 875 visit(node.condition);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 void generateGetter(Send send, Element element) { 1079 void generateGetter(Send send, Element element) {
1085 Selector selector = elements.getSelector(send); 1080 Selector selector = elements.getSelector(send);
1086 if (Elements.isStaticOrTopLevelField(element)) { 1081 if (Elements.isStaticOrTopLevelField(element)) {
1087 push(new HStatic(element)); 1082 push(new HStatic(element));
1088 if (element.kind == ElementKind.GETTER) { 1083 if (element.kind == ElementKind.GETTER) {
1089 push(new HInvokeStatic(selector, <HInstruction>[pop()])); 1084 push(new HInvokeStatic(selector, <HInstruction>[pop()]));
1090 } 1085 }
1091 } else if (element === null || Elements.isInstanceField(element)) { 1086 } else if (element === null || Elements.isInstanceField(element)) {
1092 HInstruction receiver; 1087 HInstruction receiver;
1093 if (send.receiver == null) { 1088 if (send.receiver == null) {
1094 receiver = localsHandler.thisDefinition; 1089 receiver = localsHandler.readThis();
1095 if (receiver === null) {
1096 compiler.unimplemented("SsaBuilder.generateGetter.", node: send);
1097 }
1098 } else { 1090 } else {
1099 visit(send.receiver); 1091 visit(send.receiver);
1100 receiver = pop(); 1092 receiver = pop();
1101 } 1093 }
1102 SourceString getterName = send.selector.asIdentifier().source; 1094 SourceString getterName = send.selector.asIdentifier().source;
1103 Element staticInterceptor = null; 1095 Element staticInterceptor = null;
1104 if (methodInterceptionEnabled) { 1096 if (methodInterceptionEnabled) {
1105 staticInterceptor = interceptors.getStaticGetInterceptor(getterName); 1097 staticInterceptor = interceptors.getStaticGetInterceptor(getterName);
1106 } 1098 }
1107 if (staticInterceptor != null) { 1099 if (staticInterceptor != null) {
(...skipping 19 matching lines...) Expand all
1127 add(target); 1119 add(target);
1128 add(new HInvokeStatic(selector, <HInstruction>[target, value])); 1120 add(new HInvokeStatic(selector, <HInstruction>[target, value]));
1129 } else { 1121 } else {
1130 add(new HStaticStore(element, value)); 1122 add(new HStaticStore(element, value));
1131 } 1123 }
1132 stack.add(value); 1124 stack.add(value);
1133 } else if (element === null || Elements.isInstanceField(element)) { 1125 } else if (element === null || Elements.isInstanceField(element)) {
1134 SourceString dartSetterName = send.selector.asIdentifier().source; 1126 SourceString dartSetterName = send.selector.asIdentifier().source;
1135 HInstruction receiver; 1127 HInstruction receiver;
1136 if (send.receiver == null) { 1128 if (send.receiver == null) {
1137 receiver = localsHandler.thisDefinition; 1129 receiver = localsHandler.readThis();
1138 if (receiver === null) {
1139 compiler.unimplemented("Ssa.generateSetter.", node: send);
1140 }
1141 } else { 1130 } else {
1142 visit(send.receiver); 1131 visit(send.receiver);
1143 receiver = pop(); 1132 receiver = pop();
1144 } 1133 }
1145 add(new HInvokeDynamicSetter( 1134 add(new HInvokeDynamicSetter(
1146 selector, null, dartSetterName, receiver, value)); 1135 selector, null, dartSetterName, receiver, value));
1147 stack.add(value); 1136 stack.add(value);
1148 } else { 1137 } else {
1149 localsHandler.updateLocal(element, value); 1138 localsHandler.updateLocal(element, value);
1150 stack.add(value); 1139 stack.add(value);
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1322 add(target); 1311 add(target);
1323 inputs.add(target); 1312 inputs.add(target);
1324 visit(node.receiver); 1313 visit(node.receiver);
1325 inputs.add(pop()); 1314 inputs.add(pop());
1326 addGenericSendArgumentsToList(node.arguments, inputs); 1315 addGenericSendArgumentsToList(node.arguments, inputs);
1327 push(new HInvokeInterceptor(selector, dartMethodName, false, inputs)); 1316 push(new HInvokeInterceptor(selector, dartMethodName, false, inputs));
1328 return; 1317 return;
1329 } 1318 }
1330 1319
1331 if (node.receiver === null) { 1320 if (node.receiver === null) {
1332 HThis receiver = localsHandler.thisDefinition; 1321 inputs.add(localsHandler.readThis());
1333 if (receiver === null) {
1334 compiler.unimplemented("Ssa.visitDynamicSend.", node: node);
1335 }
1336 inputs.add(receiver);
1337 } else { 1322 } else {
1338 visit(node.receiver); 1323 visit(node.receiver);
1339 inputs.add(pop()); 1324 inputs.add(pop());
1340 } 1325 }
1341 1326
1342 addDynamicSendArgumentsToList(node, inputs); 1327 addDynamicSendArgumentsToList(node, inputs);
1343 1328
1344 // The first entry in the inputs list is the receiver. 1329 // The first entry in the inputs list is the receiver.
1345 push(new HInvokeDynamicMethod(selector, dartMethodName, inputs)); 1330 push(new HInvokeDynamicMethod(selector, dartMethodName, inputs));
1346 1331
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1410 break; 1395 break;
1411 default: 1396 default:
1412 throw "Unknown foreign: ${node.selector}"; 1397 throw "Unknown foreign: ${node.selector}";
1413 } 1398 }
1414 } 1399 }
1415 1400
1416 visitSuperSend(Send node) { 1401 visitSuperSend(Send node) {
1417 Selector selector = elements.getSelector(node); 1402 Selector selector = elements.getSelector(node);
1418 Element element = elements[node]; 1403 Element element = elements[node];
1419 HStatic target = new HStatic(element); 1404 HStatic target = new HStatic(element);
1420 HThis context = localsHandler.thisDefinition; 1405 HInstruction context = localsHandler.readThis();
1421 if (context === null) {
1422 compiler.unimplemented("Ssa.visitSuperSend without thisDefinition.",
1423 node: node);
1424 }
1425 add(target); 1406 add(target);
1426 var inputs = <HInstruction>[target, context]; 1407 var inputs = <HInstruction>[target, context];
1427 addStaticSendArgumentsToList(node, element, inputs); 1408 addStaticSendArgumentsToList(node, element, inputs);
1428 push(new HInvokeSuper(selector, inputs)); 1409 push(new HInvokeSuper(selector, inputs));
1429 } 1410 }
1430 1411
1431 visitStaticSend(Send node) { 1412 visitStaticSend(Send node) {
1432 Selector selector = elements.getSelector(node); 1413 Selector selector = elements.getSelector(node);
1433 Element element = elements[node]; 1414 Element element = elements[node];
1434 HStatic target = new HStatic(element); 1415 HStatic target = new HStatic(element);
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
1868 if (exception.type != null) { 1849 if (exception.type != null) {
1869 compiler.unimplemented('SsaBuilder catch with type', node: node); 1850 compiler.unimplemented('SsaBuilder catch with type', node: node);
1870 } 1851 }
1871 visit(node.block); 1852 visit(node.block);
1872 } 1853 }
1873 1854
1874 visitTypedef(Typedef node) { 1855 visitTypedef(Typedef node) {
1875 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); 1856 compiler.unimplemented('SsaBuilder.visitTypedef', node: node);
1876 } 1857 }
1877 } 1858 }
OLDNEW
« no previous file with comments | « frog/leg/elements/elements.dart ('k') | frog/leg/ssa/closure.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698