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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/optimize.dart

Issue 266913017: Convert property methods into getters. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 6 years, 7 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
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 part of ssa; 5 part of ssa;
6 6
7 abstract class OptimizationPhase { 7 abstract class OptimizationPhase {
8 String get name; 8 String get name;
9 void visitGraph(HGraph graph); 9 void visitGraph(HGraph graph);
10 } 10 }
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 } 258 }
259 259
260 // Try converting the instruction to a builtin instruction. 260 // Try converting the instruction to a builtin instruction.
261 HInstruction instruction = 261 HInstruction instruction =
262 node.specializer.tryConvertToBuiltin(node, compiler); 262 node.specializer.tryConvertToBuiltin(node, compiler);
263 if (instruction != null) return instruction; 263 if (instruction != null) return instruction;
264 264
265 Selector selector = node.selector; 265 Selector selector = node.selector;
266 HInstruction input = node.inputs[1]; 266 HInstruction input = node.inputs[1];
267 267
268 if (selector.isCall() || selector.isOperator()) { 268 if (selector.isCall || selector.isOperator) {
269 Element target; 269 Element target;
270 if (input.isExtendableArray(compiler)) { 270 if (input.isExtendableArray(compiler)) {
271 if (selector.applies(backend.jsArrayRemoveLast, compiler)) { 271 if (selector.applies(backend.jsArrayRemoveLast, compiler)) {
272 target = backend.jsArrayRemoveLast; 272 target = backend.jsArrayRemoveLast;
273 } else if (selector.applies(backend.jsArrayAdd, compiler)) { 273 } else if (selector.applies(backend.jsArrayAdd, compiler)) {
274 // The codegen special cases array calls, but does not 274 // The codegen special cases array calls, but does not
275 // inline argument type checks. 275 // inline argument type checks.
276 if (!compiler.enableTypeAssertions) { 276 if (!compiler.enableTypeAssertions) {
277 target = backend.jsArrayAdd; 277 target = backend.jsArrayAdd;
278 } 278 }
(...skipping 26 matching lines...) Expand all
305 // HInvokeDynamicMethod and not create a HForeign because 305 // HInvokeDynamicMethod and not create a HForeign because
306 // HForeign is too opaque for the SsaCheckInserter (that adds a 306 // HForeign is too opaque for the SsaCheckInserter (that adds a
307 // bounds check on removeLast). Once we start inlining, the 307 // bounds check on removeLast). Once we start inlining, the
308 // bounds check will become explicit, so we won't need this 308 // bounds check will become explicit, so we won't need this
309 // optimization. 309 // optimization.
310 HInvokeDynamicMethod result = new HInvokeDynamicMethod( 310 HInvokeDynamicMethod result = new HInvokeDynamicMethod(
311 node.selector, node.inputs.sublist(1), node.instructionType); 311 node.selector, node.inputs.sublist(1), node.instructionType);
312 result.element = target; 312 result.element = target;
313 return result; 313 return result;
314 } 314 }
315 } else if (selector.isGetter()) { 315 } else if (selector.isGetter) {
316 if (selector.asUntyped.applies(backend.jsIndexableLength, compiler)) { 316 if (selector.asUntyped.applies(backend.jsIndexableLength, compiler)) {
317 HInstruction optimized = tryOptimizeLengthInterceptedGetter(node); 317 HInstruction optimized = tryOptimizeLengthInterceptedGetter(node);
318 if (optimized != null) return optimized; 318 if (optimized != null) return optimized;
319 } 319 }
320 } 320 }
321 321
322 return node; 322 return node;
323 } 323 }
324 324
325 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 325 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
326 if (node.isInterceptedCall) { 326 if (node.isInterceptedCall) {
327 HInstruction folded = handleInterceptedCall(node); 327 HInstruction folded = handleInterceptedCall(node);
328 if (folded != node) return folded; 328 if (folded != node) return folded;
329 } 329 }
330 330
331 TypeMask receiverType = node.getDartReceiver(compiler).instructionType; 331 TypeMask receiverType = node.getDartReceiver(compiler).instructionType;
332 Selector selector = new TypedSelector(receiverType, node.selector); 332 Selector selector = new TypedSelector(receiverType, node.selector);
333 Element element = compiler.world.locateSingleElement(selector); 333 Element element = compiler.world.locateSingleElement(selector);
334 // TODO(ngeoffray): Also fold if it's a getter or variable. 334 // TODO(ngeoffray): Also fold if it's a getter or variable.
335 if (element != null 335 if (element != null
336 && element.isFunction() 336 && element.isFunction
337 // If we found out that the only target is a [:noSuchMethod:], 337 // If we found out that the only target is a [:noSuchMethod:],
338 // we just ignore it. 338 // we just ignore it.
339 && element.name == selector.name) { 339 && element.name == selector.name) {
340 FunctionElement method = element; 340 FunctionElement method = element;
341 341
342 if (method.isNative()) { 342 if (method.isNative) {
343 HInstruction folded = tryInlineNativeMethod(node, method); 343 HInstruction folded = tryInlineNativeMethod(node, method);
344 if (folded != null) return folded; 344 if (folded != null) return folded;
345 } else { 345 } else {
346 // TODO(ngeoffray): If the method has optional parameters, 346 // TODO(ngeoffray): If the method has optional parameters,
347 // we should pass the default values. 347 // we should pass the default values.
348 FunctionSignature parameters = method.functionSignature; 348 FunctionSignature parameters = method.functionSignature;
349 if (parameters.optionalParameterCount == 0 349 if (parameters.optionalParameterCount == 0
350 || parameters.parameterCount == node.selector.argumentCount) { 350 || parameters.parameterCount == node.selector.argumentCount) {
351 node.element = element; 351 node.element = element;
352 } 352 }
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 simplifyCondition(node.elseBlock, condition, isNegated); 570 simplifyCondition(node.elseBlock, condition, isNegated);
571 return node; 571 return node;
572 } 572 }
573 573
574 HInstruction visitIs(HIs node) { 574 HInstruction visitIs(HIs node) {
575 DartType type = node.typeExpression; 575 DartType type = node.typeExpression;
576 Element element = type.element; 576 Element element = type.element;
577 577
578 if (!node.isRawCheck) { 578 if (!node.isRawCheck) {
579 return node; 579 return node;
580 } else if (element.isTypedef()) { 580 } else if (element.isTypedef) {
581 return node; 581 return node;
582 } else if (element == compiler.functionClass) { 582 } else if (element == compiler.functionClass) {
583 return node; 583 return node;
584 } 584 }
585 585
586 if (element == compiler.objectClass || type.treatAsDynamic) { 586 if (element == compiler.objectClass || type.treatAsDynamic) {
587 return graph.addConstantBool(true, compiler); 587 return graph.addConstantBool(true, compiler);
588 } 588 }
589 589
590 HInstruction expression = node.expression; 590 HInstruction expression = node.expression;
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 Element field = findConcreteFieldForDynamicAccess(receiver, node.selector); 736 Element field = findConcreteFieldForDynamicAccess(receiver, node.selector);
737 if (field == null) return node; 737 if (field == null) return node;
738 return directFieldGet(receiver, field); 738 return directFieldGet(receiver, field);
739 } 739 }
740 740
741 HInstruction directFieldGet(HInstruction receiver, Element field) { 741 HInstruction directFieldGet(HInstruction receiver, Element field) {
742 ast.Modifiers modifiers = field.modifiers; 742 ast.Modifiers modifiers = field.modifiers;
743 bool isAssignable = !compiler.world.fieldNeverChanges(field); 743 bool isAssignable = !compiler.world.fieldNeverChanges(field);
744 744
745 TypeMask type; 745 TypeMask type;
746 if (field.getEnclosingClass().isNative()) { 746 if (field.enclosingClass.isNative) {
747 type = TypeMaskFactory.fromNativeBehavior( 747 type = TypeMaskFactory.fromNativeBehavior(
748 native.NativeBehavior.ofFieldLoad(field, compiler), 748 native.NativeBehavior.ofFieldLoad(field, compiler),
749 compiler); 749 compiler);
750 } else { 750 } else {
751 type = TypeMaskFactory.inferredTypeForElement(field, compiler); 751 type = TypeMaskFactory.inferredTypeForElement(field, compiler);
752 } 752 }
753 753
754 return new HFieldGet( 754 return new HFieldGet(
755 field, receiver, type, isAssignable: isAssignable); 755 field, receiver, type, isAssignable: isAssignable);
756 } 756 }
757 757
758 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 758 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
759 if (node.isInterceptedCall) { 759 if (node.isInterceptedCall) {
760 HInstruction folded = handleInterceptedCall(node); 760 HInstruction folded = handleInterceptedCall(node);
761 if (folded != node) return folded; 761 if (folded != node) return folded;
762 } 762 }
763 763
764 HInstruction receiver = node.getDartReceiver(compiler); 764 HInstruction receiver = node.getDartReceiver(compiler);
765 VariableElement field = 765 VariableElement field =
766 findConcreteFieldForDynamicAccess(receiver, node.selector); 766 findConcreteFieldForDynamicAccess(receiver, node.selector);
767 if (field == null || !field.isAssignable()) return node; 767 if (field == null || !field.isAssignable) return node;
768 // Use [:node.inputs.last:] in case the call follows the 768 // Use [:node.inputs.last:] in case the call follows the
769 // interceptor calling convention, but is not a call on an 769 // interceptor calling convention, but is not a call on an
770 // interceptor. 770 // interceptor.
771 HInstruction value = node.inputs.last; 771 HInstruction value = node.inputs.last;
772 if (compiler.enableTypeAssertions) { 772 if (compiler.enableTypeAssertions) {
773 DartType type = field.type; 773 DartType type = field.type;
774 if (!type.treatAsRaw || type.kind == TypeKind.TYPE_VARIABLE) { 774 if (!type.treatAsRaw || type.kind == TypeKind.TYPE_VARIABLE) {
775 // We cannot generate the correct type representation here, so don't 775 // We cannot generate the correct type representation here, so don't
776 // inline this access. 776 // inline this access.
777 return node; 777 return node;
(...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 dominatedUsers.forEach((HInstruction user) { 1597 dominatedUsers.forEach((HInstruction user) {
1598 user.changeUse(input, newInput); 1598 user.changeUse(input, newInput);
1599 }); 1599 });
1600 } 1600 }
1601 1601
1602 void visitIs(HIs instruction) { 1602 void visitIs(HIs instruction) {
1603 DartType type = instruction.typeExpression; 1603 DartType type = instruction.typeExpression;
1604 Element element = type.element; 1604 Element element = type.element;
1605 if (!instruction.isRawCheck) { 1605 if (!instruction.isRawCheck) {
1606 return; 1606 return;
1607 } else if (element.isTypedef()) { 1607 } else if (element.isTypedef) {
1608 return; 1608 return;
1609 } 1609 }
1610 1610
1611 List<HInstruction> ifUsers = <HInstruction>[]; 1611 List<HInstruction> ifUsers = <HInstruction>[];
1612 List<HInstruction> notIfUsers = <HInstruction>[]; 1612 List<HInstruction> notIfUsers = <HInstruction>[];
1613 1613
1614 collectIfUsers(instruction, ifUsers, notIfUsers); 1614 collectIfUsers(instruction, ifUsers, notIfUsers);
1615 1615
1616 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; 1616 if (ifUsers.isEmpty && notIfUsers.isEmpty) return;
1617 1617
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
1904 nonEscapingReceivers.add(instruction); 1904 nonEscapingReceivers.add(instruction);
1905 } 1905 }
1906 1906
1907 /** 1907 /**
1908 * Sets `receiver.element` to contain [value]. Kills all potential 1908 * Sets `receiver.element` to contain [value]. Kills all potential
1909 * places that may be affected by this update. 1909 * places that may be affected by this update.
1910 */ 1910 */
1911 void registerFieldValueUpdate(Element element, 1911 void registerFieldValueUpdate(Element element,
1912 HInstruction receiver, 1912 HInstruction receiver,
1913 HInstruction value) { 1913 HInstruction value) {
1914 if (element.isNative()) return; // TODO(14955): Remove this restriction? 1914 if (element.isNative) return; // TODO(14955): Remove this restriction?
1915 // [value] is being set in some place in memory, we remove it from 1915 // [value] is being set in some place in memory, we remove it from
1916 // the non-escaping set. 1916 // the non-escaping set.
1917 nonEscapingReceivers.remove(value); 1917 nonEscapingReceivers.remove(value);
1918 Map<HInstruction, HInstruction> map = fieldValues.putIfAbsent( 1918 Map<HInstruction, HInstruction> map = fieldValues.putIfAbsent(
1919 element, () => <HInstruction, HInstruction> {}); 1919 element, () => <HInstruction, HInstruction> {});
1920 map.forEach((key, value) { 1920 map.forEach((key, value) {
1921 if (mayAlias(receiver, key)) map[key] = null; 1921 if (mayAlias(receiver, key)) map[key] = null;
1922 }); 1922 });
1923 map[receiver] = value; 1923 map[receiver] = value;
1924 } 1924 }
1925 1925
1926 /** 1926 /**
1927 * Registers that `receiver.element` is now [value]. 1927 * Registers that `receiver.element` is now [value].
1928 */ 1928 */
1929 void registerFieldValue(Element element, 1929 void registerFieldValue(Element element,
1930 HInstruction receiver, 1930 HInstruction receiver,
1931 HInstruction value) { 1931 HInstruction value) {
1932 if (element.isNative()) return; // TODO(14955): Remove this restriction? 1932 if (element.isNative) return; // TODO(14955): Remove this restriction?
1933 Map<HInstruction, HInstruction> map = fieldValues.putIfAbsent( 1933 Map<HInstruction, HInstruction> map = fieldValues.putIfAbsent(
1934 element, () => <HInstruction, HInstruction> {}); 1934 element, () => <HInstruction, HInstruction> {});
1935 map[receiver] = value; 1935 map[receiver] = value;
1936 } 1936 }
1937 1937
1938 /** 1938 /**
1939 * Returns the value stored in `receiver.element`. Returns null if 1939 * Returns the value stored in `receiver.element`. Returns null if
1940 * we don't know. 1940 * we don't know.
1941 */ 1941 */
1942 HInstruction lookupFieldValue(Element element, HInstruction receiver) { 1942 HInstruction lookupFieldValue(Element element, HInstruction receiver) {
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
2116 2116
2117 keyedValues.forEach((receiver, values) { 2117 keyedValues.forEach((receiver, values) {
2118 result.keyedValues[receiver] = 2118 result.keyedValues[receiver] =
2119 new Map<HInstruction, HInstruction>.from(values); 2119 new Map<HInstruction, HInstruction>.from(values);
2120 }); 2120 });
2121 2121
2122 result.nonEscapingReceivers.addAll(nonEscapingReceivers); 2122 result.nonEscapingReceivers.addAll(nonEscapingReceivers);
2123 return result; 2123 return result;
2124 } 2124 }
2125 } 2125 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698