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

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

Issue 12033056: Implement "one-shot" interceptors. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 11 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 class SsaCodeGeneratorTask extends CompilerTask { 7 class SsaCodeGeneratorTask extends CompilerTask {
8 8
9 final JavaScriptBackend backend; 9 final JavaScriptBackend backend;
10 10
(...skipping 1481 matching lines...) Expand 10 before | Expand all | Expand 10 after
1492 } 1492 }
1493 1493
1494 js.Call jsPropertyCall(js.Expression receiver, 1494 js.Call jsPropertyCall(js.Expression receiver,
1495 String fieldName, 1495 String fieldName,
1496 List<js.Expression> arguments) { 1496 List<js.Expression> arguments) {
1497 return new js.Call(new js.PropertyAccess.field(receiver, fieldName), 1497 return new js.Call(new js.PropertyAccess.field(receiver, fieldName),
1498 arguments); 1498 arguments);
1499 } 1499 }
1500 1500
1501 void visitInterceptor(HInterceptor node) { 1501 void visitInterceptor(HInterceptor node) {
1502 String name = 1502 backend.registerSpecializedGetInterceptor(node.interceptedClasses);
1503 backend.registerSpecializedGetInterceptor(node.interceptedClasses); 1503 String name = backend.namer.getInterceptorName(
1504 js.VariableUse interceptor = new js.VariableUse(name); 1504 backend.getInterceptorMethod, node.interceptedClasses);
1505 var isolate = new js.VariableUse(backend.namer.CURRENT_ISOLATE);
1505 use(node.receiver); 1506 use(node.receiver);
1506 List<js.Expression> arguments = <js.Expression>[pop()]; 1507 List<js.Expression> arguments = <js.Expression>[pop()];
1507 push(new js.Call(interceptor, arguments), node); 1508 push(jsPropertyCall(isolate, name, arguments), node);
1508 } 1509 }
1509 1510
1510 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 1511 visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
1511 use(node.receiver); 1512 use(node.receiver);
1512 js.Expression object = pop(); 1513 js.Expression object = pop();
1513 SourceString name = node.selector.name; 1514 SourceString name = node.selector.name;
1514 String methodName; 1515 String methodName;
1515 List<js.Expression> arguments = visitArguments(node.inputs); 1516 List<js.Expression> arguments = visitArguments(node.inputs);
1516 Element target = node.element; 1517 Element target = node.element;
1517 1518
(...skipping 12 matching lines...) Expand all
1530 // list class is instantiated. 1531 // list class is instantiated.
1531 world.registerInstantiatedClass(compiler.listClass); 1532 world.registerInstantiatedClass(compiler.listClass);
1532 } else if (target == backend.jsStringConcat) { 1533 } else if (target == backend.jsStringConcat) {
1533 push(new js.Binary('+', object, arguments[0]), node); 1534 push(new js.Binary('+', object, arguments[0]), node);
1534 return; 1535 return;
1535 } 1536 }
1536 } 1537 }
1537 1538
1538 if (methodName == null) { 1539 if (methodName == null) {
1539 methodName = backend.namer.invocationName(node.selector); 1540 methodName = backend.namer.invocationName(node.selector);
1540 bool inLoop = node.block.enclosingLoopHeader != null; 1541 registerMethodInvoke(node);
1541
1542 Selector selector = getOptimizedSelectorFor(node, node.selector);
1543 if (node.isInterceptorCall) {
1544 backend.addInterceptedSelector(selector);
1545 }
1546 // Register this invocation to collect the types used at all call sites.
1547 backend.registerDynamicInvocation(node, selector, types);
1548
1549 // If we don't know what we're calling or if we are calling a getter,
1550 // we need to register that fact that we may be calling a closure
1551 // with the same arguments.
1552 if (target == null || target.isGetter()) {
1553 // TODO(kasperl): If we have a typed selector for the call, we
1554 // may know something about the types of closures that need
1555 // the specific closure call method.
1556 Selector call = new Selector.callClosureFrom(selector);
1557 world.registerDynamicInvocation(call.name, call);
1558 }
1559
1560 if (target != null) {
1561 // If we know we're calling a specific method, register that
1562 // method only.
1563 if (inLoop) backend.builder.functionsCalledInLoop.add(target);
1564 world.registerDynamicInvocationOf(target);
1565 } else {
1566 if (inLoop) backend.builder.selectorsCalledInLoop[name] = selector;
1567 world.registerDynamicInvocation(name, selector);
1568 }
1569 } 1542 }
1570 push(jsPropertyCall(object, methodName, arguments), node); 1543 push(jsPropertyCall(object, methodName, arguments), node);
1571 } 1544 }
1572 1545
1546 void visitOneShotInterceptor(HOneShotInterceptor node) {
1547 List<js.Expression> arguments = visitArguments(node.inputs);
1548 var isolate = new js.VariableUse(backend.namer.CURRENT_ISOLATE);
1549 Selector selector = node.selector;
1550 String methodName = backend.namer.oneShotInterceptorName(selector);
1551 push(jsPropertyCall(isolate, methodName, arguments), node);
1552 backend.registerSpecializedGetInterceptor(node.interceptedClasses);
1553 backend.addOneShotInterceptor(selector);
1554 if (selector.isGetter()) {
1555 registerGetter(node);
1556 } else if (selector.isSetter()) {
1557 registerSetter(node);
1558 } else {
1559 registerMethodInvoke(node);
1560 }
1561 }
1562
1573 Selector getOptimizedSelectorFor(HInvokeDynamic node, 1563 Selector getOptimizedSelectorFor(HInvokeDynamic node,
1574 Selector defaultSelector) { 1564 Selector defaultSelector) {
1575 // TODO(4434): For private members we need to use the untyped selector. 1565 // TODO(4434): For private members we need to use the untyped selector.
1576 if (defaultSelector.name.isPrivate()) return defaultSelector; 1566 if (defaultSelector.name.isPrivate()) return defaultSelector;
1577 // TODO(ngeoffray): Type intercepted calls. 1567 // TODO(ngeoffray): Type intercepted calls.
1578 if (node.isInterceptorCall) return defaultSelector; 1568 if (node.isInterceptorCall) return defaultSelector;
1579 // If [JSInvocationMirror.invokeOn] has been called, we must not create a 1569 // If [JSInvocationMirror.invokeOn] has been called, we must not create a
1580 // typed selector based on the receiver type. 1570 // typed selector based on the receiver type.
1581 if (node.element == null && // Invocation is not exact. 1571 if (node.element == null && // Invocation is not exact.
1582 backend.compiler.enabledInvokeOn) { 1572 backend.compiler.enabledInvokeOn) {
1583 return defaultSelector; 1573 return defaultSelector;
1584 } 1574 }
1585 HType receiverHType = types[node.inputs[0]]; 1575 HType receiverHType = types[node.inputs[0]];
1586 DartType receiverType = receiverHType.computeType(compiler); 1576 DartType receiverType = receiverHType.computeType(compiler);
1587 if (receiverType != null && 1577 if (receiverType != null &&
1588 !identical(receiverType.kind, TypeKind.MALFORMED_TYPE)) { 1578 !identical(receiverType.kind, TypeKind.MALFORMED_TYPE)) {
1589 return new TypedSelector(receiverType, defaultSelector); 1579 return new TypedSelector(receiverType, defaultSelector);
1590 } else { 1580 } else {
1591 return defaultSelector; 1581 return defaultSelector;
1592 } 1582 }
1593 } 1583 }
1594 1584
1585 void registerInvoke(HInvokeDynamic node) {
1586 bool inLoop = node.block.enclosingLoopHeader != null;
1587 SourceString name = node.selector.name;
1588 if (inLoop) {
1589 Element target = node.element;
1590 if (target != null) {
1591 backend.builder.functionsCalledInLoop.add(target);
1592 } else {
1593 backend.builder.selectorsCalledInLoop[name] = node.selector;
1594 }
1595 }
1596
1597 if (node.isInterceptorCall) {
1598 backend.addInterceptedSelector(node.selector);
1599 }
1600 }
1601
1602 void registerMethodInvoke(HInvokeDynamic node) {
1603 Selector selector = getOptimizedSelectorFor(node, node.selector);
1604 // Register this invocation to collect the types used at all call sites.
1605 backend.registerDynamicInvocation(node, selector, types);
1606
1607 // If we don't know what we're calling or if we are calling a getter,
1608 // we need to register that fact that we may be calling a closure
1609 // with the same arguments.
1610 Element target = node.element;
1611 if (target == null || target.isGetter()) {
1612 // TODO(kasperl): If we have a typed selector for the call, we
1613 // may know something about the types of closures that need
1614 // the specific closure call method.
1615 Selector call = new Selector.callClosureFrom(selector);
1616 world.registerDynamicInvocation(call.name, call);
1617 }
1618
1619 if (target != null) {
1620 // If we know we're calling a specific method, register that
1621 // method only.
1622 world.registerDynamicInvocationOf(target);
1623 } else {
1624 SourceString name = node.selector.name;
1625 world.registerDynamicInvocation(name, selector);
1626 }
1627 registerInvoke(node);
1628 }
1629
1630 void registerSetter(HInvokeDynamic node) {
1631 Selector selector = getOptimizedSelectorFor(node, node.selector);
1632 world.registerDynamicSetter(selector.name, selector);
1633 HType valueType = node.isInterceptorCall
1634 ? types[node.inputs[2]]
1635 : types[node.inputs[1]];
1636 backend.addedDynamicSetter(selector, valueType);
1637 registerInvoke(node);
1638 }
1639
1640 void registerGetter(HInvokeDynamic node) {
1641 Selector getter = node.selector;
1642 world.registerDynamicGetter(
1643 getter.name, getOptimizedSelectorFor(node, getter));
1644 world.registerInstantiatedClass(compiler.functionClass);
1645 registerInvoke(node);
1646 }
1647
1595 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 1648 visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
1596 use(node.receiver); 1649 use(node.receiver);
1597 Selector setter = node.selector; 1650 Selector setter = node.selector;
1598 String name = backend.namer.invocationName(setter); 1651 String name = backend.namer.invocationName(setter);
1599 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node); 1652 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node);
1600 Selector selector = getOptimizedSelectorFor(node, setter); 1653 registerSetter(node);
1601 world.registerDynamicSetter(setter.name, selector);
1602 HType valueType;
1603 if (node.isInterceptorCall) {
1604 valueType = types[node.inputs[2]];
1605 backend.addInterceptedSelector(setter);
1606 } else {
1607 valueType = types[node.inputs[1]];
1608 }
1609 backend.addedDynamicSetter(selector, valueType);
1610 } 1654 }
1611 1655
1612 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { 1656 visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
1613 use(node.receiver); 1657 use(node.receiver);
1614 Selector getter = node.selector; 1658 Selector getter = node.selector;
1615 String name = backend.namer.invocationName(getter); 1659 String name = backend.namer.invocationName(getter);
1616 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node); 1660 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node);
1617 world.registerDynamicGetter( 1661 registerGetter(node);
1618 getter.name, getOptimizedSelectorFor(node, getter));
1619 if (node.isInterceptorCall) {
1620 backend.addInterceptedSelector(getter);
1621 }
1622 world.registerInstantiatedClass(compiler.functionClass);
1623 } 1662 }
1624 1663
1625 visitInvokeClosure(HInvokeClosure node) { 1664 visitInvokeClosure(HInvokeClosure node) {
1626 Selector call = new Selector.callClosureFrom(node.selector); 1665 Selector call = new Selector.callClosureFrom(node.selector);
1627 use(node.receiver); 1666 use(node.receiver);
1628 push(jsPropertyCall(pop(), 1667 push(jsPropertyCall(pop(),
1629 backend.namer.invocationName(call), 1668 backend.namer.invocationName(call),
1630 visitArguments(node.inputs)), 1669 visitArguments(node.inputs)),
1631 node); 1670 node);
1632 world.registerDynamicInvocation(call.name, call); 1671 world.registerDynamicInvocation(call.name, call);
(...skipping 1356 matching lines...) Expand 10 before | Expand all | Expand 10 after
2989 if (leftType.canBeNull() && rightType.canBeNull()) { 3028 if (leftType.canBeNull() && rightType.canBeNull()) {
2990 if (left.isConstantNull() || right.isConstantNull() || 3029 if (left.isConstantNull() || right.isConstantNull() ||
2991 (leftType.isPrimitive() && leftType == rightType)) { 3030 (leftType.isPrimitive() && leftType == rightType)) {
2992 return '=='; 3031 return '==';
2993 } 3032 }
2994 return null; 3033 return null;
2995 } else { 3034 } else {
2996 return '==='; 3035 return '===';
2997 } 3036 }
2998 } 3037 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698