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

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

Issue 2994353002: Fix the locals lookup of variables and partial implementation of boxing of variables.
Patch Set: Created 3 years, 4 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';
11 import '../js_backend/native_data.dart'; 11 import '../js_backend/native_data.dart';
12 import '../js_backend/interceptor_data.dart'; 12 import '../js_backend/interceptor_data.dart';
13 import '../js_model/closure.dart' show JClosureField, JRecord;
13 import '../tree/tree.dart' as ast; 14 import '../tree/tree.dart' as ast;
14 import '../types/types.dart'; 15 import '../types/types.dart';
15 import '../world.dart' show ClosedWorld; 16 import '../world.dart' show ClosedWorld;
16 17
17 import 'graph_builder.dart'; 18 import 'graph_builder.dart';
18 import 'nodes.dart'; 19 import 'nodes.dart';
19 import 'types.dart'; 20 import 'types.dart';
20 21
21 /// Keeps track of locals (including parameters and phis) when building. The 22 /// Keeps track of locals (including parameters and phis) when building. The
22 /// 'this' reference is treated as parameter and hence handled by this class, 23 /// 'this' reference is treated as parameter and hence handled by this class,
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 // The box is passed as a parameter to a generative 148 // The box is passed as a parameter to a generative
148 // constructor body. 149 // constructor body.
149 box = builder.addParameter(closureInfo.context, commonMasks.nonNullType); 150 box = builder.addParameter(closureInfo.context, commonMasks.nonNullType);
150 } else { 151 } else {
151 box = createBox(); 152 box = createBox();
152 } 153 }
153 // Add the box to the known locals. 154 // Add the box to the known locals.
154 directLocals[closureInfo.context] = box; 155 directLocals[closureInfo.context] = box;
155 // Make sure that accesses to the boxed locals go into the box. We also 156 // 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. 157 // need to make sure that parameters are copied into the box if necessary.
157 closureInfo.forEachBoxedVariable((_from, _to) { 158 closureInfo.forEachBoxedVariable((Local from, FieldEntity boxTo) {
158 LocalVariableElement from = _from;
159 BoxFieldElement to = _to;
160 // 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
161 // loop scopes. 160 // loop scopes.
162 if (from.isRegularParameter && !forGenerativeConstructorBody) { 161 if (from.isRegularParameter && !forGenerativeConstructorBody) {
163 // 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
164 // write the parameter value into the box. 163 // write the parameter value into the box.
165 // Store the captured parameter in the box. Get the current value 164 // Store the captured parameter in the box. Get the current value
166 // before we put the redirection in place. 165 // before we put the redirection in place.
167 // We don't need to update the local for a generative 166 // We don't need to update the local for a generative
168 // constructor body, because it receives a box that already 167 // constructor body, because it receives a box that already
169 // contains the updates as the last parameter. 168 // contains the updates as the last parameter.
170 HInstruction instruction = readLocal(from); 169 HInstruction instruction = readLocal(from);
171 redirectElement(from, to); 170 redirectElement(from, boxTo);
172 updateLocal(from, instruction); 171 updateLocal(from, instruction);
173 } else { 172 } else {
174 redirectElement(from, to); 173 redirectElement(from, boxTo);
175 } 174 }
176 }); 175 });
177 } 176 }
178 177
179 /// Replaces the current box with a new box and copies over the given list 178 /// Replaces the current box with a new box and copies over the given list
180 /// of elements from the old box into the new box. 179 /// of elements from the old box into the new box.
181 void updateCaptureBox(Local currentBox, List<Local> toBeCopiedElements) { 180 void updateCaptureBox(Local currentBox, List<Local> toBeCopiedElements) {
182 // Create a new box and copy over the values from the old box into the 181 // Create a new box and copy over the values from the old box into the
183 // new one. 182 // new one.
184 HInstruction oldBox = readLocal(currentBox); 183 HInstruction oldBox = readLocal(currentBox);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 assert(local != null); 294 assert(local != null);
296 return !redirectionMapping.containsKey(local) && 295 return !redirectionMapping.containsKey(local) &&
297 !scopeInfo.localIsUsedInTryOrSync(local); 296 !scopeInfo.localIsUsedInTryOrSync(local);
298 } 297 }
299 298
300 bool isStoredInClosureField(Local local) { 299 bool isStoredInClosureField(Local local) {
301 assert(local != null); 300 assert(local != null);
302 if (isAccessedDirectly(local)) return false; 301 if (isAccessedDirectly(local)) return false;
303 if (scopeInfo is! ClosureRepresentationInfo) return false; 302 if (scopeInfo is! ClosureRepresentationInfo) return false;
304 FieldEntity redirectTarget = redirectionMapping[local]; 303 FieldEntity redirectTarget = redirectionMapping[local];
304 print(
305 'is stored in closure field $local ${isAccessedDirectly(local)} ${scopeI nfo.runtimeType} ${redirectTarget.runtimeType}');
305 if (redirectTarget == null) return false; 306 if (redirectTarget == null) return false;
306 return redirectTarget is ClosureFieldElement; 307 return redirectTarget is ClosureFieldElement ||
308 redirectTarget is JClosureField;
307 } 309 }
308 310
309 bool isBoxed(Local local) { 311 bool isBoxed(Local local) {
310 if (isAccessedDirectly(local)) return false; 312 if (isAccessedDirectly(local)) return false;
311 if (isStoredInClosureField(local)) return false; 313 if (isStoredInClosureField(local)) return false;
312 return redirectionMapping.containsKey(local); 314 return redirectionMapping.containsKey(local);
313 } 315 }
314 316
315 bool _isUsedInTryOrGenerator(Local local) { 317 bool _isUsedInTryOrGenerator(Local local) {
316 return scopeInfo.localIsUsedInTryOrSync(local); 318 return scopeInfo.localIsUsedInTryOrSync(local);
(...skipping 17 matching lines...) Expand all
334 "$executableContext."); 336 "$executableContext.");
335 } 337 }
336 } 338 }
337 HInstruction value = directLocals[local]; 339 HInstruction value = directLocals[local];
338 if (sourceInformation != null) { 340 if (sourceInformation != null) {
339 value = new HRef(value, sourceInformation); 341 value = new HRef(value, sourceInformation);
340 builder.add(value); 342 builder.add(value);
341 } 343 }
342 return value; 344 return value;
343 } else if (isStoredInClosureField(local)) { 345 } else if (isStoredInClosureField(local)) {
346 print('bbbbbbb $local');
344 ClosureRepresentationInfo closureData = scopeInfo; 347 ClosureRepresentationInfo closureData = scopeInfo;
345 ClosureFieldElement redirect = redirectionMapping[local]; 348 FieldEntity redirect = redirectionMapping[local];
346 HInstruction receiver = readLocal(closureData.closureEntity); 349 HInstruction receiver = readLocal(closureData.closureEntity);
347 TypeMask type = local is BoxLocal 350 TypeMask type = local is BoxLocal
348 ? commonMasks.nonNullType 351 ? commonMasks.nonNullType
349 : getTypeOfCapturedVariable(redirect); 352 : getTypeOfCapturedVariable(redirect);
350 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); 353 HInstruction fieldGet = new HFieldGet(redirect, receiver, type);
351 builder.add(fieldGet); 354 builder.add(fieldGet);
352 return fieldGet..sourceInformation = sourceInformation; 355 return fieldGet..sourceInformation = sourceInformation;
353 } else if (isBoxed(local)) { 356 } else if (isBoxed(local)) {
354 BoxFieldElement redirect = redirectionMapping[local]; 357 FieldEntity redirect = redirectionMapping[local];
358 BoxLocal localBox;
355 // In the function that declares the captured variable the box is 359 // In the function that declares the captured variable the box is
356 // accessed as direct local. Inside the nested closure the box is 360 // accessed as direct local. Inside the nested closure the box is
357 // accessed through a closure-field. 361 // accessed through a closure-field.
358 // Calling [readLocal] makes sure we generate the correct code to get 362 // Calling [readLocal] makes sure we generate the correct code to get
359 // the box. 363 // the box.
364 print("AAAAAAAAAAAAAA $local $redirect ${redirect.runtimeType}");
365 if (redirect is BoxFieldElement) {
366 localBox = redirect.box;
367 } else if (redirect is JRecord) {
368 localBox = redirect.box;
369 }
370 assert(localBox != null);
371
360 HInstruction box = readLocal(redirect.box); 372 HInstruction box = readLocal(redirect.box);
361 HInstruction lookup = 373 HInstruction lookup =
362 new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect)); 374 new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect));
363 builder.add(lookup); 375 builder.add(lookup);
364 return lookup..sourceInformation = sourceInformation; 376 return lookup..sourceInformation = sourceInformation;
365 } else { 377 } else {
366 assert(_isUsedInTryOrGenerator(local)); 378 assert(_isUsedInTryOrGenerator(local));
367 HLocalValue localValue = getLocal(local); 379 HLocalValue localValue = getLocal(local);
368 HInstruction instruction = new HLocalGet( 380 HInstruction instruction = new HLocalGet(
369 local, localValue, commonMasks.dynamicType, sourceInformation); 381 local, localValue, commonMasks.dynamicType, sourceInformation);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 void updateLocal(Local local, HInstruction value, 421 void updateLocal(Local local, HInstruction value,
410 {SourceInformation sourceInformation}) { 422 {SourceInformation sourceInformation}) {
411 if (value is HRef) { 423 if (value is HRef) {
412 HRef ref = value; 424 HRef ref = value;
413 value = ref.value; 425 value = ref.value;
414 } 426 }
415 assert(!isStoredInClosureField(local)); 427 assert(!isStoredInClosureField(local));
416 if (isAccessedDirectly(local)) { 428 if (isAccessedDirectly(local)) {
417 directLocals[local] = value; 429 directLocals[local] = value;
418 } else if (isBoxed(local)) { 430 } else if (isBoxed(local)) {
419 BoxFieldElement redirect = redirectionMapping[local]; 431 FieldEntity redirect = redirectionMapping[local];
432 assert(redirect != null);
433 BoxLocal localBox;
434 if (redirect is BoxFieldElement) {
435 localBox = redirect.box;
436 } else if (redirect is JRecord) {
437 localBox = redirect.box;
438 }
439 assert(localBox != null);
440
420 // The box itself could be captured, or be local. A local variable that 441 // The box itself could be captured, or be local. A local variable that
421 // is captured will be boxed, but the box itself will be a local. 442 // is captured will be boxed, but the box itself will be a local.
422 // Inside the closure the box is stored in a closure-field and cannot 443 // Inside the closure the box is stored in a closure-field and cannot
423 // be accessed directly. 444 // be accessed directly.
424 HInstruction box = readLocal(redirect.box); 445 HInstruction box = readLocal(localBox);
425 builder.add(new HFieldSet(redirect, box, value) 446 builder.add(new HFieldSet(redirect, box, value)
426 ..sourceInformation = sourceInformation); 447 ..sourceInformation = sourceInformation);
427 } else { 448 } else {
428 assert(_isUsedInTryOrGenerator(local)); 449 assert(_isUsedInTryOrGenerator(local));
429 HLocalValue localValue = getLocal(local); 450 HLocalValue localValue = getLocal(local);
430 builder.add(new HLocalSet(local, localValue, value) 451 builder.add(new HLocalSet(local, localValue, value)
431 ..sourceInformation = sourceInformation); 452 ..sourceInformation = sourceInformation);
432 } 453 }
433 } 454 }
434 455
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 // simplicity, we mark the type as an interface type. 657 // simplicity, we mark the type as an interface type.
637 result = new TypeMask.nonNullSubtype(cls, closedWorld); 658 result = new TypeMask.nonNullSubtype(cls, closedWorld);
638 } else { 659 } else {
639 result = new TypeMask.nonNullSubclass(cls, closedWorld); 660 result = new TypeMask.nonNullSubclass(cls, closedWorld);
640 } 661 }
641 cachedTypeOfThis = result; 662 cachedTypeOfThis = result;
642 } 663 }
643 return result; 664 return result;
644 } 665 }
645 666
646 Map<Element, TypeMask> cachedTypesOfCapturedVariables = 667 Map<FieldEntity, TypeMask> cachedTypesOfCapturedVariables =
647 new Map<Element, TypeMask>(); 668 new Map<FieldEntity, TypeMask>();
648 669
649 TypeMask getTypeOfCapturedVariable(FieldElement element) { 670 TypeMask getTypeOfCapturedVariable(FieldEntity element) {
650 return cachedTypesOfCapturedVariables.putIfAbsent(element, () { 671 return cachedTypesOfCapturedVariables.putIfAbsent(element, () {
651 return TypeMaskFactory.inferredTypeForMember( 672 return TypeMaskFactory.inferredTypeForMember(
652 element, _globalInferenceResults); 673 element, _globalInferenceResults);
653 }); 674 });
654 } 675 }
655 676
656 /// Variables stored in the current activation. These variables are 677 /// Variables stored in the current activation. These variables are
657 /// being updated in try/catch blocks, and should be 678 /// being updated in try/catch blocks, and should be
658 /// accessed indirectly through [HLocalGet] and [HLocalSet]. 679 /// accessed indirectly through [HLocalGet] and [HLocalSet].
659 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{}; 680 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{};
(...skipping 13 matching lines...) Expand all
673 final MemberEntity memberContext; 694 final MemberEntity memberContext;
674 695
675 // Avoid slow Object.hashCode. 696 // Avoid slow Object.hashCode.
676 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); 697 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30);
677 static int _nextHashCode = 0; 698 static int _nextHashCode = 0;
678 699
679 SyntheticLocal(this.name, this.executableContext, this.memberContext); 700 SyntheticLocal(this.name, this.executableContext, this.memberContext);
680 701
681 toString() => 'SyntheticLocal($name)'; 702 toString() => 'SyntheticLocal($name)';
682 } 703 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart ('k') | pkg/compiler/lib/src/universe/use.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698