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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/constant_system_javascript.dart

Issue 692513002: Remove old dart2js code. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of js_backend;
6
7 const JAVA_SCRIPT_CONSTANT_SYSTEM = const JavaScriptConstantSystem();
8
9 class JavaScriptBitNotOperation extends BitNotOperation {
10 const JavaScriptBitNotOperation();
11
12 ConstantValue fold(ConstantValue constant) {
13 if (JAVA_SCRIPT_CONSTANT_SYSTEM.isInt(constant)) {
14 // In JavaScript we don't check for -0 and treat it as if it was zero.
15 if (constant.isMinusZero) constant = DART_CONSTANT_SYSTEM.createInt(0);
16 IntConstantValue intConstant = constant;
17 // We convert the result of bit-operations to 32 bit unsigned integers.
18 return
19 JAVA_SCRIPT_CONSTANT_SYSTEM.createInt32(~intConstant.primitiveValue);
20 }
21 return null;
22 }
23 }
24
25 /**
26 * In JavaScript we truncate the result to an unsigned 32 bit integer. Also, -0
27 * is treated as if it was the integer 0.
28 */
29 class JavaScriptBinaryBitOperation implements BinaryOperation {
30 final BinaryBitOperation dartBitOperation;
31
32 const JavaScriptBinaryBitOperation(this.dartBitOperation);
33
34 String get name => dartBitOperation.name;
35
36 ConstantValue fold(ConstantValue left, ConstantValue right) {
37 // In JavaScript we don't check for -0 and treat it as if it was zero.
38 if (left.isMinusZero) left = DART_CONSTANT_SYSTEM.createInt(0);
39 if (right.isMinusZero) right = DART_CONSTANT_SYSTEM.createInt(0);
40 IntConstantValue result = dartBitOperation.fold(left, right);
41 if (result != null) {
42 // We convert the result of bit-operations to 32 bit unsigned integers.
43 return JAVA_SCRIPT_CONSTANT_SYSTEM.createInt32(result.primitiveValue);
44 }
45 return result;
46 }
47
48 apply(left, right) => dartBitOperation.apply(left, right);
49 }
50
51 class JavaScriptShiftRightOperation extends JavaScriptBinaryBitOperation {
52 const JavaScriptShiftRightOperation() : super(const ShiftRightOperation());
53
54 ConstantValue fold(ConstantValue left, ConstantValue right) {
55 // Truncate the input value to 32 bits if necessary.
56 if (left.isInt) {
57 IntConstantValue intConstant = left;
58 int value = intConstant.primitiveValue;
59 int truncatedValue = value & JAVA_SCRIPT_CONSTANT_SYSTEM.BITS32;
60 if (value < 0) {
61 // Sign-extend if the input was negative. The current semantics don't
62 // make much sense, since we only look at bit 31.
63 // TODO(floitsch): we should treat the input to right shifts as
64 // unsigned.
65
66 // A 32 bit complement-two value x can be computed by:
67 // x_u - 2^32 (where x_u is its unsigned representation).
68 // Example: 0xFFFFFFFF - 0x100000000 => -1.
69 // We simply and with the sign-bit and multiply by two. If the sign-bit
70 // was set, then the result is 0. Otherwise it will become 2^32.
71 final int SIGN_BIT = 0x80000000;
72 truncatedValue -= 2 * (truncatedValue & SIGN_BIT);
73 }
74 if (value != truncatedValue) {
75 left = DART_CONSTANT_SYSTEM.createInt(truncatedValue);
76 }
77 }
78 return super.fold(left, right);
79 }
80 }
81
82 class JavaScriptNegateOperation implements UnaryOperation {
83 final NegateOperation dartNegateOperation = const NegateOperation();
84
85 const JavaScriptNegateOperation();
86
87 String get name => dartNegateOperation.name;
88
89 ConstantValue fold(ConstantValue constant) {
90 if (constant.isInt) {
91 IntConstantValue intConstant = constant;
92 if (intConstant.primitiveValue == 0) {
93 return JAVA_SCRIPT_CONSTANT_SYSTEM.createDouble(-0.0);
94 }
95 }
96 return dartNegateOperation.fold(constant);
97 }
98 }
99
100 class JavaScriptBinaryArithmeticOperation implements BinaryOperation {
101 final BinaryOperation dartArithmeticOperation;
102
103 const JavaScriptBinaryArithmeticOperation(this.dartArithmeticOperation);
104
105 String get name => dartArithmeticOperation.name;
106
107 ConstantValue fold(ConstantValue left, ConstantValue right) {
108 ConstantValue result = dartArithmeticOperation.fold(left, right);
109 if (result == null) return result;
110 return JAVA_SCRIPT_CONSTANT_SYSTEM.convertToJavaScriptConstant(result);
111 }
112
113 apply(left, right) => dartArithmeticOperation.apply(left, right);
114 }
115
116 class JavaScriptIdentityOperation implements BinaryOperation {
117 final IdentityOperation dartIdentityOperation = const IdentityOperation();
118
119 const JavaScriptIdentityOperation();
120
121 String get name => dartIdentityOperation.name;
122
123 BoolConstantValue fold(ConstantValue left, ConstantValue right) {
124 BoolConstantValue result = dartIdentityOperation.fold(left, right);
125 if (result == null || result.primitiveValue) return result;
126 // In JavaScript -0.0 === 0 and all doubles are equal to their integer
127 // values. Furthermore NaN !== NaN.
128 if (left.isNum && right.isNum) {
129 NumConstantValue leftNum = left;
130 NumConstantValue rightNum = right;
131 double leftDouble = leftNum.primitiveValue.toDouble();
132 double rightDouble = rightNum.primitiveValue.toDouble();
133 return new BoolConstantValue(leftDouble == rightDouble);
134 }
135 return result;
136 }
137
138 apply(left, right) => identical(left, right);
139 }
140
141 /**
142 * Constant system following the semantics for Dart code that has been
143 * compiled to JavaScript.
144 */
145 class JavaScriptConstantSystem extends ConstantSystem {
146 final int BITS31 = 0x8FFFFFFF;
147 final int BITS32 = 0xFFFFFFFF;
148
149 final add = const JavaScriptBinaryArithmeticOperation(const AddOperation());
150 final bitAnd = const JavaScriptBinaryBitOperation(const BitAndOperation());
151 final bitNot = const JavaScriptBitNotOperation();
152 final bitOr = const JavaScriptBinaryBitOperation(const BitOrOperation());
153 final bitXor = const JavaScriptBinaryBitOperation(const BitXorOperation());
154 final booleanAnd = const BooleanAndOperation();
155 final booleanOr = const BooleanOrOperation();
156 final divide =
157 const JavaScriptBinaryArithmeticOperation(const DivideOperation());
158 final equal = const EqualsOperation();
159 final greaterEqual = const GreaterEqualOperation();
160 final greater = const GreaterOperation();
161 final identity = const JavaScriptIdentityOperation();
162 final lessEqual = const LessEqualOperation();
163 final less = const LessOperation();
164 final modulo =
165 const JavaScriptBinaryArithmeticOperation(const ModuloOperation());
166 final multiply =
167 const JavaScriptBinaryArithmeticOperation(const MultiplyOperation());
168 final negate = const JavaScriptNegateOperation();
169 final not = const NotOperation();
170 final shiftLeft =
171 const JavaScriptBinaryBitOperation(const ShiftLeftOperation());
172 final shiftRight = const JavaScriptShiftRightOperation();
173 final subtract =
174 const JavaScriptBinaryArithmeticOperation(const SubtractOperation());
175 final truncatingDivide = const JavaScriptBinaryArithmeticOperation(
176 const TruncatingDivideOperation());
177
178 const JavaScriptConstantSystem();
179
180 /**
181 * Returns true if [value] will turn into NaN or infinity
182 * at runtime.
183 */
184 bool integerBecomesNanOrInfinity(int value) {
185 double doubleValue = value.toDouble();
186 return doubleValue.isNaN || doubleValue.isInfinite;
187 }
188
189 NumConstantValue convertToJavaScriptConstant(NumConstantValue constant) {
190 if (constant.isInt) {
191 IntConstantValue intConstant = constant;
192 int intValue = intConstant.primitiveValue;
193 if (integerBecomesNanOrInfinity(intValue)) {
194 return new DoubleConstantValue(intValue.toDouble());
195 }
196 // If the integer loses precision with JavaScript numbers, use
197 // the floored version JavaScript will use.
198 int floorValue = intValue.toDouble().floor().toInt();
199 if (floorValue != intValue) {
200 return new IntConstantValue(floorValue);
201 }
202 } else if (constant.isDouble) {
203 DoubleConstantValue doubleResult = constant;
204 double doubleValue = doubleResult.primitiveValue;
205 if (!doubleValue.isInfinite && !doubleValue.isNaN &&
206 !constant.isMinusZero) {
207 int intValue = doubleValue.truncate();
208 if (intValue == doubleValue) {
209 return new IntConstantValue(intValue);
210 }
211 }
212 }
213 return constant;
214 }
215
216 NumConstantValue createInt(int i)
217 => convertToJavaScriptConstant(new IntConstantValue(i));
218 NumConstantValue createInt32(int i) => new IntConstantValue(i & BITS32);
219 NumConstantValue createDouble(double d)
220 => convertToJavaScriptConstant(new DoubleConstantValue(d));
221 StringConstantValue createString(DartString string) {
222 return new StringConstantValue(string);
223 }
224 BoolConstantValue createBool(bool value) => new BoolConstantValue(value);
225 NullConstantValue createNull() => new NullConstantValue();
226
227 // Integer checks don't verify that the number is not -0.0.
228 bool isInt(ConstantValue constant) => constant.isInt || constant.isMinusZero;
229 bool isDouble(ConstantValue constant)
230 => constant.isDouble && !constant.isMinusZero;
231 bool isString(ConstantValue constant) => constant.isString;
232 bool isBool(ConstantValue constant) => constant.isBool;
233 bool isNull(ConstantValue constant) => constant.isNull;
234
235 bool isSubtype(Compiler compiler, DartType s, DartType t) {
236 // At runtime, an integer is both an integer and a double: the
237 // integer type check is Math.floor, which will return true only
238 // for real integers, and our double type check is 'typeof number'
239 // which will return true for both integers and doubles.
240 if (s.element == compiler.intClass && t.element == compiler.doubleClass) {
241 return true;
242 }
243 return compiler.types.isSubtype(s, t);
244 }
245
246 MapConstantValue createMap(Compiler compiler,
247 InterfaceType sourceType,
248 List<ConstantValue> keys,
249 List<ConstantValue> values) {
250 JavaScriptBackend backend = compiler.backend;
251
252 bool onlyStringKeys = true;
253 ConstantValue protoValue = null;
254 for (int i = 0; i < keys.length ; i++) {
255 var key = keys[i];
256 if (key.isString) {
257 if (key.primitiveValue == JavaScriptMapConstant.PROTO_PROPERTY) {
258 protoValue = values[i];
259 }
260 } else {
261 onlyStringKeys = false;
262 // Don't handle __proto__ values specially in the general map case.
263 protoValue = null;
264 break;
265 }
266 }
267
268 bool hasProtoKey = (protoValue != null);
269 DartType keysType;
270 if (sourceType.treatAsRaw) {
271 keysType = compiler.listClass.rawType;
272 } else {
273 List<DartType> arguments = <DartType>[sourceType.typeArguments.first];
274 keysType = new InterfaceType(compiler.listClass, arguments);
275 }
276 ListConstantValue keysList = new ListConstantValue(keysType, keys);
277 String className = onlyStringKeys
278 ? (hasProtoKey ? JavaScriptMapConstant.DART_PROTO_CLASS
279 : JavaScriptMapConstant.DART_STRING_CLASS)
280 : JavaScriptMapConstant.DART_GENERAL_CLASS;
281 ClassElement classElement = backend.jsHelperLibrary.find(className);
282 classElement.ensureResolved(compiler);
283 List<DartType> typeArgument = sourceType.typeArguments;
284 InterfaceType type;
285 if (sourceType.treatAsRaw) {
286 type = classElement.rawType;
287 } else {
288 type = new InterfaceType(classElement, typeArgument);
289 }
290 return new JavaScriptMapConstant(
291 type, keysList, values, protoValue, onlyStringKeys);
292
293 }
294 }
295
296 class JavaScriptMapConstant extends MapConstantValue {
297 /**
298 * The [PROTO_PROPERTY] must not be used as normal property in any JavaScript
299 * object. It would change the prototype chain.
300 */
301 static const LiteralDartString PROTO_PROPERTY =
302 const LiteralDartString("__proto__");
303
304 /** The dart class implementing constant map literals. */
305 static const String DART_CLASS = "ConstantMap";
306 static const String DART_STRING_CLASS = "ConstantStringMap";
307 static const String DART_PROTO_CLASS = "ConstantProtoMap";
308 static const String DART_GENERAL_CLASS = "GeneralConstantMap";
309 static const String LENGTH_NAME = "length";
310 static const String JS_OBJECT_NAME = "_jsObject";
311 static const String KEYS_NAME = "_keys";
312 static const String PROTO_VALUE = "_protoValue";
313 static const String JS_DATA_NAME = "_jsData";
314
315 final ListConstantValue keyList;
316 final ConstantValue protoValue;
317 final bool onlyStringKeys;
318
319 JavaScriptMapConstant(InterfaceType type,
320 ListConstantValue keyList,
321 List<ConstantValue> values,
322 this.protoValue,
323 this.onlyStringKeys)
324 : this.keyList = keyList,
325 super(type, keyList.entries, values);
326 bool get isMap => true;
327
328 TypeMask computeMask(Compiler compiler) {
329 return compiler.typesTask.constMapType;
330 }
331
332 List<ConstantValue> getDependencies() {
333 List<ConstantValue> result = <ConstantValue>[];
334 if (onlyStringKeys) {
335 result.add(keyList);
336 } else {
337 // Add the keys individually to avoid generating an unused list constant
338 // for the keys.
339 result.addAll(keys);
340 }
341 result.addAll(values);
342 return result;
343 }
344 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698