| OLD | NEW |
| 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 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 js.Expression result = sequenceElements.removeLast(); | 464 js.Expression result = sequenceElements.removeLast(); |
| 465 while (sequenceElements.isNotEmpty) { | 465 while (sequenceElements.isNotEmpty) { |
| 466 result = new js.Binary(',', sequenceElements.removeLast(), result); | 466 result = new js.Binary(',', sequenceElements.removeLast(), result); |
| 467 } | 467 } |
| 468 return result; | 468 return result; |
| 469 } | 469 } |
| 470 } | 470 } |
| 471 | 471 |
| 472 /** | 472 /** |
| 473 * Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET]. | 473 * Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET]. |
| 474 * Also, skip all trailing constant `null` arguments. JavaScript will fill |
| 475 * missing arguments with `undefined` anyway. For functions that rely on |
| 476 * 'arguments.length' in JavaScript, [allArgsRequired] should be set to |
| 477 * `true`. |
| 474 */ | 478 */ |
| 475 List<js.Expression> visitArguments(List<HInstruction> inputs, | 479 List<js.Expression> visitArguments(List<HInstruction> inputs, |
| 476 {int start: HInvoke.ARGUMENTS_OFFSET}) { | 480 {int start: HInvoke.ARGUMENTS_OFFSET, |
| 481 bool allArgsRequired: false}) { |
| 477 assert(inputs.length >= start); | 482 assert(inputs.length >= start); |
| 478 List<js.Expression> result = new List<js.Expression>(inputs.length - start); | 483 int max; |
| 479 for (int i = start; i < inputs.length; i++) { | 484 if (allArgsRequired) { |
| 485 max = inputs.length; |
| 486 } else { |
| 487 for (max = inputs.length; max > start; --max) { |
| 488 HInstruction input = inputs[max-1]; |
| 489 if (input is! HConstant) break; |
| 490 HConstant constant = input; |
| 491 if (!constant.constant.isNull) break; |
| 492 } |
| 493 } |
| 494 List<js.Expression> result = new List<js.Expression>(max - start); |
| 495 for (int i = start; i < max; i++) { |
| 480 use(inputs[i]); | 496 use(inputs[i]); |
| 481 result[i - start] = pop(); | 497 result[i - start] = pop(); |
| 482 } | 498 } |
| 483 return result; | 499 return result; |
| 484 } | 500 } |
| 485 | 501 |
| 486 bool isVariableDeclared(String variableName) { | 502 bool isVariableDeclared(String variableName) { |
| 487 return declaredLocals.contains(variableName) || | 503 return declaredLocals.contains(variableName) || |
| 488 collectedVariableDeclarations.contains(variableName); | 504 collectedVariableDeclarations.contains(variableName); |
| 489 } | 505 } |
| (...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1506 List<js.Expression> arguments = <js.Expression>[pop()]; | 1522 List<js.Expression> arguments = <js.Expression>[pop()]; |
| 1507 push(jsPropertyCall(isolate, name, arguments), node); | 1523 push(jsPropertyCall(isolate, name, arguments), node); |
| 1508 registry.registerUseInterceptor(); | 1524 registry.registerUseInterceptor(); |
| 1509 } | 1525 } |
| 1510 | 1526 |
| 1511 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { | 1527 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { |
| 1512 use(node.receiver); | 1528 use(node.receiver); |
| 1513 js.Expression object = pop(); | 1529 js.Expression object = pop(); |
| 1514 String name = node.selector.name; | 1530 String name = node.selector.name; |
| 1515 String methodName; | 1531 String methodName; |
| 1516 List<js.Expression> arguments = visitArguments(node.inputs); | 1532 bool allArgsRequired = false; |
| 1517 Element target = node.element; | 1533 Element target = node.element; |
| 1518 | 1534 |
| 1519 if (target != null && !node.isInterceptedCall) { | 1535 if (target != null && !node.isInterceptedCall) { |
| 1520 if (target == backend.jsArrayAdd) { | 1536 if (target == backend.jsArrayAdd) { |
| 1521 methodName = 'push'; | 1537 methodName = 'push'; |
| 1538 allArgsRequired = true; |
| 1522 } else if (target == backend.jsArrayRemoveLast) { | 1539 } else if (target == backend.jsArrayRemoveLast) { |
| 1523 methodName = 'pop'; | 1540 methodName = 'pop'; |
| 1524 } else if (target == backend.jsStringSplit) { | 1541 } else if (target == backend.jsStringSplit) { |
| 1525 methodName = 'split'; | 1542 methodName = 'split'; |
| 1526 // Split returns a List, so we make sure the backend knows the | 1543 // Split returns a List, so we make sure the backend knows the |
| 1527 // list class is instantiated. | 1544 // list class is instantiated. |
| 1528 registry.registerInstantiatedClass(compiler.listClass); | 1545 registry.registerInstantiatedClass(compiler.listClass); |
| 1529 } else if (target.isNative && target.isFunction | 1546 } else if (target.isNative && target.isFunction) { |
| 1530 && !node.isInterceptedCall) { | |
| 1531 // A direct (i.e. non-interceptor) native call is the result of | 1547 // A direct (i.e. non-interceptor) native call is the result of |
| 1532 // optimization. The optimization ensures any type checks or | 1548 // optimization. The optimization ensures any type checks or |
| 1533 // conversions have been satisified. | 1549 // conversions have been satisified. |
| 1534 methodName = target.fixedBackendName; | 1550 methodName = target.fixedBackendName; |
| 1551 // TODO(herhut): Add notion of allArgsRequired to native annotations. |
| 1552 allArgsRequired = true; |
| 1535 } | 1553 } |
| 1536 } | 1554 } |
| 1555 // TODO(herhut): Add proper calling conventions to encode when arguments |
| 1556 // may be dropped. |
| 1557 List<js.Expression> arguments = visitArguments(node.inputs, |
| 1558 allArgsRequired: allArgsRequired); |
| 1537 | 1559 |
| 1538 if (methodName == null) { | 1560 if (methodName == null) { |
| 1539 methodName = backend.namer.invocationName(node.selector); | 1561 methodName = backend.namer.invocationName(node.selector); |
| 1540 registerMethodInvoke(node); | 1562 registerMethodInvoke(node); |
| 1541 } | 1563 } |
| 1542 push(jsPropertyCall(object, methodName, arguments), node); | 1564 push(jsPropertyCall(object, methodName, arguments), node); |
| 1543 } | 1565 } |
| 1544 | 1566 |
| 1545 void visitInvokeConstructorBody(HInvokeConstructorBody node) { | 1567 void visitInvokeConstructorBody(HInvokeConstructorBody node) { |
| 1546 use(node.inputs[0]); | 1568 use(node.inputs[0]); |
| (...skipping 1166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2713 js.PropertyAccess accessHelper(String name) { | 2735 js.PropertyAccess accessHelper(String name) { |
| 2714 Element helper = backend.findHelper(name); | 2736 Element helper = backend.findHelper(name); |
| 2715 if (helper == null) { | 2737 if (helper == null) { |
| 2716 // For mocked-up tests. | 2738 // For mocked-up tests. |
| 2717 return js.js('(void 0).$name'); | 2739 return js.js('(void 0).$name'); |
| 2718 } | 2740 } |
| 2719 registry.registerStaticUse(helper); | 2741 registry.registerStaticUse(helper); |
| 2720 return backend.namer.elementAccess(helper); | 2742 return backend.namer.elementAccess(helper); |
| 2721 } | 2743 } |
| 2722 } | 2744 } |
| OLD | NEW |