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

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

Issue 2933363003: Add ClosureRepresentationInfo, the new public face of ClosureClassMap (Closed)
Patch Set: . 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 14 matching lines...) Expand all
25 /// The values of locals that can be directly accessed (without redirections 25 /// The values of locals that can be directly accessed (without redirections
26 /// to boxes or closure-fields). 26 /// to boxes or closure-fields).
27 /// 27 ///
28 /// [directLocals] is iterated, so it is "insertion ordered" to make the 28 /// [directLocals] is iterated, so it is "insertion ordered" to make the
29 /// iteration order a function only of insertions and not a function of 29 /// iteration order a function only of insertions and not a function of
30 /// e.g. Element hash codes. I'd prefer to use a SortedMap but some elements 30 /// e.g. Element hash codes. I'd prefer to use a SortedMap but some elements
31 /// don't have source locations for [Elements.compareByPosition]. 31 /// don't have source locations for [Elements.compareByPosition].
32 Map<Local, HInstruction> directLocals = new Map<Local, HInstruction>(); 32 Map<Local, HInstruction> directLocals = new Map<Local, HInstruction>();
33 Map<Local, FieldEntity> redirectionMapping = new Map<Local, FieldEntity>(); 33 Map<Local, FieldEntity> redirectionMapping = new Map<Local, FieldEntity>();
34 final GraphBuilder builder; 34 final GraphBuilder builder;
35 ClosureClassMap closureData; 35 ClosureRepresentationInfo closureData;
36 Map<TypeVariableType, TypeVariableLocal> typeVariableLocals = 36 Map<TypeVariableType, TypeVariableLocal> typeVariableLocals =
37 new Map<TypeVariableType, TypeVariableLocal>(); 37 new Map<TypeVariableType, TypeVariableLocal>();
38 final Entity executableContext; 38 final Entity executableContext;
39 final MemberEntity memberContext; 39 final MemberEntity memberContext;
40 40
41 /// The class that defines the current type environment or null if no type 41 /// The class that defines the current type environment or null if no type
42 /// variables are in scope. 42 /// variables are in scope.
43 final ClassEntity contextClass; 43 final ClassEntity contextClass;
44 44
45 /// The type of the current instance, if concrete. 45 /// The type of the current instance, if concrete.
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 HInstruction oldValue = readLocal(boxedVariable); 189 HInstruction oldValue = readLocal(boxedVariable);
190 updateLocal(boxElement, newBox); 190 updateLocal(boxElement, newBox);
191 updateLocal(boxedVariable, oldValue); 191 updateLocal(boxedVariable, oldValue);
192 } 192 }
193 updateLocal(boxElement, newBox); 193 updateLocal(boxElement, newBox);
194 } 194 }
195 195
196 /// Documentation wanted -- johnniwinther 196 /// Documentation wanted -- johnniwinther
197 /// 197 ///
198 /// Invariant: [function] must be an implementation element. 198 /// Invariant: [function] must be an implementation element.
199 void startFunction(MemberEntity element, ClosureClassMap closureData, 199 void startFunction(
200 ClosureScope scopeData, Map<Local, TypeMask> parameters, 200 MemberEntity element,
201 ClosureRepresentationInfo closureData,
202 ClosureAnalysisInfo scopeData,
203 Map<Local, TypeMask> parameters,
201 {bool isGenerativeConstructorBody}) { 204 {bool isGenerativeConstructorBody}) {
202 assert(!(element is MemberElement && !element.isImplementation), 205 assert(!(element is MemberElement && !element.isImplementation),
203 failedAt(element)); 206 failedAt(element));
204 this.closureData = closureData; 207 this.closureData = closureData;
205 208
206 parameters.forEach((Local local, TypeMask typeMask) { 209 parameters.forEach((Local local, TypeMask typeMask) {
207 if (isGenerativeConstructorBody) { 210 if (isGenerativeConstructorBody) {
208 if (scopeData != null && scopeData.isCaptured(local)) { 211 if (scopeData.isCaptured(local)) {
209 // The parameter will be a field in the box passed as the 212 // The parameter will be a field in the box passed as the
210 // last parameter. So no need to have it. 213 // last parameter. So no need to have it.
211 return; 214 return;
212 } 215 }
213 } 216 }
214 HInstruction parameter = builder.addParameter(local, typeMask); 217 HInstruction parameter = builder.addParameter(local, typeMask);
215 builder.parameters[local] = parameter; 218 builder.parameters[local] = parameter;
216 directLocals[local] = parameter; 219 directLocals[local] = parameter;
217 }); 220 });
218 221
219 if (scopeData != null) { 222 enterScope(scopeData,
220 // TODO(efortuna): Remove the above if wrapper (always execute this step) 223 forGenerativeConstructorBody: isGenerativeConstructorBody);
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 }
227 224
228 // If the freeVariableMapping is not empty, then this function was a 225 // If the freeVariableMapping is not empty, then this function was a
229 // nested closure that captures variables. Redirect the captured 226 // nested closure that captures variables. Redirect the captured
230 // variables to fields in the closure. 227 // variables to fields in the closure.
231 closureData.forEachFreeVariable((Local from, FieldEntity to) { 228 closureData.forEachFreeVariable((Local from, FieldEntity to) {
232 redirectElement(from, to); 229 redirectElement(from, to);
233 }); 230 });
234 if (closureData.isClosure) { 231 if (closureData.isClosure) {
235 // Inside closure redirect references to itself to [:this:]. 232 // Inside closure redirect references to itself to [:this:].
236 HThis thisInstruction = 233 HThis thisInstruction =
237 new HThis(closureData.thisLocal, commonMasks.nonNullType); 234 new HThis(closureData.thisLocal, commonMasks.nonNullType);
238 builder.graph.thisInstruction = thisInstruction; 235 builder.graph.thisInstruction = thisInstruction;
239 builder.graph.entry.addAtEntry(thisInstruction); 236 builder.graph.entry.addAtEntry(thisInstruction);
240 updateLocal(closureData.closureElement, thisInstruction); 237 updateLocal(closureData.closureEntity, thisInstruction);
241 } else if (element.isInstanceMember) { 238 } else if (element.isInstanceMember) {
242 // Once closures have been mapped to classes their instance members might 239 // Once closures have been mapped to classes their instance members might
243 // not have any thisElement if the closure was created inside a static 240 // not have any thisElement if the closure was created inside a static
244 // context. 241 // context.
245 HThis thisInstruction = new HThis(closureData.thisLocal, getTypeOfThis()); 242 HThis thisInstruction = new HThis(closureData.thisLocal, getTypeOfThis());
246 builder.graph.thisInstruction = thisInstruction; 243 builder.graph.thisInstruction = thisInstruction;
247 builder.graph.entry.addAtEntry(thisInstruction); 244 builder.graph.entry.addAtEntry(thisInstruction);
248 directLocals[closureData.thisLocal] = thisInstruction; 245 directLocals[closureData.thisLocal] = thisInstruction;
249 } 246 }
250 247
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 builder.lastAddedParameter = value; 285 builder.lastAddedParameter = value;
289 } 286 }
290 } 287 }
291 } 288 }
292 289
293 /// Returns true if the local can be accessed directly. Boxed variables or 290 /// Returns true if the local can be accessed directly. Boxed variables or
294 /// captured variables that are stored in the closure-field return [:false:]. 291 /// captured variables that are stored in the closure-field return [:false:].
295 bool isAccessedDirectly(Local local) { 292 bool isAccessedDirectly(Local local) {
296 assert(local != null); 293 assert(local != null);
297 return !redirectionMapping.containsKey(local) && 294 return !redirectionMapping.containsKey(local) &&
298 !closureData.variablesUsedInTryOrGenerator.contains(local); 295 !closureData.variableIsUsedInTryOrSync(local);
299 } 296 }
300 297
301 bool isStoredInClosureField(Local local) { 298 bool isStoredInClosureField(Local local) {
302 assert(local != null); 299 assert(local != null);
303 if (isAccessedDirectly(local)) return false; 300 if (isAccessedDirectly(local)) return false;
304 FieldEntity redirectTarget = redirectionMapping[local]; 301 FieldEntity redirectTarget = redirectionMapping[local];
305 if (redirectTarget == null) return false; 302 if (redirectTarget == null) return false;
306 return redirectTarget is ClosureFieldElement; 303 return redirectTarget is ClosureFieldElement;
307 } 304 }
308 305
309 bool isBoxed(Local local) { 306 bool isBoxed(Local local) {
310 if (isAccessedDirectly(local)) return false; 307 if (isAccessedDirectly(local)) return false;
311 if (isStoredInClosureField(local)) return false; 308 if (isStoredInClosureField(local)) return false;
312 return redirectionMapping.containsKey(local); 309 return redirectionMapping.containsKey(local);
313 } 310 }
314 311
315 bool isUsedInTryOrGenerator(Local local) { 312 bool isUsedInTryOrGenerator(Local local) {
316 return closureData.variablesUsedInTryOrGenerator.contains(local); 313 return closureData.variableIsUsedInTryOrSync(local);
317 } 314 }
318 315
319 /// Returns an [HInstruction] for the given element. If the element is 316 /// Returns an [HInstruction] for the given element. If the element is
320 /// boxed or stored in a closure then the method generates code to retrieve 317 /// boxed or stored in a closure then the method generates code to retrieve
321 /// the value. 318 /// the value.
322 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) { 319 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) {
323 if (isAccessedDirectly(local)) { 320 if (isAccessedDirectly(local)) {
324 if (directLocals[local] == null) { 321 if (directLocals[local] == null) {
325 if (local is TypeVariableLocal) { 322 if (local is TypeVariableLocal) {
326 throw new SpannableAssertionFailure( 323 throw new SpannableAssertionFailure(
327 CURRENT_ELEMENT_SPANNABLE, 324 CURRENT_ELEMENT_SPANNABLE,
328 "Runtime type information not available for $local " 325 "Runtime type information not available for $local "
329 "in $executableContext."); 326 "in $executableContext.");
330 } else { 327 } else {
331 throw new SpannableAssertionFailure( 328 throw new SpannableAssertionFailure(
332 local, 329 local,
333 "Cannot find value $local in ${directLocals.keys} for " 330 "Cannot find value $local in ${directLocals.keys} for "
334 "$executableContext."); 331 "$executableContext.");
335 } 332 }
336 } 333 }
337 HInstruction value = directLocals[local]; 334 HInstruction value = directLocals[local];
338 if (sourceInformation != null) { 335 if (sourceInformation != null) {
339 value = new HRef(value, sourceInformation); 336 value = new HRef(value, sourceInformation);
340 builder.add(value); 337 builder.add(value);
341 } 338 }
342 return value; 339 return value;
343 } else if (isStoredInClosureField(local)) { 340 } else if (isStoredInClosureField(local)) {
344 ClosureFieldElement redirect = redirectionMapping[local]; 341 ClosureFieldElement redirect = redirectionMapping[local];
345 HInstruction receiver = readLocal(closureData.closureElement); 342 HInstruction receiver = readLocal(closureData.closureEntity);
346 TypeMask type = local is BoxLocal 343 TypeMask type = local is BoxLocal
347 ? commonMasks.nonNullType 344 ? commonMasks.nonNullType
348 : getTypeOfCapturedVariable(redirect); 345 : getTypeOfCapturedVariable(redirect);
349 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); 346 HInstruction fieldGet = new HFieldGet(redirect, receiver, type);
350 builder.add(fieldGet); 347 builder.add(fieldGet);
351 return fieldGet..sourceInformation = sourceInformation; 348 return fieldGet..sourceInformation = sourceInformation;
352 } else if (isBoxed(local)) { 349 } else if (isBoxed(local)) {
353 BoxFieldElement redirect = redirectionMapping[local]; 350 BoxFieldElement redirect = redirectionMapping[local];
354 // In the function that declares the captured variable the box is 351 // In the function that declares the captured variable the box is
355 // accessed as direct local. Inside the nested closure the box is 352 // accessed as direct local. Inside the nested closure the box is
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 final MemberEntity memberContext; 673 final MemberEntity memberContext;
677 674
678 // Avoid slow Object.hashCode. 675 // Avoid slow Object.hashCode.
679 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); 676 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30);
680 static int _nextHashCode = 0; 677 static int _nextHashCode = 0;
681 678
682 SyntheticLocal(this.name, this.executableContext, this.memberContext); 679 SyntheticLocal(this.name, this.executableContext, this.memberContext);
683 680
684 toString() => 'SyntheticLocal($name)'; 681 toString() => 'SyntheticLocal($name)';
685 } 682 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698