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

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

Issue 11412105: - Move length getter and setter interceptors to the new interceptor scheme. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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 | 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 class SsaCodeGeneratorTask extends CompilerTask { 7 class SsaCodeGeneratorTask extends CompilerTask {
8 8
9 final JavaScriptBackend backend; 9 final JavaScriptBackend backend;
10 10
(...skipping 1511 matching lines...) Expand 10 before | Expand all | Expand 10 after
1522 } 1522 }
1523 } 1523 }
1524 1524
1525 js.Call jsPropertyCall(js.Expression receiver, 1525 js.Call jsPropertyCall(js.Expression receiver,
1526 String fieldName, 1526 String fieldName,
1527 List<js.Expression> arguments) { 1527 List<js.Expression> arguments) {
1528 return new js.Call(new js.PropertyAccess.field(receiver, fieldName), 1528 return new js.Call(new js.PropertyAccess.field(receiver, fieldName),
1529 arguments); 1529 arguments);
1530 } 1530 }
1531 1531
1532 // TODO(ngeoffray): Once we remove the old interceptors, we can
1533 // start using HInvokeInterceptor to represent interceptor calls on
1534 // an Interceptor class. Currently we recognize if a call is a call
1535 // on an interceptor by checking if the arguments in the inputs list
1536 // is one more than the arguments in the selector. The extra
1537 // argument in an interceptor call is the actual receiver.
1538 bool isInterceptorCall(HInvokeDynamic node) {
1539 return node.inputs.length - 1 != node.selector.argumentCount;
1540 }
1541
1542 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 1532 visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
1543 use(node.receiver); 1533 use(node.receiver);
1544 js.Expression object = pop(); 1534 js.Expression object = pop();
1545 SourceString name = node.selector.name; 1535 SourceString name = node.selector.name;
1546 String methodName; 1536 String methodName;
1547 List<js.Expression> arguments; 1537 List<js.Expression> arguments;
1548 Element target = node.element; 1538 Element target = node.element;
1549 1539
1550 // Avoid adding the generative constructor name to the list of 1540 // Avoid adding the generative constructor name to the list of
1551 // seen selectors. 1541 // seen selectors.
1552 if (target != null && target.isGenerativeConstructorBody()) { 1542 if (target != null && target.isGenerativeConstructorBody()) {
1553 methodName = name.slowToString(); 1543 methodName = name.slowToString();
1554 arguments = visitArguments(node.inputs); 1544 arguments = visitArguments(node.inputs);
1555 } else { 1545 } else {
1556 methodName = backend.namer.instanceMethodInvocationName( 1546 methodName = backend.namer.instanceMethodInvocationName(
1557 node.selector.library, name, node.selector); 1547 node.selector.library, name, node.selector);
1558 arguments = visitArguments(node.inputs); 1548 arguments = visitArguments(node.inputs);
1559 bool inLoop = node.block.enclosingLoopHeader != null; 1549 bool inLoop = node.block.enclosingLoopHeader != null;
1560 1550
1561 // Register this invocation to collect the types used at all call sites. 1551 // Register this invocation to collect the types used at all call sites.
1562 Selector selector = getOptimizedSelectorFor(node, node.selector); 1552 Selector selector = getOptimizedSelectorFor(node, node.selector);
1563 // TODO(ngeoffray): Remove the following restriction. Because 1553 // TODO(ngeoffray): Remove the following restriction. Because
1564 // the second input of this interceptor call is the actual 1554 // the second input of this interceptor call is the actual
1565 // receiver (the first is the interceptor), the backend gets 1555 // receiver (the first is the interceptor), the backend gets
1566 // confused. We should pass a list of types instead of a node to 1556 // confused. We should pass a list of types instead of a node to
1567 // [registerDynamicInvocation]. 1557 // [registerDynamicInvocation].
1568 if (!isInterceptorCall(node)) { 1558 if (!node.isInterceptorCall) {
1569 backend.registerDynamicInvocation(node, selector, types); 1559 backend.registerDynamicInvocation(node, selector, types);
1570 } else { 1560 } else {
1571 backend.addInterceptedSelector(selector); 1561 backend.addInterceptedSelector(selector);
1572 } 1562 }
1573 1563
1574 // If we don't know what we're calling or if we are calling a getter, 1564 // If we don't know what we're calling or if we are calling a getter,
1575 // we need to register that fact that we may be calling a closure 1565 // we need to register that fact that we may be calling a closure
1576 // with the same arguments. 1566 // with the same arguments.
1577 if (target == null || target.isGetter()) { 1567 if (target == null || target.isGetter()) {
1578 // TODO(kasperl): If we have a typed selector for the call, we 1568 // TODO(kasperl): If we have a typed selector for the call, we
(...skipping 14 matching lines...) Expand all
1593 } 1583 }
1594 } 1584 }
1595 push(jsPropertyCall(object, methodName, arguments), node); 1585 push(jsPropertyCall(object, methodName, arguments), node);
1596 } 1586 }
1597 1587
1598 Selector getOptimizedSelectorFor(HInvokeDynamic node, 1588 Selector getOptimizedSelectorFor(HInvokeDynamic node,
1599 Selector defaultSelector) { 1589 Selector defaultSelector) {
1600 // TODO(4434): For private members we need to use the untyped selector. 1590 // TODO(4434): For private members we need to use the untyped selector.
1601 if (defaultSelector.name.isPrivate()) return defaultSelector; 1591 if (defaultSelector.name.isPrivate()) return defaultSelector;
1602 // TODO(ngeoffray): Type intercepted calls. 1592 // TODO(ngeoffray): Type intercepted calls.
1603 if (isInterceptorCall(node)) return defaultSelector; 1593 if (node.isInterceptorCall) return defaultSelector;
1604 // If [JSInvocationMirror.invokeOn] has been called, we must not create a 1594 // If [JSInvocationMirror.invokeOn] has been called, we must not create a
1605 // typed selector based on the receiver type. 1595 // typed selector based on the receiver type.
1606 if (node.element == null && // Invocation is not exact. 1596 if (node.element == null && // Invocation is not exact.
1607 backend.compiler.enabledInvokeOn) { 1597 backend.compiler.enabledInvokeOn) {
1608 return defaultSelector; 1598 return defaultSelector;
1609 } 1599 }
1610 HType receiverHType = types[node.inputs[0]]; 1600 HType receiverHType = types[node.inputs[0]];
1611 DartType receiverType = receiverHType.computeType(compiler); 1601 DartType receiverType = receiverHType.computeType(compiler);
1612 if (receiverType != null) { 1602 if (receiverType != null) {
1613 return new TypedSelector(receiverType, defaultSelector); 1603 return new TypedSelector(receiverType, defaultSelector);
1614 } else { 1604 } else {
1615 return defaultSelector; 1605 return defaultSelector;
1616 } 1606 }
1617 } 1607 }
1618 1608
1619 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 1609 visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
1620 use(node.receiver); 1610 use(node.receiver);
1621 Selector setter = node.selector; 1611 Selector setter = node.selector;
1622 String name = backend.namer.setterName(setter.library, setter.name); 1612 String name = backend.namer.setterName(setter.library, setter.name);
1623 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node); 1613 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node);
1624 Selector selector = getOptimizedSelectorFor(node, setter); 1614 Selector selector = getOptimizedSelectorFor(node, setter);
1625 world.registerDynamicSetter(setter.name, selector); 1615 world.registerDynamicSetter(setter.name, selector);
1626 backend.addedDynamicSetter(selector, types[node.inputs[1]]); 1616 HType valueType;
1617 if (node.isInterceptorCall) {
1618 valueType = types[node.inputs[2]];
1619 backend.addInterceptedSelector(setter);
1620 } else {
1621 valueType = types[node.inputs[1]];
1622 }
1623 backend.addedDynamicSetter(selector, valueType);
1627 } 1624 }
1628 1625
1629 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { 1626 visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
1630 use(node.receiver); 1627 use(node.receiver);
1631 Selector getter = node.selector; 1628 Selector getter = node.selector;
1632 String name = backend.namer.getterName(getter.library, getter.name); 1629 String name = backend.namer.getterName(getter.library, getter.name);
1633 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node); 1630 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node);
1634 world.registerDynamicGetter( 1631 world.registerDynamicGetter(
1635 getter.name, getOptimizedSelectorFor(node, getter)); 1632 getter.name, getOptimizedSelectorFor(node, getter));
1636 if (isInterceptorCall(node)) { 1633 if (node.isInterceptorCall) {
1637 backend.addInterceptedSelector(getter); 1634 backend.addInterceptedSelector(getter);
1638 } 1635 }
1639 } 1636 }
1640 1637
1641 visitInvokeClosure(HInvokeClosure node) { 1638 visitInvokeClosure(HInvokeClosure node) {
1642 use(node.receiver); 1639 use(node.receiver);
1643 push(jsPropertyCall(pop(), 1640 push(jsPropertyCall(pop(),
1644 backend.namer.closureInvocationName(node.selector), 1641 backend.namer.closureInvocationName(node.selector),
1645 visitArguments(node.inputs)), 1642 visitArguments(node.inputs)),
1646 node); 1643 node);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1707 js.VariableUse classReference = new js.VariableUse(className); 1704 js.VariableUse classReference = new js.VariableUse(className);
1708 js.PropertyAccess prototype = 1705 js.PropertyAccess prototype =
1709 new js.PropertyAccess.field(classReference, "prototype"); 1706 new js.PropertyAccess.field(classReference, "prototype");
1710 js.PropertyAccess method = 1707 js.PropertyAccess method =
1711 new js.PropertyAccess.field(prototype, methodName); 1708 new js.PropertyAccess.field(prototype, methodName);
1712 push(jsPropertyCall(method, "call", visitArguments(node.inputs)), node); 1709 push(jsPropertyCall(method, "call", visitArguments(node.inputs)), node);
1713 } 1710 }
1714 world.registerStaticUse(superMethod); 1711 world.registerStaticUse(superMethod);
1715 } 1712 }
1716 1713
1717 visitFieldGet(HFieldGet node) { 1714 visitFieldGet(HFieldGet node) {
ahe 2012/11/23 06:51:23 What is a HFieldGet? Is that when we know that we
ngeoffray 2012/11/23 12:01:17 Yes.
1718 String name = backend.namer.getName(node.element);
1719 use(node.receiver); 1715 use(node.receiver);
1720 push(new js.PropertyAccess.field(pop(), name), node); 1716 if (node.element == backend.jsArrayLength
1721 HType receiverHType = types[node.receiver]; 1717 || node.element == backend.jsStringLength) {
1722 DartType type = receiverHType.computeType(compiler); 1718 push(new js.PropertyAccess.field(pop(), 'length'), node);
ahe 2012/11/23 06:51:23 Please add a comment explaining why this name shou
ngeoffray 2012/11/23 12:01:17 Done.
1723 if (type != null) { 1719 } else {
1724 world.registerFieldGetter( 1720 String name = backend.namer.getName(node.element);
1725 node.element.name, node.element.getLibrary(), type); 1721 push(new js.PropertyAccess.field(pop(), name), node);
1722 HType receiverHType = types[node.receiver];
1723 DartType type = receiverHType.computeType(compiler);
1724 if (type != null) {
1725 world.registerFieldGetter(
1726 node.element.name, node.element.getLibrary(), type);
1727 }
1726 } 1728 }
1727 } 1729 }
1728 1730
1729 // Determine if an instruction is a simple number computation 1731 // Determine if an instruction is a simple number computation
1730 // involving only things with guaranteed number types and a given 1732 // involving only things with guaranteed number types and a given
1731 // field. 1733 // field.
1732 bool isSimpleFieldNumberComputation(HInstruction value, HFieldSet node) { 1734 bool isSimpleFieldNumberComputation(HInstruction value, HFieldSet node) {
1733 if (value.guaranteedType.union(HType.NUMBER, compiler) == HType.NUMBER) { 1735 if (value.guaranteedType.union(HType.NUMBER, compiler) == HType.NUMBER) {
1734 return true; 1736 return true;
1735 } 1737 }
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
2191 use(node.inputs[2]); 2193 use(node.inputs[2]);
2192 js.Expression index = pop(); 2194 js.Expression index = pop();
2193 use(node.inputs[3]); 2195 use(node.inputs[3]);
2194 push(new js.Assignment(new js.PropertyAccess(receiver, index), pop()), 2196 push(new js.Assignment(new js.PropertyAccess(receiver, index), pop()),
2195 node); 2197 node);
2196 } else { 2198 } else {
2197 visitInvokeStatic(node); 2199 visitInvokeStatic(node);
2198 } 2200 }
2199 } 2201 }
2200 2202
2201 String builtinJsName(HInvokeInterceptor interceptor) {
2202 // Don't count the target method or the receiver in the arity.
2203 int arity = interceptor.inputs.length - 2;
2204 HInstruction receiver = interceptor.inputs[1];
2205 bool isCall = interceptor.selector.isCall();
2206 SourceString name = interceptor.selector.name;
2207
2208 if (interceptor.isLengthGetterOnStringOrArray(types)) {
2209 return 'length';
2210 } else if (interceptor.isPopCall(types)) {
2211 return 'pop';
2212 } else if (receiver.isExtendableArray(types) && isCall) {
2213 if (name == const SourceString('add') && arity == 1) {
2214 return 'push';
2215 }
2216 } else if (receiver.isString(types) && isCall) {
2217 if (name == const SourceString('concat') &&
2218 arity == 1 &&
2219 interceptor.inputs[2].isString(types)) {
2220 return '+';
2221 }
2222 if (name == const SourceString('split') &&
2223 arity == 1 &&
2224 interceptor.inputs[2].isString(types)) {
2225 return 'split';
2226 }
2227 }
2228
2229 return null;
2230 }
2231
2232 void visitInvokeInterceptor(HInvokeInterceptor node) {
2233 String builtin = builtinJsName(node);
2234 if (builtin != null) {
2235 if (builtin == '+') {
2236 use(node.inputs[1]);
2237 js.Expression left = pop();
2238 use(node.inputs[2]);
2239 push(new js.Binary("+", left, pop()), node);
2240 } else {
2241 use(node.inputs[1]);
2242 js.PropertyAccess access = new js.PropertyAccess.field(pop(), builtin);
2243 if (node.selector.isGetter()) {
2244 push(access, node);
2245 return;
2246 }
2247 List<js.Expression> arguments = <js.Expression>[];
2248 for (int i = 2; i < node.inputs.length; i++) {
2249 use(node.inputs[i]);
2250 arguments.add(pop());
2251 }
2252 push(new js.Call(access, arguments), node);
2253 }
2254 } else {
2255 return visitInvokeStatic(node);
2256 }
2257 }
2258
2259 void checkInt(HInstruction input, String cmp) { 2203 void checkInt(HInstruction input, String cmp) {
2260 use(input); 2204 use(input);
2261 js.Expression left = pop(); 2205 js.Expression left = pop();
2262 use(input); 2206 use(input);
2263 js.Expression or0 = new js.Binary("|", pop(), new js.LiteralNumber("0")); 2207 js.Expression or0 = new js.Binary("|", pop(), new js.LiteralNumber("0"));
2264 push(new js.Binary(cmp, left, or0)); 2208 push(new js.Binary(cmp, left, or0));
2265 } 2209 }
2266 2210
2267 void checkBigInt(HInstruction input, String cmp) { 2211 void checkBigInt(HInstruction input, String cmp) {
2268 use(input); 2212 use(input);
(...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after
3110 if (leftType.canBeNull() && rightType.canBeNull()) { 3054 if (leftType.canBeNull() && rightType.canBeNull()) {
3111 if (left.isConstantNull() || right.isConstantNull() || 3055 if (left.isConstantNull() || right.isConstantNull() ||
3112 (leftType.isPrimitive() && leftType == rightType)) { 3056 (leftType.isPrimitive() && leftType == rightType)) {
3113 return '=='; 3057 return '==';
3114 } 3058 }
3115 return null; 3059 return null;
3116 } else { 3060 } else {
3117 return '==='; 3061 return '===';
3118 } 3062 }
3119 } 3063 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698