| 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; |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 js.Expression condition = visitExpression(node.condition); | 652 js.Expression condition = visitExpression(node.condition); |
| 653 int usesBefore = fallthrough.useCount; | 653 int usesBefore = fallthrough.useCount; |
| 654 // Unless the 'else' part ends the method. make sure to terminate any | 654 // Unless the 'else' part ends the method. make sure to terminate any |
| 655 // uncompletable code paths in the 'then' part. | 655 // uncompletable code paths in the 'then' part. |
| 656 emitUnreachableAsReturn.add(!isEndOfMethod(node.elseStatement)); | 656 emitUnreachableAsReturn.add(!isEndOfMethod(node.elseStatement)); |
| 657 js.Statement thenBody = buildBodyStatement(node.thenStatement); | 657 js.Statement thenBody = buildBodyStatement(node.thenStatement); |
| 658 emitUnreachableAsReturn.removeLast(); | 658 emitUnreachableAsReturn.removeLast(); |
| 659 bool thenHasFallthrough = (fallthrough.useCount > usesBefore); | 659 bool thenHasFallthrough = (fallthrough.useCount > usesBefore); |
| 660 if (thenHasFallthrough) { | 660 if (thenHasFallthrough) { |
| 661 js.Statement elseBody = buildBodyStatement(node.elseStatement); | 661 js.Statement elseBody = buildBodyStatement(node.elseStatement); |
| 662 accumulator.add(new js.If(condition, thenBody, elseBody)); | 662 accumulator.add(new js.If(condition, thenBody, elseBody) |
| 663 .withSourceInformation(node.sourceInformation)); |
| 663 return null; | 664 return null; |
| 664 } else { | 665 } else { |
| 665 // The 'then' body cannot complete normally, so emit a short 'if' | 666 // The 'then' body cannot complete normally, so emit a short 'if' |
| 666 // and put the 'else' body after it. | 667 // and put the 'else' body after it. |
| 667 accumulator.add(new js.If.noElse(condition, thenBody)); | 668 accumulator.add(new js.If.noElse(condition, thenBody) |
| 669 .withSourceInformation(node.sourceInformation)); |
| 668 return node.elseStatement; | 670 return node.elseStatement; |
| 669 } | 671 } |
| 670 } | 672 } |
| 671 | 673 |
| 672 @override | 674 @override |
| 673 visitLabeledStatement(tree_ir.LabeledStatement node) { | 675 visitLabeledStatement(tree_ir.LabeledStatement node) { |
| 674 fallthrough.push(node.next); | 676 fallthrough.push(node.next); |
| 675 js.Statement body = buildBodyStatement(node.body); | 677 js.Statement body = buildBodyStatement(node.body); |
| 676 fallthrough.pop(); | 678 fallthrough.pop(); |
| 677 accumulator.add(insertLabel(node.label, body)); | 679 accumulator.add(insertLabel(node.label, body)); |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1072 accumulator.add(new js.If.noElse(condition, body)); | 1074 accumulator.add(new js.If.noElse(condition, body)); |
| 1073 } else { | 1075 } else { |
| 1074 accumulator.add(new js.ExpressionStatement(access)); | 1076 accumulator.add(new js.ExpressionStatement(access)); |
| 1075 } | 1077 } |
| 1076 return node.next; | 1078 return node.next; |
| 1077 } | 1079 } |
| 1078 | 1080 |
| 1079 @override | 1081 @override |
| 1080 js.Expression visitApplyBuiltinOperator(tree_ir.ApplyBuiltinOperator node) { | 1082 js.Expression visitApplyBuiltinOperator(tree_ir.ApplyBuiltinOperator node) { |
| 1081 List<js.Expression> args = visitExpressionList(node.arguments); | 1083 List<js.Expression> args = visitExpressionList(node.arguments); |
| 1082 switch (node.operator) { | 1084 |
| 1083 case BuiltinOperator.NumAdd: | 1085 js.Expression createExpression() { |
| 1084 return new js.Binary('+', args[0], args[1]); | 1086 switch (node.operator) { |
| 1085 case BuiltinOperator.NumSubtract: | 1087 case BuiltinOperator.NumAdd: |
| 1086 return new js.Binary('-', args[0], args[1]); | 1088 return new js.Binary('+', args[0], args[1]); |
| 1087 case BuiltinOperator.NumMultiply: | 1089 case BuiltinOperator.NumSubtract: |
| 1088 return new js.Binary('*', args[0], args[1]); | 1090 return new js.Binary('-', args[0], args[1]); |
| 1089 case BuiltinOperator.NumDivide: | 1091 case BuiltinOperator.NumMultiply: |
| 1090 return new js.Binary('/', args[0], args[1]); | 1092 return new js.Binary('*', args[0], args[1]); |
| 1091 case BuiltinOperator.NumRemainder: | 1093 case BuiltinOperator.NumDivide: |
| 1092 return new js.Binary('%', args[0], args[1]); | 1094 return new js.Binary('/', args[0], args[1]); |
| 1093 case BuiltinOperator.NumTruncatingDivideToSigned32: | 1095 case BuiltinOperator.NumRemainder: |
| 1094 return js.js('(# / #) | 0', args); | 1096 return new js.Binary('%', args[0], args[1]); |
| 1095 case BuiltinOperator.NumAnd: | 1097 case BuiltinOperator.NumTruncatingDivideToSigned32: |
| 1096 return normalizeBitOp(js.js('# & #', args), node); | 1098 return js.js('(# / #) | 0', args); |
| 1097 case BuiltinOperator.NumOr: | 1099 case BuiltinOperator.NumAnd: |
| 1098 return normalizeBitOp(js.js('# | #', args), node); | 1100 return normalizeBitOp(js.js('# & #', args), node); |
| 1099 case BuiltinOperator.NumXor: | 1101 case BuiltinOperator.NumOr: |
| 1100 return normalizeBitOp(js.js('# ^ #', args), node); | 1102 return normalizeBitOp(js.js('# | #', args), node); |
| 1101 case BuiltinOperator.NumLt: | 1103 case BuiltinOperator.NumXor: |
| 1102 return new js.Binary('<', args[0], args[1]); | 1104 return normalizeBitOp(js.js('# ^ #', args), node); |
| 1103 case BuiltinOperator.NumLe: | 1105 case BuiltinOperator.NumLt: |
| 1104 return new js.Binary('<=', args[0], args[1]); | 1106 return new js.Binary('<', args[0], args[1]); |
| 1105 case BuiltinOperator.NumGt: | 1107 case BuiltinOperator.NumLe: |
| 1106 return new js.Binary('>', args[0], args[1]); | 1108 return new js.Binary('<=', args[0], args[1]); |
| 1107 case BuiltinOperator.NumGe: | 1109 case BuiltinOperator.NumGt: |
| 1108 return new js.Binary('>=', args[0], args[1]); | 1110 return new js.Binary('>', args[0], args[1]); |
| 1109 case BuiltinOperator.NumShl: | 1111 case BuiltinOperator.NumGe: |
| 1110 return normalizeBitOp(js.js('# << #', args), node); | 1112 return new js.Binary('>=', args[0], args[1]); |
| 1111 case BuiltinOperator.NumShr: | 1113 case BuiltinOperator.NumShl: |
| 1112 // No normalization required since output is always uint32. | 1114 return normalizeBitOp(js.js('# << #', args), node); |
| 1113 return js.js('# >>> #', args); | 1115 case BuiltinOperator.NumShr: |
| 1114 case BuiltinOperator.NumBitNot: | 1116 // No normalization required since output is always uint32. |
| 1115 return js.js('(~#) >>> 0', args); | 1117 return js.js('# >>> #', args); |
| 1116 case BuiltinOperator.NumNegate: | 1118 case BuiltinOperator.NumBitNot: |
| 1117 return js.js('-#', args); | 1119 return js.js('(~#) >>> 0', args); |
| 1118 case BuiltinOperator.StringConcatenate: | 1120 case BuiltinOperator.NumNegate: |
| 1119 if (args.isEmpty) return js.string(''); | 1121 return js.js('-#', args); |
| 1120 return args.reduce((e1,e2) => new js.Binary('+', e1, e2)); | 1122 case BuiltinOperator.StringConcatenate: |
| 1121 case BuiltinOperator.CharCodeAt: | 1123 if (args.isEmpty) return js.string(''); |
| 1122 return js.js('#.charCodeAt(#)', args); | 1124 return args.reduce((e1,e2) => new js.Binary('+', e1, e2)); |
| 1123 case BuiltinOperator.Identical: | 1125 case BuiltinOperator.CharCodeAt: |
| 1124 registry.registerStaticUse(new StaticUse.staticInvoke( | 1126 return js.js('#.charCodeAt(#)', args); |
| 1125 glue.identicalFunction, new CallStructure.unnamed(args.length))); | 1127 case BuiltinOperator.Identical: |
| 1126 return buildStaticHelperInvocation(glue.identicalFunction, args); | 1128 registry.registerStaticUse(new StaticUse.staticInvoke( |
| 1127 case BuiltinOperator.StrictEq: | 1129 glue.identicalFunction, new CallStructure.unnamed(args.length))); |
| 1128 return new js.Binary('===', args[0], args[1]); | 1130 return buildStaticHelperInvocation(glue.identicalFunction, args); |
| 1129 case BuiltinOperator.StrictNeq: | 1131 case BuiltinOperator.StrictEq: |
| 1130 return new js.Binary('!==', args[0], args[1]); | 1132 return new js.Binary('===', args[0], args[1]); |
| 1131 case BuiltinOperator.LooseEq: | 1133 case BuiltinOperator.StrictNeq: |
| 1132 return new js.Binary('==', args[0], args[1]); | 1134 return new js.Binary('!==', args[0], args[1]); |
| 1133 case BuiltinOperator.LooseNeq: | 1135 case BuiltinOperator.LooseEq: |
| 1134 return new js.Binary('!=', args[0], args[1]); | 1136 return new js.Binary('==', args[0], args[1]); |
| 1135 case BuiltinOperator.IsFalsy: | 1137 case BuiltinOperator.LooseNeq: |
| 1136 return new js.Prefix('!', args[0]); | 1138 return new js.Binary('!=', args[0], args[1]); |
| 1137 case BuiltinOperator.IsNumber: | 1139 case BuiltinOperator.IsFalsy: |
| 1138 return js.js('typeof # === "number"', args); | 1140 return new js.Prefix('!', args[0]); |
| 1139 case BuiltinOperator.IsNotNumber: | 1141 case BuiltinOperator.IsNumber: |
| 1140 return js.js('typeof # !== "number"', args); | 1142 return js.js('typeof # === "number"', args); |
| 1141 case BuiltinOperator.IsFloor: | 1143 case BuiltinOperator.IsNotNumber: |
| 1142 return js.js('Math.floor(#) === #', args); | 1144 return js.js('typeof # !== "number"', args); |
| 1143 case BuiltinOperator.IsInteger: | 1145 case BuiltinOperator.IsFloor: |
| 1144 return js.js('typeof # === "number" && Math.floor(#) === #', args); | 1146 return js.js('Math.floor(#) === #', args); |
| 1145 case BuiltinOperator.IsNotInteger: | 1147 case BuiltinOperator.IsInteger: |
| 1146 return js.js('typeof # !== "number" || Math.floor(#) !== #', args); | 1148 return js.js('typeof # === "number" && Math.floor(#) === #', args); |
| 1147 case BuiltinOperator.IsUnsigned32BitInteger: | 1149 case BuiltinOperator.IsNotInteger: |
| 1148 return js.js('# >>> 0 === #', args); | 1150 return js.js('typeof # !== "number" || Math.floor(#) !== #', args); |
| 1149 case BuiltinOperator.IsNotUnsigned32BitInteger: | 1151 case BuiltinOperator.IsUnsigned32BitInteger: |
| 1150 return js.js('# >>> 0 !== #', args); | 1152 return js.js('# >>> 0 === #', args); |
| 1151 case BuiltinOperator.IsFixedLengthJSArray: | 1153 case BuiltinOperator.IsNotUnsigned32BitInteger: |
| 1152 // TODO(sra): Remove boolify (i.e. !!). | 1154 return js.js('# >>> 0 !== #', args); |
| 1153 return js.js(r'!!#.fixed$length', args); | 1155 case BuiltinOperator.IsFixedLengthJSArray: |
| 1154 case BuiltinOperator.IsExtendableJSArray: | 1156 // TODO(sra): Remove boolify (i.e. !!). |
| 1155 return js.js(r'!#.fixed$length', args); | 1157 return js.js(r'!!#.fixed$length', args); |
| 1156 case BuiltinOperator.IsModifiableJSArray: | 1158 case BuiltinOperator.IsExtendableJSArray: |
| 1157 return js.js(r'!#.immutable$list', args); | 1159 return js.js(r'!#.fixed$length', args); |
| 1158 case BuiltinOperator.IsUnmodifiableJSArray: | 1160 case BuiltinOperator.IsModifiableJSArray: |
| 1159 // TODO(sra): Remove boolify (i.e. !!). | 1161 return js.js(r'!#.immutable$list', args); |
| 1160 return js.js(r'!!#.immutable$list', args); | 1162 case BuiltinOperator.IsUnmodifiableJSArray: |
| 1163 // TODO(sra): Remove boolify (i.e. !!). |
| 1164 return js.js(r'!!#.immutable$list', args); |
| 1165 } |
| 1161 } | 1166 } |
| 1167 |
| 1168 return createExpression().withSourceInformation(node.sourceInformation); |
| 1162 } | 1169 } |
| 1163 | 1170 |
| 1164 /// Add a uint32 normalization `op >>> 0` to [op] if it is not in 31-bit | 1171 /// Add a uint32 normalization `op >>> 0` to [op] if it is not in 31-bit |
| 1165 /// range. | 1172 /// range. |
| 1166 js.Expression normalizeBitOp(js.Expression op, | 1173 js.Expression normalizeBitOp(js.Expression op, |
| 1167 tree_ir.ApplyBuiltinOperator node) { | 1174 tree_ir.ApplyBuiltinOperator node) { |
| 1168 const MAX_UINT31 = 0x7fffffff; | 1175 const MAX_UINT31 = 0x7fffffff; |
| 1169 const MAX_UINT32 = 0xffffffff; | 1176 const MAX_UINT32 = 0xffffffff; |
| 1170 | 1177 |
| 1171 int constantValue(tree_ir.Expression e) { | 1178 int constantValue(tree_ir.Expression e) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1260 void registerDefaultParameterValues(ExecutableElement element) { | 1267 void registerDefaultParameterValues(ExecutableElement element) { |
| 1261 if (element is! FunctionElement) return; | 1268 if (element is! FunctionElement) return; |
| 1262 FunctionElement function = element; | 1269 FunctionElement function = element; |
| 1263 if (function.isStatic) return; // Defaults are inlined at call sites. | 1270 if (function.isStatic) return; // Defaults are inlined at call sites. |
| 1264 function.functionSignature.forEachOptionalParameter((param) { | 1271 function.functionSignature.forEachOptionalParameter((param) { |
| 1265 ConstantValue constant = glue.getDefaultParameterValue(param); | 1272 ConstantValue constant = glue.getDefaultParameterValue(param); |
| 1266 registry.registerCompileTimeConstant(constant); | 1273 registry.registerCompileTimeConstant(constant); |
| 1267 }); | 1274 }); |
| 1268 } | 1275 } |
| 1269 } | 1276 } |
| OLD | NEW |