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

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

Issue 2464103002: Introduce ClassLike, MemberLike, FieldLike and FunctionLike (Closed)
Patch Set: Created 4 years, 1 month 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) 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 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
6 import '../common/names.dart' show Selectors; 6 import '../common/names.dart' show Selectors;
7 import '../common/tasks.dart' show CompilerTask; 7 import '../common/tasks.dart' show CompilerTask;
8 import '../compiler.dart' show Compiler; 8 import '../compiler.dart' show Compiler;
9 import '../constants/constant_system.dart'; 9 import '../constants/constant_system.dart';
10 import '../constants/values.dart'; 10 import '../constants/values.dart';
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 if (actualReceiver.isIndexablePrimitive(compiler)) { 325 if (actualReceiver.isIndexablePrimitive(compiler)) {
326 if (actualReceiver.isConstantString()) { 326 if (actualReceiver.isConstantString()) {
327 HConstant constantInput = actualReceiver; 327 HConstant constantInput = actualReceiver;
328 StringConstantValue constant = constantInput.constant; 328 StringConstantValue constant = constantInput.constant;
329 return graph.addConstantInt(constant.length, compiler); 329 return graph.addConstantInt(constant.length, compiler);
330 } else if (actualReceiver.isConstantList()) { 330 } else if (actualReceiver.isConstantList()) {
331 HConstant constantInput = actualReceiver; 331 HConstant constantInput = actualReceiver;
332 ListConstantValue constant = constantInput.constant; 332 ListConstantValue constant = constantInput.constant;
333 return graph.addConstantInt(constant.length, compiler); 333 return graph.addConstantInt(constant.length, compiler);
334 } 334 }
335 Element element = helpers.jsIndexableLength; 335 MemberElement element = helpers.jsIndexableLength;
336 bool isFixed = isFixedLength(actualReceiver.instructionType, compiler); 336 bool isFixed = isFixedLength(actualReceiver.instructionType, compiler);
337 TypeMask actualType = node.instructionType; 337 TypeMask actualType = node.instructionType;
338 ClosedWorld closedWorld = compiler.closedWorld; 338 ClosedWorld closedWorld = compiler.closedWorld;
339 TypeMask resultType = backend.positiveIntType; 339 TypeMask resultType = backend.positiveIntType;
340 // If we already have computed a more specific type, keep that type. 340 // If we already have computed a more specific type, keep that type.
341 if (HInstruction.isInstanceOf( 341 if (HInstruction.isInstanceOf(
342 actualType, helpers.jsUInt31Class, closedWorld)) { 342 actualType, helpers.jsUInt31Class, closedWorld)) {
343 resultType = backend.uint31Type; 343 resultType = backend.uint31Type;
344 } else if (HInstruction.isInstanceOf( 344 } else if (HInstruction.isInstanceOf(
345 actualType, helpers.jsUInt32Class, closedWorld)) { 345 actualType, helpers.jsUInt32Class, closedWorld)) {
(...skipping 30 matching lines...) Expand all
376 HInstruction input = node.inputs[1]; 376 HInstruction input = node.inputs[1];
377 377
378 ClosedWorld world = compiler.closedWorld; 378 ClosedWorld world = compiler.closedWorld;
379 379
380 bool applies(Element element) { 380 bool applies(Element element) {
381 return selector.applies(element) && 381 return selector.applies(element) &&
382 (mask == null || mask.canHit(element, selector, world)); 382 (mask == null || mask.canHit(element, selector, world));
383 } 383 }
384 384
385 if (selector.isCall || selector.isOperator) { 385 if (selector.isCall || selector.isOperator) {
386 Element target; 386 MethodElement target;
387 if (input.isExtendableArray(compiler)) { 387 if (input.isExtendableArray(compiler)) {
388 if (applies(helpers.jsArrayRemoveLast)) { 388 if (applies(helpers.jsArrayRemoveLast)) {
389 target = helpers.jsArrayRemoveLast; 389 target = helpers.jsArrayRemoveLast;
390 } else if (applies(helpers.jsArrayAdd)) { 390 } else if (applies(helpers.jsArrayAdd)) {
391 // The codegen special cases array calls, but does not 391 // The codegen special cases array calls, but does not
392 // inline argument type checks. 392 // inline argument type checks.
393 if (!compiler.options.enableTypeAssertions) { 393 if (!compiler.options.enableTypeAssertions) {
394 target = helpers.jsArrayAdd; 394 target = helpers.jsArrayAdd;
395 } 395 }
396 } 396 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 TypeMask receiverType = node.getDartReceiver(compiler).instructionType; 446 TypeMask receiverType = node.getDartReceiver(compiler).instructionType;
447 Element element = 447 Element element =
448 compiler.closedWorld.locateSingleElement(node.selector, receiverType); 448 compiler.closedWorld.locateSingleElement(node.selector, receiverType);
449 // TODO(ngeoffray): Also fold if it's a getter or variable. 449 // TODO(ngeoffray): Also fold if it's a getter or variable.
450 if (element != null && 450 if (element != null &&
451 element.isFunction 451 element.isFunction
452 // If we found out that the only target is an implicitly called 452 // If we found out that the only target is an implicitly called
453 // [:noSuchMethod:] we just ignore it. 453 // [:noSuchMethod:] we just ignore it.
454 && 454 &&
455 node.selector.applies(element)) { 455 node.selector.applies(element)) {
456 FunctionElement method = element; 456 MethodElement method = element;
457 457
458 if (backend.isNative(method)) { 458 if (backend.isNative(method)) {
459 HInstruction folded = tryInlineNativeMethod(node, method); 459 HInstruction folded = tryInlineNativeMethod(node, method);
460 if (folded != null) return folded; 460 if (folded != null) return folded;
461 } else { 461 } else {
462 // TODO(ngeoffray): If the method has optional parameters, 462 // TODO(ngeoffray): If the method has optional parameters,
463 // we should pass the default values. 463 // we should pass the default values.
464 FunctionSignature parameters = method.functionSignature; 464 FunctionSignature parameters = method.functionSignature;
465 if (parameters.optionalParameterCount == 0 || 465 if (parameters.optionalParameterCount == 0 ||
466 parameters.parameterCount == node.selector.argumentCount) { 466 parameters.parameterCount == node.selector.argumentCount) {
467 node.element = element; 467 node.element = method;
468 } 468 }
469 } 469 }
470 return node; 470 return node;
471 } 471 }
472 472
473 // Replace method calls through fields with a closure call on the value of 473 // Replace method calls through fields with a closure call on the value of
474 // the field. This usually removes the demand for the call-through stub and 474 // the field. This usually removes the demand for the call-through stub and
475 // makes the field load available to further optimization, e.g. LICM. 475 // makes the field load available to further optimization, e.g. LICM.
476 476
477 if (element != null && 477 if (element != null &&
478 element.isField && 478 element.isField &&
479 element.name == node.selector.name) { 479 element.name == node.selector.name) {
480 if (!backend.isNative(element) && !node.isCallOnInterceptor(compiler)) { 480 FieldElement field = element;
481 if (!backend.isNative(field) && !node.isCallOnInterceptor(compiler)) {
481 HInstruction receiver = node.getDartReceiver(compiler); 482 HInstruction receiver = node.getDartReceiver(compiler);
482 TypeMask type = 483 TypeMask type = TypeMaskFactory.inferredTypeForElement(field, compiler);
483 TypeMaskFactory.inferredTypeForElement(element, compiler); 484 HInstruction load = new HFieldGet(field, receiver, type);
484 HInstruction load = new HFieldGet(element, receiver, type);
485 node.block.addBefore(node, load); 485 node.block.addBefore(node, load);
486 Selector callSelector = new Selector.callClosureFrom(node.selector); 486 Selector callSelector = new Selector.callClosureFrom(node.selector);
487 List<HInstruction> inputs = <HInstruction>[load] 487 List<HInstruction> inputs = <HInstruction>[load]
488 ..addAll(node.inputs.skip(node.isInterceptedCall ? 2 : 1)); 488 ..addAll(node.inputs.skip(node.isInterceptedCall ? 2 : 1));
489 HInstruction closureCall = 489 HInstruction closureCall =
490 new HInvokeClosure(callSelector, inputs, node.instructionType) 490 new HInvokeClosure(callSelector, inputs, node.instructionType)
491 ..sourceInformation = node.sourceInformation; 491 ..sourceInformation = node.sourceInformation;
492 node.block.addAfter(load, closureCall); 492 node.block.addAfter(load, closureCall);
493 return closureCall; 493 return closureCall;
494 } 494 }
495 } 495 }
496 496
497 return node; 497 return node;
498 } 498 }
499 499
500 HInstruction tryInlineNativeMethod( 500 HInstruction tryInlineNativeMethod(
501 HInvokeDynamicMethod node, FunctionElement method) { 501 HInvokeDynamicMethod node, MethodElement method) {
502 // Enable direct calls to a native method only if we don't run in checked 502 // Enable direct calls to a native method only if we don't run in checked
503 // mode, where the Dart version may have type annotations on parameters and 503 // mode, where the Dart version may have type annotations on parameters and
504 // return type that it should check. 504 // return type that it should check.
505 // Also check that the parameters are not functions: it's the callee that 505 // Also check that the parameters are not functions: it's the callee that
506 // will translate them to JS functions. 506 // will translate them to JS functions.
507 // 507 //
508 // TODO(ngeoffray): There are some cases where we could still inline in 508 // TODO(ngeoffray): There are some cases where we could still inline in
509 // checked mode if we know the arguments have the right type. And we could 509 // checked mode if we know the arguments have the right type. And we could
510 // do the closure conversion as well as the return type annotation check. 510 // do the closure conversion as well as the return type annotation check.
511 511
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 HInstruction removeIfCheckAlwaysSucceeds(HCheck node, TypeMask checkedType) { 818 HInstruction removeIfCheckAlwaysSucceeds(HCheck node, TypeMask checkedType) {
819 ClosedWorld closedWorld = compiler.closedWorld; 819 ClosedWorld closedWorld = compiler.closedWorld;
820 if (checkedType.containsAll(closedWorld)) return node; 820 if (checkedType.containsAll(closedWorld)) return node;
821 HInstruction input = node.checkedInput; 821 HInstruction input = node.checkedInput;
822 TypeMask inputType = input.instructionType; 822 TypeMask inputType = input.instructionType;
823 return inputType.isInMask(checkedType, closedWorld) ? input : node; 823 return inputType.isInMask(checkedType, closedWorld) ? input : node;
824 } 824 }
825 825
826 HInstruction removeCheck(HCheck node) => node.checkedInput; 826 HInstruction removeCheck(HCheck node) => node.checkedInput;
827 827
828 VariableElement findConcreteFieldForDynamicAccess( 828 FieldElement findConcreteFieldForDynamicAccess(
829 HInstruction receiver, Selector selector) { 829 HInstruction receiver, Selector selector) {
830 TypeMask receiverType = receiver.instructionType; 830 TypeMask receiverType = receiver.instructionType;
831 return compiler.closedWorld.locateSingleField(selector, receiverType); 831 return compiler.closedWorld.locateSingleField(selector, receiverType);
832 } 832 }
833 833
834 HInstruction visitFieldGet(HFieldGet node) { 834 HInstruction visitFieldGet(HFieldGet node) {
835 if (node.isNullCheck) return node; 835 if (node.isNullCheck) return node;
836 var receiver = node.receiver; 836 var receiver = node.receiver;
837 if (node.element == helpers.jsIndexableLength) { 837 if (node.element == helpers.jsIndexableLength) {
838 if (graph.allocatedFixedLists.contains(receiver)) { 838 if (graph.allocatedFixedLists.contains(receiver)) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 return node; 893 return node;
894 } 894 }
895 895
896 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) { 896 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
897 propagateConstantValueToUses(node); 897 propagateConstantValueToUses(node);
898 if (node.isInterceptedCall) { 898 if (node.isInterceptedCall) {
899 HInstruction folded = handleInterceptedCall(node); 899 HInstruction folded = handleInterceptedCall(node);
900 if (folded != node) return folded; 900 if (folded != node) return folded;
901 } 901 }
902 HInstruction receiver = node.getDartReceiver(compiler); 902 HInstruction receiver = node.getDartReceiver(compiler);
903 Element field = findConcreteFieldForDynamicAccess(receiver, node.selector); 903 FieldElement field =
904 findConcreteFieldForDynamicAccess(receiver, node.selector);
904 if (field != null) return directFieldGet(receiver, field); 905 if (field != null) return directFieldGet(receiver, field);
905 906
906 if (node.element == null) { 907 if (node.element == null) {
907 Element element = compiler.closedWorld 908 MemberElement element = compiler.closedWorld
908 .locateSingleElement(node.selector, receiver.instructionType); 909 .locateSingleElement(node.selector, receiver.instructionType);
909 if (element != null && element.name == node.selector.name) { 910 if (element != null && element.name == node.selector.name) {
910 node.element = element; 911 node.element = element;
911 if (element.isFunction) { 912 if (element.isFunction) {
912 // A property extraction getter, aka a tear-off. 913 // A property extraction getter, aka a tear-off.
913 node.sideEffects.clearAllDependencies(); 914 node.sideEffects.clearAllDependencies();
914 node.sideEffects.clearAllSideEffects(); 915 node.sideEffects.clearAllSideEffects();
915 node.setUseGvn(); // We don't care about identity of tear-offs. 916 node.setUseGvn(); // We don't care about identity of tear-offs.
916 } 917 }
917 } 918 }
918 } 919 }
919 return node; 920 return node;
920 } 921 }
921 922
922 HInstruction directFieldGet(HInstruction receiver, Element field) { 923 HInstruction directFieldGet(HInstruction receiver, FieldElement field) {
923 bool isAssignable = !compiler.closedWorld.fieldNeverChanges(field); 924 bool isAssignable = !compiler.closedWorld.fieldNeverChanges(field);
924 925
925 TypeMask type; 926 TypeMask type;
926 if (backend.isNative(field.enclosingClass)) { 927 if (backend.isNative(field.enclosingClass)) {
927 type = TypeMaskFactory.fromNativeBehavior( 928 type = TypeMaskFactory.fromNativeBehavior(
928 backend.getNativeFieldLoadBehavior(field), compiler); 929 backend.getNativeFieldLoadBehavior(field), compiler);
929 } else { 930 } else {
930 type = TypeMaskFactory.inferredTypeForElement(field, compiler); 931 type = TypeMaskFactory.inferredTypeForElement(field, compiler);
931 } 932 }
932 933
933 return new HFieldGet(field, receiver, type, isAssignable: isAssignable); 934 return new HFieldGet(field, receiver, type, isAssignable: isAssignable);
934 } 935 }
935 936
936 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 937 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
937 if (node.isInterceptedCall) { 938 if (node.isInterceptedCall) {
938 HInstruction folded = handleInterceptedCall(node); 939 HInstruction folded = handleInterceptedCall(node);
939 if (folded != node) return folded; 940 if (folded != node) return folded;
940 } 941 }
941 942
942 HInstruction receiver = node.getDartReceiver(compiler); 943 HInstruction receiver = node.getDartReceiver(compiler);
943 VariableElement field = 944 FieldElement field =
944 findConcreteFieldForDynamicAccess(receiver, node.selector); 945 findConcreteFieldForDynamicAccess(receiver, node.selector);
945 if (field == null || !field.isAssignable) return node; 946 if (field == null || !field.isAssignable) return node;
946 // Use [:node.inputs.last:] in case the call follows the 947 // Use [:node.inputs.last:] in case the call follows the
947 // interceptor calling convention, but is not a call on an 948 // interceptor calling convention, but is not a call on an
948 // interceptor. 949 // interceptor.
949 HInstruction value = node.inputs.last; 950 HInstruction value = node.inputs.last;
950 if (compiler.options.enableTypeAssertions) { 951 if (compiler.options.enableTypeAssertions) {
951 DartType type = field.type; 952 DartType type = field.type;
952 if (!type.treatAsRaw || type.isTypeVariable) { 953 if (!type.treatAsRaw || type.isTypeVariable) {
953 // We cannot generate the correct type representation here, so don't 954 // We cannot generate the correct type representation here, so don't
954 // inline this access. 955 // inline this access.
955 return node; 956 return node;
956 } 957 }
957 HInstruction other = 958 HInstruction other =
958 value.convertType(compiler, type, HTypeConversion.CHECKED_MODE_CHECK); 959 value.convertType(compiler, type, HTypeConversion.CHECKED_MODE_CHECK);
959 if (other != value) { 960 if (other != value) {
960 node.block.addBefore(node, other); 961 node.block.addBefore(node, other);
961 value = other; 962 value = other;
962 } 963 }
963 } 964 }
964 return new HFieldSet(field, receiver, value); 965 return new HFieldSet(field, receiver, value);
965 } 966 }
966 967
967 HInstruction visitInvokeStatic(HInvokeStatic node) { 968 HInstruction visitInvokeStatic(HInvokeStatic node) {
968 propagateConstantValueToUses(node); 969 propagateConstantValueToUses(node);
969 Element element = node.element; 970 MemberElement element = node.element;
970 971
971 if (element == backend.helpers.checkConcurrentModificationError) { 972 if (element == backend.helpers.checkConcurrentModificationError) {
972 if (node.inputs.length == 2) { 973 if (node.inputs.length == 2) {
973 HInstruction firstArgument = node.inputs[0]; 974 HInstruction firstArgument = node.inputs[0];
974 if (firstArgument is HConstant) { 975 if (firstArgument is HConstant) {
975 HConstant constant = firstArgument; 976 HConstant constant = firstArgument;
976 if (constant.constant.isTrue) return constant; 977 if (constant.constant.isTrue) return constant;
977 } 978 }
978 } 979 }
979 } else if (element == backend.helpers.checkInt) { 980 } else if (element == backend.helpers.checkInt) {
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 index = insertBoundsCheck(node, node.receiver, index); 1332 index = insertBoundsCheck(node, node.receiver, index);
1332 } 1333 }
1333 1334
1334 void visitIndexAssign(HIndexAssign node) { 1335 void visitIndexAssign(HIndexAssign node) {
1335 if (boundsChecked.contains(node)) return; 1336 if (boundsChecked.contains(node)) return;
1336 HInstruction index = node.index; 1337 HInstruction index = node.index;
1337 index = insertBoundsCheck(node, node.receiver, index); 1338 index = insertBoundsCheck(node, node.receiver, index);
1338 } 1339 }
1339 1340
1340 void visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 1341 void visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
1341 Element element = node.element; 1342 MemberElement element = node.element;
1342 if (node.isInterceptedCall) return; 1343 if (node.isInterceptedCall) return;
1343 if (element != helpers.jsArrayRemoveLast) return; 1344 if (element != helpers.jsArrayRemoveLast) return;
1344 if (boundsChecked.contains(node)) return; 1345 if (boundsChecked.contains(node)) return;
1345 // `0` is the index we want to check, but we want to report `-1`, as if we 1346 // `0` is the index we want to check, but we want to report `-1`, as if we
1346 // executed `a[a.length-1]` 1347 // executed `a[a.length-1]`
1347 HBoundsCheck check = insertBoundsCheck( 1348 HBoundsCheck check = insertBoundsCheck(
1348 node, node.receiver, graph.addConstantInt(0, backend.compiler)); 1349 node, node.receiver, graph.addConstantInt(0, backend.compiler));
1349 HInstruction minusOne = graph.addConstantInt(-1, backend.compiler); 1350 HInstruction minusOne = graph.addConstantInt(-1, backend.compiler);
1350 check.inputs.add(minusOne); 1351 check.inputs.add(minusOne);
1351 minusOne.usedBy.add(check); 1352 minusOne.usedBy.add(check);
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after
2155 2156
2156 for (HBasicBlock block in falseTargets) { 2157 for (HBasicBlock block in falseTargets) {
2157 insertTypePropagationForDominatedUsers(block, input, nonNullType); 2158 insertTypePropagationForDominatedUsers(block, input, nonNullType);
2158 } 2159 }
2159 // We don't strengthen the known-true references. It doesn't happen often 2160 // We don't strengthen the known-true references. It doesn't happen often
2160 // and we don't want "if (x==null) return x;" to convert between JavaScript 2161 // and we don't want "if (x==null) return x;" to convert between JavaScript
2161 // 'null' and 'undefined'. 2162 // 'null' and 'undefined'.
2162 } 2163 }
2163 2164
2164 collectTargets(HInstruction instruction, List<HBasicBlock> trueTargets, 2165 collectTargets(HInstruction instruction, List<HBasicBlock> trueTargets,
2165 List<HBasicBlock> falseTargets) { 2166 List<HBasicBlock> falseTargets) {
2166 for (HInstruction user in instruction.usedBy) { 2167 for (HInstruction user in instruction.usedBy) {
2167 if (user is HIf) { 2168 if (user is HIf) {
2168 trueTargets?.add(user.thenBlock); 2169 trueTargets?.add(user.thenBlock);
2169 falseTargets?.add(user.elseBlock); 2170 falseTargets?.add(user.elseBlock);
2170 } else if (user is HNot) { 2171 } else if (user is HNot) {
2171 collectTargets(user, falseTargets, trueTargets); 2172 collectTargets(user, falseTargets, trueTargets);
2172 } else if (user is HPhi) { 2173 } else if (user is HPhi) {
2173 List<HInstruction> inputs = user.inputs; 2174 List<HInstruction> inputs = user.inputs;
2174 if (inputs.length == 2) { 2175 if (inputs.length == 2) {
2175 assert(inputs.contains(instruction)); 2176 assert(inputs.contains(instruction));
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2252 HInstruction instruction = block.first; 2253 HInstruction instruction = block.first;
2253 while (instruction != null) { 2254 while (instruction != null) {
2254 HInstruction next = instruction.next; 2255 HInstruction next = instruction.next;
2255 instruction.accept(this); 2256 instruction.accept(this);
2256 instruction = next; 2257 instruction = next;
2257 } 2258 }
2258 } 2259 }
2259 2260
2260 void visitFieldGet(HFieldGet instruction) { 2261 void visitFieldGet(HFieldGet instruction) {
2261 if (instruction.isNullCheck) return; 2262 if (instruction.isNullCheck) return;
2262 Element element = instruction.element; 2263 MemberElement element = instruction.element;
2263 HInstruction receiver = instruction.getDartReceiver(compiler).nonCheck(); 2264 HInstruction receiver = instruction.getDartReceiver(compiler).nonCheck();
2264 HInstruction existing = memorySet.lookupFieldValue(element, receiver); 2265 HInstruction existing = memorySet.lookupFieldValue(element, receiver);
2265 if (existing != null) { 2266 if (existing != null) {
2266 instruction.block.rewriteWithBetterUser(instruction, existing); 2267 instruction.block.rewriteWithBetterUser(instruction, existing);
2267 instruction.block.remove(instruction); 2268 instruction.block.remove(instruction);
2268 } else { 2269 } else {
2269 memorySet.registerFieldValue(element, receiver, instruction); 2270 memorySet.registerFieldValue(element, receiver, instruction);
2270 } 2271 }
2271 } 2272 }
2272 2273
2273 void visitFieldSet(HFieldSet instruction) { 2274 void visitFieldSet(HFieldSet instruction) {
2274 HInstruction receiver = instruction.getDartReceiver(compiler).nonCheck(); 2275 HInstruction receiver = instruction.getDartReceiver(compiler).nonCheck();
2275 memorySet.registerFieldValueUpdate( 2276 memorySet.registerFieldValueUpdate(
2276 instruction.element, receiver, instruction.inputs.last); 2277 instruction.element, receiver, instruction.inputs.last);
2277 } 2278 }
2278 2279
2279 void visitCreate(HCreate instruction) { 2280 void visitCreate(HCreate instruction) {
2280 memorySet.registerAllocation(instruction); 2281 memorySet.registerAllocation(instruction);
2281 if (shouldTrackInitialValues(instruction)) { 2282 if (shouldTrackInitialValues(instruction)) {
2282 int argumentIndex = 0; 2283 int argumentIndex = 0;
2283 instruction.element.forEachInstanceField((_, Element member) { 2284 instruction.element.forEachInstanceField((_, FieldElement member) {
2284 if (compiler.elementHasCompileTimeError(member)) return; 2285 if (compiler.elementHasCompileTimeError(member)) return;
2285 memorySet.registerFieldValue( 2286 memorySet.registerFieldValue(
2286 member, instruction, instruction.inputs[argumentIndex++]); 2287 member, instruction, instruction.inputs[argumentIndex++]);
2287 }, includeSuperAndInjectedMembers: true); 2288 }, includeSuperAndInjectedMembers: true);
2288 } 2289 }
2289 // In case this instruction has as input non-escaping objects, we 2290 // In case this instruction has as input non-escaping objects, we
2290 // need to mark these objects as escaping. 2291 // need to mark these objects as escaping.
2291 memorySet.killAffectedBy(instruction); 2292 memorySet.killAffectedBy(instruction);
2292 } 2293 }
2293 2294
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2330 } 2331 }
2331 2332
2332 void visitInstruction(HInstruction instruction) { 2333 void visitInstruction(HInstruction instruction) {
2333 if (instruction.isAllocation) { 2334 if (instruction.isAllocation) {
2334 memorySet.registerAllocation(instruction); 2335 memorySet.registerAllocation(instruction);
2335 } 2336 }
2336 memorySet.killAffectedBy(instruction); 2337 memorySet.killAffectedBy(instruction);
2337 } 2338 }
2338 2339
2339 void visitLazyStatic(HLazyStatic instruction) { 2340 void visitLazyStatic(HLazyStatic instruction) {
2340 handleStaticLoad(instruction.element, instruction); 2341 FieldElement field = instruction.element;
Siggi Cherem (dart-lang) 2016/11/03 00:52:30 is the idea to convert all of the uses of elements
Johnni Winther 2016/11/03 09:55:06 Yes.
2342 handleStaticLoad(field, instruction);
2341 } 2343 }
2342 2344
2343 void handleStaticLoad(Element element, HInstruction instruction) { 2345 void handleStaticLoad(MemberElement element, HInstruction instruction) {
2344 HInstruction existing = memorySet.lookupFieldValue(element, null); 2346 HInstruction existing = memorySet.lookupFieldValue(element, null);
2345 if (existing != null) { 2347 if (existing != null) {
2346 instruction.block.rewriteWithBetterUser(instruction, existing); 2348 instruction.block.rewriteWithBetterUser(instruction, existing);
2347 instruction.block.remove(instruction); 2349 instruction.block.remove(instruction);
2348 } else { 2350 } else {
2349 memorySet.registerFieldValue(element, null, instruction); 2351 memorySet.registerFieldValue(element, null, instruction);
2350 } 2352 }
2351 } 2353 }
2352 2354
2353 void visitStatic(HStatic instruction) { 2355 void visitStatic(HStatic instruction) {
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
2480 void registerAllocation(HInstruction instruction) { 2482 void registerAllocation(HInstruction instruction) {
2481 assert(instruction == instruction.nonCheck()); 2483 assert(instruction == instruction.nonCheck());
2482 nonEscapingReceivers.add(instruction); 2484 nonEscapingReceivers.add(instruction);
2483 } 2485 }
2484 2486
2485 /** 2487 /**
2486 * Sets `receiver.element` to contain [value]. Kills all potential places that 2488 * Sets `receiver.element` to contain [value]. Kills all potential places that
2487 * may be affected by this update. 2489 * may be affected by this update.
2488 */ 2490 */
2489 void registerFieldValueUpdate( 2491 void registerFieldValueUpdate(
2490 Element element, HInstruction receiver, HInstruction value) { 2492 MemberElement element, HInstruction receiver, HInstruction value) {
2491 assert(receiver == null || receiver == receiver.nonCheck()); 2493 assert(receiver == null || receiver == receiver.nonCheck());
2492 if (backend.isNative(element)) { 2494 if (backend.isNative(element)) {
2493 return; // TODO(14955): Remove this restriction? 2495 return; // TODO(14955): Remove this restriction?
2494 } 2496 }
2495 // [value] is being set in some place in memory, we remove it from 2497 // [value] is being set in some place in memory, we remove it from
2496 // the non-escaping set. 2498 // the non-escaping set.
2497 nonEscapingReceivers.remove(value.nonCheck()); 2499 nonEscapingReceivers.remove(value.nonCheck());
2498 Map<HInstruction, HInstruction> map = 2500 Map<HInstruction, HInstruction> map =
2499 fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{}); 2501 fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{});
2500 map.forEach((key, value) { 2502 map.forEach((key, value) {
2501 if (mayAlias(receiver, key)) map[key] = null; 2503 if (mayAlias(receiver, key)) map[key] = null;
2502 }); 2504 });
2503 map[receiver] = value; 2505 map[receiver] = value;
2504 } 2506 }
2505 2507
2506 /** 2508 /**
2507 * Registers that `receiver.element` is now [value]. 2509 * Registers that `receiver.element` is now [value].
2508 */ 2510 */
2509 void registerFieldValue( 2511 void registerFieldValue(
2510 Element element, HInstruction receiver, HInstruction value) { 2512 MemberElement element, HInstruction receiver, HInstruction value) {
2511 assert(receiver == null || receiver == receiver.nonCheck()); 2513 assert(receiver == null || receiver == receiver.nonCheck());
2512 if (backend.isNative(element)) { 2514 if (backend.isNative(element)) {
2513 return; // TODO(14955): Remove this restriction? 2515 return; // TODO(14955): Remove this restriction?
2514 } 2516 }
2515 Map<HInstruction, HInstruction> map = 2517 Map<HInstruction, HInstruction> map =
2516 fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{}); 2518 fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{});
2517 map[receiver] = value; 2519 map[receiver] = value;
2518 } 2520 }
2519 2521
2520 /** 2522 /**
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
2718 2720
2719 keyedValues.forEach((receiver, values) { 2721 keyedValues.forEach((receiver, values) {
2720 result.keyedValues[receiver] = 2722 result.keyedValues[receiver] =
2721 new Map<HInstruction, HInstruction>.from(values); 2723 new Map<HInstruction, HInstruction>.from(values);
2722 }); 2724 });
2723 2725
2724 result.nonEscapingReceivers.addAll(nonEscapingReceivers); 2726 result.nonEscapingReceivers.addAll(nonEscapingReceivers);
2725 return result; 2727 return result;
2726 } 2728 }
2727 } 2729 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698