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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart

Issue 12033056: Implement "one-shot" interceptors. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 11 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /** 7 /**
8 * [InvokeDynamicSpecializer] and its subclasses are helpers to 8 * [InvokeDynamicSpecializer] and its subclasses are helpers to
9 * optimize intercepted dynamic calls. It knows what input types 9 * optimize intercepted dynamic calls. It knows what input types
10 * would be beneficial for performance, and how to change a invoke 10 * would be beneficial for performance, and how to change a invoke
11 * dynamic to a builtin instruction (e.g. HIndex, HBitNot). 11 * dynamic to a builtin instruction (e.g. HIndex, HBitNot).
12 */ 12 */
13 class InvokeDynamicSpecializer { 13 class InvokeDynamicSpecializer {
14 const InvokeDynamicSpecializer(); 14 const InvokeDynamicSpecializer();
15 15
16 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, 16 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
17 HInstruction input, 17 HInstruction input,
18 HTypeMap types, 18 HTypeMap types,
19 Compiler compiler) { 19 Compiler compiler) {
20 return HType.UNKNOWN; 20 return HType.UNKNOWN;
21 } 21 }
22 22
23 HType computeTypeFromInputTypes(HInvokeDynamicMethod instruction, 23 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
24 HTypeMap types, 24 HTypeMap types,
25 Compiler compiler) { 25 Compiler compiler) {
26 return HType.UNKNOWN; 26 return HType.UNKNOWN;
27 } 27 }
28 28
29 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, 29 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
30 HTypeMap types) { 30 HTypeMap types) {
31 return null; 31 return null;
32 } 32 }
33 33
34 Operation operation(ConstantSystem constantSystem) => null; 34 Operation operation(ConstantSystem constantSystem) => null;
35 35
36 static InvokeDynamicSpecializer lookupSpecializer(Selector selector) { 36 static InvokeDynamicSpecializer lookupSpecializer(Selector selector) {
37 if (selector.kind == SelectorKind.INDEX) { 37 if (selector.kind == SelectorKind.INDEX) {
38 return selector.name == const SourceString('[]') 38 return selector.name == const SourceString('[]')
39 ? const IndexSpecializer() 39 ? const IndexSpecializer()
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 return const GreaterEqualSpecializer(); 77 return const GreaterEqualSpecializer();
78 } 78 }
79 } 79 }
80 return const InvokeDynamicSpecializer(); 80 return const InvokeDynamicSpecializer();
81 } 81 }
82 } 82 }
83 83
84 class IndexAssignSpecializer extends InvokeDynamicSpecializer { 84 class IndexAssignSpecializer extends InvokeDynamicSpecializer {
85 const IndexAssignSpecializer(); 85 const IndexAssignSpecializer();
86 86
87 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, 87 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
88 HInstruction input, 88 HInstruction input,
89 HTypeMap types, 89 HTypeMap types,
90 Compiler compiler) { 90 Compiler compiler) {
91 HInstruction index = instruction.inputs[2]; 91 HInstruction index = instruction.inputs[2];
92 if (input == instruction.inputs[1] && 92 if (input == instruction.inputs[1] &&
93 (index.isTypeUnknown(types) || index.isNumber(types))) { 93 (index.isTypeUnknown(types) || index.isNumber(types))) {
94 return HType.MUTABLE_ARRAY; 94 return HType.MUTABLE_ARRAY;
95 } 95 }
96 // The index should be an int when the receiver is a string or array. 96 // The index should be an int when the receiver is a string or array.
97 // However it turns out that inserting an integer check in the optimized 97 // However it turns out that inserting an integer check in the optimized
98 // version is cheaper than having another bailout case. This is true, 98 // version is cheaper than having another bailout case. This is true,
99 // because the integer check will simply throw if it fails. 99 // because the integer check will simply throw if it fails.
100 return HType.UNKNOWN; 100 return HType.UNKNOWN;
101 } 101 }
102 102
103 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, 103 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
104 HTypeMap types) { 104 HTypeMap types) {
105 if (instruction.inputs[1].isMutableArray(types)) { 105 if (instruction.inputs[1].isMutableArray(types)) {
106 return new HIndexAssign(instruction.inputs[1], 106 return new HIndexAssign(instruction.inputs[1],
107 instruction.inputs[2], 107 instruction.inputs[2],
108 instruction.inputs[3]); 108 instruction.inputs[3]);
109 } 109 }
110 return null; 110 return null;
111 } 111 }
112 } 112 }
113 113
114 class IndexSpecializer extends InvokeDynamicSpecializer { 114 class IndexSpecializer extends InvokeDynamicSpecializer {
115 const IndexSpecializer(); 115 const IndexSpecializer();
116 116
117 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, 117 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
118 HInstruction input, 118 HInstruction input,
119 HTypeMap types, 119 HTypeMap types,
120 Compiler compiler) { 120 Compiler compiler) {
121 HInstruction index = instruction.inputs[2]; 121 HInstruction index = instruction.inputs[2];
122 if (input == instruction.inputs[1] && 122 if (input == instruction.inputs[1] &&
123 (index.isTypeUnknown(types) || index.isNumber(types))) { 123 (index.isTypeUnknown(types) || index.isNumber(types))) {
124 return HType.INDEXABLE_PRIMITIVE; 124 return HType.INDEXABLE_PRIMITIVE;
125 } 125 }
126 // The index should be an int when the receiver is a string or array. 126 // The index should be an int when the receiver is a string or array.
127 // However it turns out that inserting an integer check in the optimized 127 // However it turns out that inserting an integer check in the optimized
128 // version is cheaper than having another bailout case. This is true, 128 // version is cheaper than having another bailout case. This is true,
129 // because the integer check will simply throw if it fails. 129 // because the integer check will simply throw if it fails.
130 return HType.UNKNOWN; 130 return HType.UNKNOWN;
131 } 131 }
132 132
133 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, 133 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
134 HTypeMap types) { 134 HTypeMap types) {
135 if (instruction.inputs[1].isIndexablePrimitive(types)) { 135 if (instruction.inputs[1].isIndexablePrimitive(types)) {
136 return new HIndex(instruction.inputs[1], instruction.inputs[2]); 136 return new HIndex(instruction.inputs[1], instruction.inputs[2]);
137 } 137 }
138 return null; 138 return null;
139 } 139 }
140 } 140 }
141 141
142 class BitNotSpecializer extends InvokeDynamicSpecializer { 142 class BitNotSpecializer extends InvokeDynamicSpecializer {
143 const BitNotSpecializer(); 143 const BitNotSpecializer();
144 144
145 UnaryOperation operation(ConstantSystem constantSystem) { 145 UnaryOperation operation(ConstantSystem constantSystem) {
146 return constantSystem.bitNot; 146 return constantSystem.bitNot;
147 } 147 }
148 148
149 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, 149 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
150 HInstruction input, 150 HInstruction input,
151 HTypeMap types, 151 HTypeMap types,
152 Compiler compiler) { 152 Compiler compiler) {
153 if (input == instruction.inputs[1]) { 153 if (input == instruction.inputs[1]) {
154 HType propagatedType = types[instruction]; 154 HType propagatedType = types[instruction];
155 if (propagatedType.isUnknown() || propagatedType.isNumber()) { 155 if (propagatedType.isUnknown() || propagatedType.isNumber()) {
156 return HType.INTEGER; 156 return HType.INTEGER;
157 } 157 }
158 } 158 }
159 return HType.UNKNOWN; 159 return HType.UNKNOWN;
160 } 160 }
161 161
162 HType computeTypeFromInputTypes(HInvokeDynamicMethod instruction, 162 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
163 HTypeMap types, 163 HTypeMap types,
164 Compiler compiler) { 164 Compiler compiler) {
165 // All bitwise operations on primitive types either produce an 165 // All bitwise operations on primitive types either produce an
166 // integer or throw an error. 166 // integer or throw an error.
167 if (instruction.inputs[1].isPrimitive(types)) return HType.INTEGER; 167 if (instruction.inputs[1].isPrimitive(types)) return HType.INTEGER;
168 return HType.UNKNOWN; 168 return HType.UNKNOWN;
169 } 169 }
170 170
171 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, 171 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
172 HTypeMap types) { 172 HTypeMap types) {
173 HInstruction input = instruction.inputs[1]; 173 HInstruction input = instruction.inputs[1];
174 if (input.isNumber(types)) return new HBitNot(input); 174 if (input.isNumber(types)) return new HBitNot(input);
175 return null; 175 return null;
176 } 176 }
177 } 177 }
178 178
179 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { 179 class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
180 const UnaryNegateSpecializer(); 180 const UnaryNegateSpecializer();
181 181
182 UnaryOperation operation(ConstantSystem constantSystem) { 182 UnaryOperation operation(ConstantSystem constantSystem) {
183 return constantSystem.negate; 183 return constantSystem.negate;
184 } 184 }
185 185
186 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, 186 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
187 HInstruction input, 187 HInstruction input,
188 HTypeMap types, 188 HTypeMap types,
189 Compiler compiler) { 189 Compiler compiler) {
190 if (input == instruction.inputs[1]) { 190 if (input == instruction.inputs[1]) {
191 HType propagatedType = types[instruction]; 191 HType propagatedType = types[instruction];
192 // If the outgoing type should be a number (integer, double or both) we 192 // If the outgoing type should be a number (integer, double or both) we
193 // want the outgoing type to be the input too. 193 // want the outgoing type to be the input too.
194 // If we don't know the outgoing type we try to make it a number. 194 // If we don't know the outgoing type we try to make it a number.
195 if (propagatedType.isNumber()) return propagatedType; 195 if (propagatedType.isNumber()) return propagatedType;
196 if (propagatedType.isUnknown()) return HType.NUMBER; 196 if (propagatedType.isUnknown()) return HType.NUMBER;
197 } 197 }
198 return HType.UNKNOWN; 198 return HType.UNKNOWN;
199 } 199 }
200 200
201 HType computeTypeFromInputTypes(HInvokeDynamicMethod instruction, 201 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
202 HTypeMap types, 202 HTypeMap types,
203 Compiler compiler) { 203 Compiler compiler) {
204 HType operandType = types[instruction.inputs[1]]; 204 HType operandType = types[instruction.inputs[1]];
205 if (operandType.isNumber()) return operandType; 205 if (operandType.isNumber()) return operandType;
206 return HType.UNKNOWN; 206 return HType.UNKNOWN;
207 } 207 }
208 208
209 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, 209 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
210 HTypeMap types) { 210 HTypeMap types) {
211 HInstruction input = instruction.inputs[1]; 211 HInstruction input = instruction.inputs[1];
212 if (input.isNumber(types)) return new HNegate(input); 212 if (input.isNumber(types)) return new HNegate(input);
213 return null; 213 return null;
214 } 214 }
215 } 215 }
216 216
217 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { 217 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
218 const BinaryArithmeticSpecializer(); 218 const BinaryArithmeticSpecializer();
219 219
220 HType computeTypeFromInputTypes(HInvokeDynamicMethod instruction, 220 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
221 HTypeMap types, 221 HTypeMap types,
222 Compiler compiler) { 222 Compiler compiler) {
223 HInstruction left = instruction.inputs[1]; 223 HInstruction left = instruction.inputs[1];
224 HInstruction right = instruction.inputs[2]; 224 HInstruction right = instruction.inputs[2];
225 if (left.isInteger(types) && right.isInteger(types)) return HType.INTEGER; 225 if (left.isInteger(types) && right.isInteger(types)) return HType.INTEGER;
226 if (left.isNumber(types)) { 226 if (left.isNumber(types)) {
227 if (left.isDouble(types) || right.isDouble(types)) return HType.DOUBLE; 227 if (left.isDouble(types) || right.isDouble(types)) return HType.DOUBLE;
228 return HType.NUMBER; 228 return HType.NUMBER;
229 } 229 }
230 return HType.UNKNOWN; 230 return HType.UNKNOWN;
231 } 231 }
232 232
233 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, 233 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
234 HInstruction input, 234 HInstruction input,
235 HTypeMap types, 235 HTypeMap types,
236 Compiler compiler) { 236 Compiler compiler) {
237 if (input == instruction.inputs[0]) return HType.UNKNOWN; 237 if (input == instruction.inputs[0]) return HType.UNKNOWN;
238 238
239 HType propagatedType = types[instruction]; 239 HType propagatedType = types[instruction];
240 // If the desired output type should be an integer we want to get two 240 // If the desired output type should be an integer we want to get two
241 // integers as arguments. 241 // integers as arguments.
242 if (propagatedType.isInteger()) return HType.INTEGER; 242 if (propagatedType.isInteger()) return HType.INTEGER;
243 // If the outgoing type should be a number we can get that if both inputs 243 // If the outgoing type should be a number we can get that if both inputs
244 // are numbers. If we don't know the outgoing type we try to make it a 244 // are numbers. If we don't know the outgoing type we try to make it a
245 // number. 245 // number.
246 if (propagatedType.isUnknown() || propagatedType.isNumber()) { 246 if (propagatedType.isUnknown() || propagatedType.isNumber()) {
247 return HType.NUMBER; 247 return HType.NUMBER;
248 } 248 }
249 // Even if the desired outgoing type is not a number we still want the 249 // Even if the desired outgoing type is not a number we still want the
250 // second argument to be a number if the first one is a number. This will 250 // second argument to be a number if the first one is a number. This will
251 // not help for the outgoing type, but at least the binary arithmetic 251 // not help for the outgoing type, but at least the binary arithmetic
252 // operation will not have type problems. 252 // operation will not have type problems.
253 // TODO(floitsch): normally we shouldn't request a number, but simply 253 // TODO(floitsch): normally we shouldn't request a number, but simply
254 // throw an ArgumentError if it isn't. This would be similar 254 // throw an ArgumentError if it isn't. This would be similar
255 // to the array case. 255 // to the array case.
256 HInstruction left = instruction.inputs[1]; 256 HInstruction left = instruction.inputs[1];
257 HInstruction right = instruction.inputs[2]; 257 HInstruction right = instruction.inputs[2];
258 if (input == right && left.isNumber(types)) return HType.NUMBER; 258 if (input == right && left.isNumber(types)) return HType.NUMBER;
259 return HType.UNKNOWN; 259 return HType.UNKNOWN;
260 } 260 }
261 261
262 bool isBuiltin(HInvokeDynamicMethod instruction, HTypeMap types) { 262 bool isBuiltin(HInvokeDynamic instruction, HTypeMap types) {
263 return instruction.inputs[1].isNumber(types) 263 return instruction.inputs[1].isNumber(types)
264 && instruction.inputs[2].isNumber(types); 264 && instruction.inputs[2].isNumber(types);
265 } 265 }
266 266
267 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, 267 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
268 HTypeMap types) { 268 HTypeMap types) {
269 if (isBuiltin(instruction, types)) { 269 if (isBuiltin(instruction, types)) {
270 HInstruction builtin = 270 HInstruction builtin =
271 newBuiltinVariant(instruction.inputs[1], instruction.inputs[2]); 271 newBuiltinVariant(instruction.inputs[1], instruction.inputs[2]);
272 if (builtin != null) return builtin; 272 if (builtin != null) return builtin;
273 // Even if there is no builtin equivalent instruction, we know 273 // Even if there is no builtin equivalent instruction, we know
274 // the instruction does not have any side effect, and that it 274 // the instruction does not have any side effect, and that it
275 // can be GVN'ed. 275 // can be GVN'ed.
276 instruction.clearAllSideEffects(); 276 instruction.clearAllSideEffects();
277 instruction.clearAllDependencies(); 277 instruction.clearAllDependencies();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 372
373 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { 373 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) {
374 // Truncating divide does not have a JS equivalent. 374 // Truncating divide does not have a JS equivalent.
375 return null; 375 return null;
376 } 376 }
377 } 377 }
378 378
379 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { 379 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
380 const BinaryBitOpSpecializer(); 380 const BinaryBitOpSpecializer();
381 381
382 HType computeTypeFromInputTypes(HInvokeDynamicMethod instruction, 382 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
383 HTypeMap types, 383 HTypeMap types,
384 Compiler compiler) { 384 Compiler compiler) {
385 // All bitwise operations on primitive types either produce an 385 // All bitwise operations on primitive types either produce an
386 // integer or throw an error. 386 // integer or throw an error.
387 HInstruction left = instruction.inputs[1]; 387 HInstruction left = instruction.inputs[1];
388 if (left.isPrimitive(types)) return HType.INTEGER; 388 if (left.isPrimitive(types)) return HType.INTEGER;
389 return HType.UNKNOWN; 389 return HType.UNKNOWN;
390 } 390 }
391 391
392 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, 392 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
393 HInstruction input, 393 HInstruction input,
394 HTypeMap types, 394 HTypeMap types,
395 Compiler compiler) { 395 Compiler compiler) {
396 if (input == instruction.inputs[0]) return HType.UNKNOWN; 396 if (input == instruction.inputs[0]) return HType.UNKNOWN;
397 HType propagatedType = types[instruction]; 397 HType propagatedType = types[instruction];
398 // If the outgoing type should be a number we can get that only if both 398 // If the outgoing type should be a number we can get that only if both
399 // inputs are integers. If we don't know the outgoing type we try to make 399 // inputs are integers. If we don't know the outgoing type we try to make
400 // it an integer. 400 // it an integer.
401 if (propagatedType.isUnknown() || propagatedType.isNumber()) { 401 if (propagatedType.isUnknown() || propagatedType.isNumber()) {
402 return HType.INTEGER; 402 return HType.INTEGER;
403 } 403 }
404 return HType.UNKNOWN; 404 return HType.UNKNOWN;
405 } 405 }
406 } 406 }
407 407
408 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { 408 class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
409 const ShiftLeftSpecializer(); 409 const ShiftLeftSpecializer();
410 410
411 BinaryOperation operation(ConstantSystem constantSystem) { 411 BinaryOperation operation(ConstantSystem constantSystem) {
412 return constantSystem.shiftLeft; 412 return constantSystem.shiftLeft;
413 } 413 }
414 414
415 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, 415 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
416 HTypeMap types) { 416 HTypeMap types) {
417 HInstruction left = instruction.inputs[1]; 417 HInstruction left = instruction.inputs[1];
418 HInstruction right = instruction.inputs[2]; 418 HInstruction right = instruction.inputs[2];
419 if (!left.isNumber(types) || !right.isConstantInteger()) return null; 419 if (!left.isNumber(types) || !right.isConstantInteger()) return null;
420 HConstant rightConstant = right; 420 HConstant rightConstant = right;
421 IntConstant intConstant = rightConstant.constant; 421 IntConstant intConstant = rightConstant.constant;
422 int count = intConstant.value; 422 int count = intConstant.value;
423 if (count >= 0 && count <= 31) { 423 if (count >= 0 && count <= 31) {
424 return newBuiltinVariant(left, right); 424 return newBuiltinVariant(left, right);
425 } 425 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 } 476 }
477 477
478 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { 478 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) {
479 return new HBitXor(left, right); 479 return new HBitXor(left, right);
480 } 480 }
481 } 481 }
482 482
483 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { 483 abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
484 const RelationalSpecializer(); 484 const RelationalSpecializer();
485 485
486 HType computeTypeFromInputTypes(HInvokeDynamicMethod instruction, 486 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
487 HTypeMap types, 487 HTypeMap types,
488 Compiler compiler) { 488 Compiler compiler) {
489 if (types[instruction.inputs[1]].isPrimitiveOrNull()) return HType.BOOLEAN; 489 if (types[instruction.inputs[1]].isPrimitiveOrNull()) return HType.BOOLEAN;
490 return HType.UNKNOWN; 490 return HType.UNKNOWN;
491 } 491 }
492 492
493 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, 493 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
494 HInstruction input, 494 HInstruction input,
495 HTypeMap types, 495 HTypeMap types,
496 Compiler compiler) { 496 Compiler compiler) {
497 if (input == instruction.inputs[0]) return HType.UNKNOWN; 497 if (input == instruction.inputs[0]) return HType.UNKNOWN;
498 HType propagatedType = types[instruction]; 498 HType propagatedType = types[instruction];
499 // For all relational operations except HIdentity, we expect to get numbers 499 // For all relational operations except HIdentity, we expect to get numbers
500 // only. With numbers the outgoing type is a boolean. If something else 500 // only. With numbers the outgoing type is a boolean. If something else
501 // is desired, then numbers are incorrect, though. 501 // is desired, then numbers are incorrect, though.
502 if (propagatedType.isUnknown() || propagatedType.isBoolean()) { 502 if (propagatedType.isUnknown() || propagatedType.isBoolean()) {
503 HInstruction left = instruction.inputs[1]; 503 HInstruction left = instruction.inputs[1];
504 if (left.isTypeUnknown(types) || left.isNumber(types)) { 504 if (left.isTypeUnknown(types) || left.isNumber(types)) {
505 return HType.NUMBER; 505 return HType.NUMBER;
506 } 506 }
507 } 507 }
508 return HType.UNKNOWN; 508 return HType.UNKNOWN;
509 } 509 }
510 510
511 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, 511 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
512 HTypeMap types) { 512 HTypeMap types) {
513 HInstruction left = instruction.inputs[1]; 513 HInstruction left = instruction.inputs[1];
514 HInstruction right = instruction.inputs[2]; 514 HInstruction right = instruction.inputs[2];
515 if (left.isNumber(types) && right.isNumber(types)) { 515 if (left.isNumber(types) && right.isNumber(types)) {
516 return newBuiltinVariant(left, right); 516 return newBuiltinVariant(left, right);
517 } 517 }
518 return null; 518 return null;
519 } 519 }
520 520
521 HInstruction newBuiltinVariant(HInstruction left, HInstruction right); 521 HInstruction newBuiltinVariant(HInstruction left, HInstruction right);
522 } 522 }
523 523
524 class EqualsSpecializer extends RelationalSpecializer { 524 class EqualsSpecializer extends RelationalSpecializer {
525 const EqualsSpecializer(); 525 const EqualsSpecializer();
526 526
527 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, 527 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
528 HInstruction input, 528 HInstruction input,
529 HTypeMap types, 529 HTypeMap types,
530 Compiler compiler) { 530 Compiler compiler) {
531 HInstruction left = instruction.inputs[1]; 531 HInstruction left = instruction.inputs[1];
532 HInstruction right = instruction.inputs[2]; 532 HInstruction right = instruction.inputs[2];
533 HType propagatedType = types[instruction]; 533 HType propagatedType = types[instruction];
534 if (input == left && types[right].isUseful()) { 534 if (input == left && types[right].isUseful()) {
535 // All our useful types have 'identical' semantics. But we don't want to 535 // All our useful types have 'identical' semantics. But we don't want to
536 // speculatively test for all possible types. Therefore we try to match 536 // speculatively test for all possible types. Therefore we try to match
537 // the two types. That is, if we see x == 3, then we speculatively test 537 // the two types. That is, if we see x == 3, then we speculatively test
538 // if x is a number and bailout if it isn't. 538 // if x is a number and bailout if it isn't.
539 // If right is a number we don't need more than a number (no need to match 539 // If right is a number we don't need more than a number (no need to match
540 // the exact type of right). 540 // the exact type of right).
541 if (right.isNumber(types)) return HType.NUMBER; 541 if (right.isNumber(types)) return HType.NUMBER;
542 return types[right]; 542 return types[right];
543 } 543 }
544 // String equality testing is much more common than array equality testing. 544 // String equality testing is much more common than array equality testing.
545 if (input == left && left.isIndexablePrimitive(types)) { 545 if (input == left && left.isIndexablePrimitive(types)) {
546 return HType.READABLE_ARRAY; 546 return HType.READABLE_ARRAY;
547 } 547 }
548 // String equality testing is much more common than array equality testing. 548 // String equality testing is much more common than array equality testing.
549 if (input == right && right.isIndexablePrimitive(types)) { 549 if (input == right && right.isIndexablePrimitive(types)) {
550 return HType.STRING; 550 return HType.STRING;
551 } 551 }
552 return HType.UNKNOWN; 552 return HType.UNKNOWN;
553 } 553 }
554 554
555 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, 555 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
556 HTypeMap types) { 556 HTypeMap types) {
557 HInstruction left = instruction.inputs[1]; 557 HInstruction left = instruction.inputs[1];
558 HInstruction right = instruction.inputs[2]; 558 HInstruction right = instruction.inputs[2];
559 if (types[left].isPrimitiveOrNull() || right.isConstantNull()) { 559 if (types[left].isPrimitiveOrNull() || right.isConstantNull()) {
560 return newBuiltinVariant(left, right); 560 return newBuiltinVariant(left, right);
561 } 561 }
562 return null; 562 return null;
563 } 563 }
564 564
565 BinaryOperation operation(ConstantSystem constantSystem) { 565 BinaryOperation operation(ConstantSystem constantSystem) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 const LessEqualSpecializer(); 611 const LessEqualSpecializer();
612 612
613 BinaryOperation operation(ConstantSystem constantSystem) { 613 BinaryOperation operation(ConstantSystem constantSystem) {
614 return constantSystem.lessEqual; 614 return constantSystem.lessEqual;
615 } 615 }
616 616
617 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { 617 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) {
618 return new HLessEqual(left, right); 618 return new HLessEqual(left, right);
619 } 619 }
620 } 620 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698