| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library code_generator; | 5 library code_generator; |
| 6 | 6 |
| 7 import 'glue.dart'; | 7 import 'glue.dart'; |
| 8 | 8 |
| 9 import '../../closure.dart' show | 9 import '../../closure.dart' show |
| 10 ClosureClassElement; | 10 ClosureClassElement; |
| 11 import '../../common.dart'; | 11 import '../../common.dart'; |
| 12 import '../../common/codegen.dart' show | 12 import '../../common/codegen.dart' show |
| 13 CodegenRegistry; | 13 CodegenRegistry; |
| 14 import '../../constants/values.dart'; | 14 import '../../constants/values.dart'; |
| 15 import '../../dart_types.dart'; | 15 import '../../dart_types.dart'; |
| 16 import '../../elements/elements.dart'; | 16 import '../../elements/elements.dart'; |
| 17 import '../../io/source_information.dart' show | 17 import '../../io/source_information.dart' show |
| 18 SourceInformation; | 18 SourceInformation; |
| 19 import '../../js/js.dart' as js; | 19 import '../../js/js.dart' as js; |
| 20 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir; | 20 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir; |
| 21 import '../../tree_ir/tree_ir_nodes.dart' show | 21 import '../../tree_ir/tree_ir_nodes.dart' show |
| 22 BuiltinMethod, | 22 BuiltinMethod, |
| 23 BuiltinOperator; | 23 BuiltinOperator, |
| 24 isCompoundableOperator; |
| 24 import '../../types/types.dart' show | 25 import '../../types/types.dart' show |
| 25 TypeMask; | 26 TypeMask; |
| 26 import '../../universe/call_structure.dart' show | 27 import '../../universe/call_structure.dart' show |
| 27 CallStructure; | 28 CallStructure; |
| 28 import '../../universe/selector.dart' show | 29 import '../../universe/selector.dart' show |
| 29 Selector; | 30 Selector; |
| 30 import '../../universe/use.dart' show | 31 import '../../universe/use.dart' show |
| 31 DynamicUse, | 32 DynamicUse, |
| 32 StaticUse, | 33 StaticUse, |
| 33 TypeUse; | 34 TypeUse; |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 | 499 |
| 499 @override | 500 @override |
| 500 js.Expression visitVariableUse(tree_ir.VariableUse node) { | 501 js.Expression visitVariableUse(tree_ir.VariableUse node) { |
| 501 return buildVariableAccess(node.variable); | 502 return buildVariableAccess(node.variable); |
| 502 } | 503 } |
| 503 | 504 |
| 504 js.Expression buildVariableAccess(tree_ir.Variable variable) { | 505 js.Expression buildVariableAccess(tree_ir.Variable variable) { |
| 505 return new js.VariableUse(getVariableName(variable)); | 506 return new js.VariableUse(getVariableName(variable)); |
| 506 } | 507 } |
| 507 | 508 |
| 509 /// Returns the JS operator for the given built-in operator for use in a |
| 510 /// compound assignment (not including the '=' sign). |
| 511 String getAsCompoundOperator(BuiltinOperator operator) { |
| 512 switch (operator) { |
| 513 case BuiltinOperator.NumAdd: |
| 514 case BuiltinOperator.StringConcatenate: |
| 515 return '+'; |
| 516 case BuiltinOperator.NumSubtract: |
| 517 return '-'; |
| 518 case BuiltinOperator.NumMultiply: |
| 519 return '*'; |
| 520 case BuiltinOperator.NumDivide: |
| 521 return '/'; |
| 522 case BuiltinOperator.NumRemainder: |
| 523 return '%'; |
| 524 default: |
| 525 throw 'Not a compoundable operator: $operator'; |
| 526 } |
| 527 } |
| 528 |
| 529 bool isCompoundableBuiltin(tree_ir.Expression exp) { |
| 530 return exp is tree_ir.ApplyBuiltinOperator && |
| 531 exp.arguments.length == 2 && |
| 532 isCompoundableOperator(exp.operator); |
| 533 } |
| 534 |
| 535 bool isOneConstant(tree_ir.Expression exp) { |
| 536 return exp is tree_ir.Constant && exp.value.isOne; |
| 537 } |
| 538 |
| 539 js.Expression makeAssignment( |
| 540 js.Expression leftHand, |
| 541 tree_ir.Expression value, |
| 542 {BuiltinOperator compound}) { |
| 543 if (isOneConstant(value)) { |
| 544 if (compound == BuiltinOperator.NumAdd) { |
| 545 return new js.Prefix('++', leftHand); |
| 546 } |
| 547 if (compound == BuiltinOperator.NumSubtract) { |
| 548 return new js.Prefix('--', leftHand); |
| 549 } |
| 550 } |
| 551 if (compound != null) { |
| 552 return new js.Assignment.compound(leftHand, |
| 553 getAsCompoundOperator(compound), visitExpression(value)); |
| 554 } |
| 555 return new js.Assignment(leftHand, visitExpression(value)); |
| 556 } |
| 557 |
| 508 @override | 558 @override |
| 509 js.Expression visitAssign(tree_ir.Assign node) { | 559 js.Expression visitAssign(tree_ir.Assign node) { |
| 510 return new js.Assignment( | 560 js.Expression variable = buildVariableAccess(node.variable); |
| 511 buildVariableAccess(node.variable), | 561 if (isCompoundableBuiltin(node.value)) { |
| 512 visitExpression(node.value)); | 562 tree_ir.ApplyBuiltinOperator rhs = node.value; |
| 563 tree_ir.Expression left = rhs.arguments[0]; |
| 564 tree_ir.Expression right = rhs.arguments[1]; |
| 565 if (left is tree_ir.VariableUse && left.variable == node.variable) { |
| 566 return makeAssignment(variable, right, compound: rhs.operator); |
| 567 } |
| 568 } |
| 569 return makeAssignment(variable, node.value); |
| 513 } | 570 } |
| 514 | 571 |
| 515 @override | 572 @override |
| 516 void visitContinue(tree_ir.Continue node) { | 573 void visitContinue(tree_ir.Continue node) { |
| 517 tree_ir.Statement next = fallthrough.target; | 574 tree_ir.Statement next = fallthrough.target; |
| 518 if (node.target.binding == next || | 575 if (node.target.binding == next || |
| 519 next is tree_ir.Continue && node.target == next.target) { | 576 next is tree_ir.Continue && node.target == next.target) { |
| 520 // Fall through to continue target or to equivalent continue. | 577 // Fall through to continue target or to equivalent continue. |
| 521 fallthrough.use(); | 578 fallthrough.use(); |
| 522 } else if (node.target.binding == shortContinue.target) { | 579 } else if (node.target.binding == shortContinue.target) { |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 | 873 |
| 817 @override | 874 @override |
| 818 js.Expression visitGetField(tree_ir.GetField node) { | 875 js.Expression visitGetField(tree_ir.GetField node) { |
| 819 registry.registerStaticUse(new StaticUse.fieldGet(node.field)); | 876 registry.registerStaticUse(new StaticUse.fieldGet(node.field)); |
| 820 return new js.PropertyAccess( | 877 return new js.PropertyAccess( |
| 821 visitExpression(node.object), | 878 visitExpression(node.object), |
| 822 glue.instanceFieldPropertyName(node.field)); | 879 glue.instanceFieldPropertyName(node.field)); |
| 823 } | 880 } |
| 824 | 881 |
| 825 @override | 882 @override |
| 826 js.Assignment visitSetField(tree_ir.SetField node) { | 883 js.Expression visitSetField(tree_ir.SetField node) { |
| 827 registry.registerStaticUse(new StaticUse.fieldSet(node.field)); | 884 registry.registerStaticUse(new StaticUse.fieldSet(node.field)); |
| 828 js.PropertyAccess field = | 885 js.PropertyAccess field = |
| 829 new js.PropertyAccess( | 886 new js.PropertyAccess( |
| 830 visitExpression(node.object), | 887 visitExpression(node.object), |
| 831 glue.instanceFieldPropertyName(node.field)); | 888 glue.instanceFieldPropertyName(node.field)); |
| 832 return new js.Assignment(field, visitExpression(node.value)); | 889 return makeAssignment(field, node.value, compound: node.compound); |
| 833 } | 890 } |
| 834 | 891 |
| 835 @override | 892 @override |
| 836 js.Expression visitGetStatic(tree_ir.GetStatic node) { | 893 js.Expression visitGetStatic(tree_ir.GetStatic node) { |
| 837 assert(node.element is FieldElement || node.element is FunctionElement); | 894 assert(node.element is FieldElement || node.element is FunctionElement); |
| 838 if (node.element is FunctionElement) { | 895 if (node.element is FunctionElement) { |
| 839 // Tear off a method. | 896 // Tear off a method. |
| 840 registry.registerStaticUse( | 897 registry.registerStaticUse( |
| 841 new StaticUse.staticTearOff(node.element.declaration)); | 898 new StaticUse.staticTearOff(node.element.declaration)); |
| 842 return glue.isolateStaticClosureAccess(node.element); | 899 return glue.isolateStaticClosureAccess(node.element); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 872 | 929 |
| 873 @override | 930 @override |
| 874 js.Expression visitGetIndex(tree_ir.GetIndex node) { | 931 js.Expression visitGetIndex(tree_ir.GetIndex node) { |
| 875 return new js.PropertyAccess( | 932 return new js.PropertyAccess( |
| 876 visitExpression(node.object), | 933 visitExpression(node.object), |
| 877 visitExpression(node.index)); | 934 visitExpression(node.index)); |
| 878 } | 935 } |
| 879 | 936 |
| 880 @override | 937 @override |
| 881 js.Expression visitSetIndex(tree_ir.SetIndex node) { | 938 js.Expression visitSetIndex(tree_ir.SetIndex node) { |
| 882 return js.js('#[#] = #', | 939 js.Expression index = new js.PropertyAccess( |
| 883 [visitExpression(node.object), | 940 visitExpression(node.object), visitExpression(node.index)); |
| 884 visitExpression(node.index), | 941 return makeAssignment(index, node.value, compound: node.compound); |
| 885 visitExpression(node.value)]); | |
| 886 } | 942 } |
| 887 | 943 |
| 888 js.Expression buildStaticHelperInvocation( | 944 js.Expression buildStaticHelperInvocation( |
| 889 FunctionElement helper, | 945 FunctionElement helper, |
| 890 List<js.Expression> arguments, | 946 List<js.Expression> arguments, |
| 891 {SourceInformation sourceInformation}) { | 947 {SourceInformation sourceInformation}) { |
| 892 registry.registerStaticUse(new StaticUse.staticInvoke( | 948 registry.registerStaticUse(new StaticUse.staticInvoke( |
| 893 helper, new CallStructure.unnamed(arguments.length))); | 949 helper, new CallStructure.unnamed(arguments.length))); |
| 894 return buildStaticInvoke( | 950 return buildStaticInvoke( |
| 895 helper, arguments, sourceInformation: sourceInformation); | 951 helper, arguments, sourceInformation: sourceInformation); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 void registerDefaultParameterValues(ExecutableElement element) { | 1214 void registerDefaultParameterValues(ExecutableElement element) { |
| 1159 if (element is! FunctionElement) return; | 1215 if (element is! FunctionElement) return; |
| 1160 FunctionElement function = element; | 1216 FunctionElement function = element; |
| 1161 if (function.isStatic) return; // Defaults are inlined at call sites. | 1217 if (function.isStatic) return; // Defaults are inlined at call sites. |
| 1162 function.functionSignature.forEachOptionalParameter((param) { | 1218 function.functionSignature.forEachOptionalParameter((param) { |
| 1163 ConstantValue constant = glue.getDefaultParameterValue(param); | 1219 ConstantValue constant = glue.getDefaultParameterValue(param); |
| 1164 registry.registerCompileTimeConstant(constant); | 1220 registry.registerCompileTimeConstant(constant); |
| 1165 }); | 1221 }); |
| 1166 } | 1222 } |
| 1167 } | 1223 } |
| OLD | NEW |