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

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

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

Powered by Google App Engine
This is Rietveld 408576698