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

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

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (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) 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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of ssa;
6
7 /**
8 * [InvokeDynamicSpecializer] and its subclasses are helpers to
9 * optimize intercepted dynamic calls. It knows what input types
10 * would be beneficial for performance, and how to change a invoke
11 * dynamic to a builtin instruction (e.g. HIndex, HBitNot).
12 */
13 class InvokeDynamicSpecializer {
14 const InvokeDynamicSpecializer();
15
16 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
17 Compiler compiler) {
18 Selector selector = instruction.selector;
19 return TypeMaskFactory.inferredTypeForSelector(selector, compiler);
20 }
21
22 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
23 Compiler compiler) {
24 return null;
25 }
26
27 Operation operation(ConstantSystem constantSystem) => null;
28
29 static InvokeDynamicSpecializer lookupSpecializer(Selector selector) {
30 if (selector.kind == SelectorKind.INDEX) {
31 return selector.name == '[]'
32 ? const IndexSpecializer()
33 : const IndexAssignSpecializer();
34 } else if (selector.kind == SelectorKind.OPERATOR) {
35 if (selector.name == 'unary-') {
36 return const UnaryNegateSpecializer();
37 } else if (selector.name == '~') {
38 return const BitNotSpecializer();
39 } else if (selector.name == '+') {
40 return const AddSpecializer();
41 } else if (selector.name == '-') {
42 return const SubtractSpecializer();
43 } else if (selector.name == '*') {
44 return const MultiplySpecializer();
45 } else if (selector.name == '/') {
46 return const DivideSpecializer();
47 } else if (selector.name == '~/') {
48 return const TruncatingDivideSpecializer();
49 } else if (selector.name == '%') {
50 return const ModuloSpecializer();
51 } else if (selector.name == '>>') {
52 return const ShiftRightSpecializer();
53 } else if (selector.name == '<<') {
54 return const ShiftLeftSpecializer();
55 } else if (selector.name == '&') {
56 return const BitAndSpecializer();
57 } else if (selector.name == '|') {
58 return const BitOrSpecializer();
59 } else if (selector.name == '^') {
60 return const BitXorSpecializer();
61 } else if (selector.name == '==') {
62 return const EqualsSpecializer();
63 } else if (selector.name == '<') {
64 return const LessSpecializer();
65 } else if (selector.name == '<=') {
66 return const LessEqualSpecializer();
67 } else if (selector.name == '>') {
68 return const GreaterSpecializer();
69 } else if (selector.name == '>=') {
70 return const GreaterEqualSpecializer();
71 }
72 } else if (selector.kind == SelectorKind.CALL) {
73 if (selector.argumentCount == 1 && selector.namedArguments.length == 0) {
74 if (selector.name == 'codeUnitAt') {
75 return const CodeUnitAtSpecializer();
76 }
77 }
78 }
79 return const InvokeDynamicSpecializer();
80 }
81 }
82
83 class IndexAssignSpecializer extends InvokeDynamicSpecializer {
84 const IndexAssignSpecializer();
85
86 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
87 Compiler compiler) {
88 if (instruction.inputs[1].isMutableIndexable(compiler)) {
89 if (!instruction.inputs[2].isInteger(compiler)
90 && compiler.enableTypeAssertions) {
91 // We want the right checked mode error.
92 return null;
93 }
94 return new HIndexAssign(instruction.inputs[1],
95 instruction.inputs[2],
96 instruction.inputs[3],
97 instruction.selector);
98 }
99 return null;
100 }
101 }
102
103 class IndexSpecializer extends InvokeDynamicSpecializer {
104 const IndexSpecializer();
105
106 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
107 Compiler compiler) {
108 if (!instruction.inputs[1].isIndexablePrimitive(compiler)) return null;
109 if (!instruction.inputs[2].isInteger(compiler)
110 && compiler.enableTypeAssertions) {
111 // We want the right checked mode error.
112 return null;
113 }
114 TypeMask receiverType =
115 instruction.getDartReceiver(compiler).instructionType;
116 Selector refined = new TypedSelector(receiverType, instruction.selector,
117 compiler.world);
118 TypeMask type = TypeMaskFactory.inferredTypeForSelector(refined, compiler);
119 return new HIndex(
120 instruction.inputs[1], instruction.inputs[2],
121 instruction.selector, type);
122 }
123 }
124
125 class BitNotSpecializer extends InvokeDynamicSpecializer {
126 const BitNotSpecializer();
127
128 UnaryOperation operation(ConstantSystem constantSystem) {
129 return constantSystem.bitNot;
130 }
131
132 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
133 Compiler compiler) {
134 // All bitwise operations on primitive types either produce an
135 // integer or throw an error.
136 JavaScriptBackend backend = compiler.backend;
137 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) {
138 return backend.uint32Type;
139 }
140 return super.computeTypeFromInputTypes(instruction, compiler);
141 }
142
143 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
144 Compiler compiler) {
145 JavaScriptBackend backend = compiler.backend;
146 HInstruction input = instruction.inputs[1];
147 if (input.isNumber(compiler)) {
148 return new HBitNot(input, instruction.selector,
149 computeTypeFromInputTypes(instruction, compiler));
150 }
151 return null;
152 }
153 }
154
155 class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
156 const UnaryNegateSpecializer();
157
158 UnaryOperation operation(ConstantSystem constantSystem) {
159 return constantSystem.negate;
160 }
161
162 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
163 Compiler compiler) {
164 TypeMask operandType = instruction.inputs[1].instructionType;
165 if (instruction.inputs[1].isNumberOrNull(compiler)) return operandType;
166 return super.computeTypeFromInputTypes(instruction, compiler);
167 }
168
169 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
170 Compiler compiler) {
171 HInstruction input = instruction.inputs[1];
172 if (input.isNumber(compiler)) {
173 return new HNegate(input, instruction.selector, input.instructionType);
174 }
175 return null;
176 }
177 }
178
179 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
180 const BinaryArithmeticSpecializer();
181
182 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
183 Compiler compiler) {
184 HInstruction left = instruction.inputs[1];
185 HInstruction right = instruction.inputs[2];
186 JavaScriptBackend backend = compiler.backend;
187 if (left.isIntegerOrNull(compiler) && right.isIntegerOrNull(compiler)) {
188 return backend.intType;
189 }
190 if (left.isNumberOrNull(compiler)) {
191 if (left.isDoubleOrNull(compiler) || right.isDoubleOrNull(compiler)) {
192 return backend.doubleType;
193 }
194 return backend.numType;
195 }
196 return super.computeTypeFromInputTypes(instruction, compiler);
197 }
198
199 bool isBuiltin(HInvokeDynamic instruction, Compiler compiler) {
200 return instruction.inputs[1].isNumber(compiler)
201 && instruction.inputs[2].isNumber(compiler);
202 }
203
204 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
205 Compiler compiler) {
206 if (isBuiltin(instruction, compiler)) {
207 HInstruction builtin = newBuiltinVariant(instruction, compiler);
208 if (builtin != null) return builtin;
209 // Even if there is no builtin equivalent instruction, we know
210 // the instruction does not have any side effect, and that it
211 // can be GVN'ed.
212 clearAllSideEffects(instruction);
213 }
214 return null;
215 }
216
217 void clearAllSideEffects(HInstruction instruction) {
218 instruction.sideEffects.clearAllSideEffects();
219 instruction.sideEffects.clearAllDependencies();
220 instruction.setUseGvn();
221 }
222
223 bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) {
224 HInstruction left = instruction.inputs[1];
225 HInstruction right = instruction.inputs[2];
226 JavaScriptBackend backend = compiler.backend;
227 return left.isPositiveIntegerOrNull(compiler)
228 && right.isPositiveIntegerOrNull(compiler);
229 }
230
231 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler);
232
233 Selector renameToOptimizedSelector(String name,
234 Selector selector,
235 Compiler compiler) {
236 if (selector.name == name) return selector;
237 JavaScriptBackend backend = compiler.backend;
238 Selector newSelector = new Selector(
239 SelectorKind.CALL, name, backend.interceptorsLibrary,
240 selector.argumentCount);
241 return selector.mask == null
242 ? newSelector
243 : new TypedSelector(selector.mask, newSelector, compiler.world);
244 }
245 }
246
247 class AddSpecializer extends BinaryArithmeticSpecializer {
248 const AddSpecializer();
249
250 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
251 Compiler compiler) {
252 if (inputsArePositiveIntegers(instruction, compiler)) {
253 JavaScriptBackend backend = compiler.backend;
254 return backend.positiveIntType;
255 }
256 return super.computeTypeFromInputTypes(instruction, compiler);
257 }
258
259 BinaryOperation operation(ConstantSystem constantSystem) {
260 return constantSystem.add;
261 }
262
263 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
264 Compiler compiler) {
265 return new HAdd(
266 instruction.inputs[1], instruction.inputs[2],
267 instruction.selector, computeTypeFromInputTypes(instruction, compiler));
268 }
269 }
270
271 class DivideSpecializer extends BinaryArithmeticSpecializer {
272 const DivideSpecializer();
273
274 BinaryOperation operation(ConstantSystem constantSystem) {
275 return constantSystem.divide;
276 }
277
278 TypeMask computeTypeFromInputTypes(HInstruction instruction,
279 Compiler compiler) {
280 HInstruction left = instruction.inputs[1];
281 JavaScriptBackend backend = compiler.backend;
282 if (left.isNumberOrNull(compiler)) {
283 return backend.doubleType;
284 }
285 return super.computeTypeFromInputTypes(instruction, compiler);
286 }
287
288 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
289 Compiler compiler) {
290 JavaScriptBackend backend = compiler.backend;
291 return new HDivide(
292 instruction.inputs[1], instruction.inputs[2],
293 instruction.selector, backend.doubleType);
294 }
295 }
296
297 class ModuloSpecializer extends BinaryArithmeticSpecializer {
298 const ModuloSpecializer();
299
300 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
301 Compiler compiler) {
302 if (inputsArePositiveIntegers(instruction, compiler)) {
303 JavaScriptBackend backend = compiler.backend;
304 return backend.positiveIntType;
305 }
306 return super.computeTypeFromInputTypes(instruction, compiler);
307 }
308
309 BinaryOperation operation(ConstantSystem constantSystem) {
310 return constantSystem.modulo;
311 }
312
313 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
314 Compiler compiler) {
315 // Modulo cannot be mapped to the native operator (different semantics).
316 return null;
317 }
318 }
319
320 class MultiplySpecializer extends BinaryArithmeticSpecializer {
321 const MultiplySpecializer();
322
323 BinaryOperation operation(ConstantSystem constantSystem) {
324 return constantSystem.multiply;
325 }
326
327 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
328 Compiler compiler) {
329 if (inputsArePositiveIntegers(instruction, compiler)) {
330 JavaScriptBackend backend = compiler.backend;
331 return backend.positiveIntType;
332 }
333 return super.computeTypeFromInputTypes(instruction, compiler);
334 }
335
336 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
337 Compiler compiler) {
338 return new HMultiply(
339 instruction.inputs[1], instruction.inputs[2],
340 instruction.selector, computeTypeFromInputTypes(instruction, compiler));
341 }
342 }
343
344 class SubtractSpecializer extends BinaryArithmeticSpecializer {
345 const SubtractSpecializer();
346
347 BinaryOperation operation(ConstantSystem constantSystem) {
348 return constantSystem.subtract;
349 }
350
351 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
352 Compiler compiler) {
353 return new HSubtract(
354 instruction.inputs[1], instruction.inputs[2],
355 instruction.selector, computeTypeFromInputTypes(instruction, compiler));
356 }
357 }
358
359 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
360 const TruncatingDivideSpecializer();
361
362 BinaryOperation operation(ConstantSystem constantSystem) {
363 return constantSystem.truncatingDivide;
364 }
365
366 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
367 Compiler compiler) {
368 if (inputsArePositiveIntegers(instruction, compiler)) {
369 JavaScriptBackend backend = compiler.backend;
370 return backend.positiveIntType;
371 }
372 return super.computeTypeFromInputTypes(instruction, compiler);
373 }
374
375 bool isNotZero(HInstruction instruction, Compiler compiler) {
376 if (!instruction.isConstantInteger()) return false;
377 HConstant rightConstant = instruction;
378 IntConstantValue intConstant = rightConstant.constant;
379 int count = intConstant.primitiveValue;
380 return count != 0;
381 }
382
383 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
384 Compiler compiler) {
385 HInstruction left = instruction.inputs[1];
386 HInstruction right = instruction.inputs[2];
387 if (isBuiltin(instruction, compiler)) {
388 if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) {
389 if (left.isUInt31(compiler)) {
390 return newBuiltinVariant(instruction, compiler);
391 }
392 // We can call _tdivFast because the rhs is a 32bit integer
393 // and not 0, nor -1.
394 instruction.selector = renameToOptimizedSelector(
395 '_tdivFast', instruction.selector, compiler);
396 }
397 clearAllSideEffects(instruction);
398 }
399 return null;
400 }
401
402 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
403 Compiler compiler) {
404 return new HTruncatingDivide(
405 instruction.inputs[1], instruction.inputs[2],
406 instruction.selector, computeTypeFromInputTypes(instruction, compiler));
407 }
408 }
409
410 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
411 const BinaryBitOpSpecializer();
412
413 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
414 Compiler compiler) {
415 // All bitwise operations on primitive types either produce an
416 // integer or throw an error.
417 HInstruction left = instruction.inputs[1];
418 JavaScriptBackend backend = compiler.backend;
419 if (left.isPrimitiveOrNull(compiler)) {
420 return backend.uint32Type;
421 }
422 return super.computeTypeFromInputTypes(instruction, compiler);
423 }
424
425 bool argumentLessThan32(HInstruction instruction) {
426 if (!instruction.isConstantInteger()) return false;
427 HConstant rightConstant = instruction;
428 IntConstantValue intConstant = rightConstant.constant;
429 int count = intConstant.primitiveValue;
430 return count >= 0 && count <= 31;
431 }
432
433 bool isPositive(HInstruction instruction, Compiler compiler) {
434 // TODO: We should use the value range analysis. Currently, ranges
435 // are discarded just after the analysis.
436 return instruction.isPositiveInteger(compiler);
437 }
438 }
439
440 class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
441 const ShiftLeftSpecializer();
442
443 BinaryOperation operation(ConstantSystem constantSystem) {
444 return constantSystem.shiftLeft;
445 }
446
447 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
448 Compiler compiler) {
449 HInstruction left = instruction.inputs[1];
450 HInstruction right = instruction.inputs[2];
451 if (left.isNumber(compiler)) {
452 if (argumentLessThan32(right)) {
453 return newBuiltinVariant(instruction, compiler);
454 }
455 // Even if there is no builtin equivalent instruction, we know
456 // the instruction does not have any side effect, and that it
457 // can be GVN'ed.
458 clearAllSideEffects(instruction);
459 Selector selector = instruction.selector;
460 if (isPositive(right, compiler)) {
461 instruction.selector = renameToOptimizedSelector(
462 '_shlPositive', instruction.selector, compiler);
463 }
464 }
465 return null;
466 }
467
468 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
469 Compiler compiler) {
470 JavaScriptBackend backend = compiler.backend;
471 return new HShiftLeft(
472 instruction.inputs[1], instruction.inputs[2],
473 instruction.selector, computeTypeFromInputTypes(instruction, compiler));
474 }
475 }
476
477 class ShiftRightSpecializer extends BinaryBitOpSpecializer {
478 const ShiftRightSpecializer();
479
480 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
481 Compiler compiler) {
482 HInstruction left = instruction.inputs[1];
483 HInstruction right = instruction.inputs[2];
484 JavaScriptBackend backend = compiler.backend;
485 if (left.isUInt32(compiler)) return left.instructionType;
486 return super.computeTypeFromInputTypes(instruction, compiler);
487 }
488
489 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
490 Compiler compiler) {
491 HInstruction left = instruction.inputs[1];
492 HInstruction right = instruction.inputs[2];
493 if (left.isNumber(compiler)) {
494 if (argumentLessThan32(right) && isPositive(left, compiler)) {
495 return newBuiltinVariant(instruction, compiler);
496 }
497 // Even if there is no builtin equivalent instruction, we know
498 // the instruction does not have any side effect, and that it
499 // can be GVN'ed.
500 clearAllSideEffects(instruction);
501 if (isPositive(right, compiler) && isPositive(left, compiler)) {
502 instruction.selector = renameToOptimizedSelector(
503 '_shrBothPositive', instruction.selector, compiler);
504 } else if (isPositive(left, compiler) && right.isNumber(compiler)) {
505 instruction.selector = renameToOptimizedSelector(
506 '_shrReceiverPositive', instruction.selector, compiler);
507 } else if (isPositive(right, compiler)) {
508 instruction.selector = renameToOptimizedSelector(
509 '_shrOtherPositive', instruction.selector, compiler);
510 }
511 }
512 return null;
513 }
514
515 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
516 Compiler compiler) {
517 JavaScriptBackend backend = compiler.backend;
518 return new HShiftRight(
519 instruction.inputs[1], instruction.inputs[2],
520 instruction.selector, computeTypeFromInputTypes(instruction, compiler));
521 }
522
523 BinaryOperation operation(ConstantSystem constantSystem) {
524 return constantSystem.shiftRight;
525 }
526 }
527
528 class BitOrSpecializer extends BinaryBitOpSpecializer {
529 const BitOrSpecializer();
530
531 BinaryOperation operation(ConstantSystem constantSystem) {
532 return constantSystem.bitOr;
533 }
534
535 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
536 Compiler compiler) {
537 HInstruction left = instruction.inputs[1];
538 HInstruction right = instruction.inputs[2];
539 JavaScriptBackend backend = compiler.backend;
540 if (left.isUInt31(compiler) && right.isUInt31(compiler)) {
541 return backend.uint31Type;
542 }
543 return super.computeTypeFromInputTypes(instruction, compiler);
544 }
545
546 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
547 Compiler compiler) {
548 JavaScriptBackend backend = compiler.backend;
549 return new HBitOr(
550 instruction.inputs[1], instruction.inputs[2],
551 instruction.selector, computeTypeFromInputTypes(instruction, compiler));
552 }
553 }
554
555 class BitAndSpecializer extends BinaryBitOpSpecializer {
556 const BitAndSpecializer();
557
558 BinaryOperation operation(ConstantSystem constantSystem) {
559 return constantSystem.bitAnd;
560 }
561
562 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
563 Compiler compiler) {
564 HInstruction left = instruction.inputs[1];
565 HInstruction right = instruction.inputs[2];
566 JavaScriptBackend backend = compiler.backend;
567 if (left.isUInt31(compiler) || right.isUInt31(compiler)) {
568 return backend.uint31Type;
569 }
570 return super.computeTypeFromInputTypes(instruction, compiler);
571 }
572
573 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
574 Compiler compiler) {
575 JavaScriptBackend backend = compiler.backend;
576 return new HBitAnd(
577 instruction.inputs[1], instruction.inputs[2],
578 instruction.selector, computeTypeFromInputTypes(instruction, compiler));
579 }
580 }
581
582 class BitXorSpecializer extends BinaryBitOpSpecializer {
583 const BitXorSpecializer();
584
585 BinaryOperation operation(ConstantSystem constantSystem) {
586 return constantSystem.bitXor;
587 }
588
589 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
590 Compiler compiler) {
591 HInstruction left = instruction.inputs[1];
592 HInstruction right = instruction.inputs[2];
593 JavaScriptBackend backend = compiler.backend;
594 if (left.isUInt31(compiler) && right.isUInt31(compiler)) {
595 return backend.uint31Type;
596 }
597 return super.computeTypeFromInputTypes(instruction, compiler);
598 }
599
600 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
601 Compiler compiler) {
602 JavaScriptBackend backend = compiler.backend;
603 return new HBitXor(
604 instruction.inputs[1], instruction.inputs[2],
605 instruction.selector, computeTypeFromInputTypes(instruction, compiler));
606 }
607 }
608
609 abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
610 const RelationalSpecializer();
611
612 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
613 Compiler compiler) {
614 JavaScriptBackend backend = compiler.backend;
615 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) {
616 return backend.boolType;
617 }
618 return super.computeTypeFromInputTypes(instruction, compiler);
619 }
620
621 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
622 Compiler compiler) {
623 HInstruction left = instruction.inputs[1];
624 HInstruction right = instruction.inputs[2];
625 if (left.isNumber(compiler) && right.isNumber(compiler)) {
626 return newBuiltinVariant(instruction, compiler);
627 }
628 return null;
629 }
630
631 HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler);
632 }
633
634 class EqualsSpecializer extends RelationalSpecializer {
635 const EqualsSpecializer();
636
637 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
638 Compiler compiler) {
639 HInstruction left = instruction.inputs[1];
640 HInstruction right = instruction.inputs[2];
641 TypeMask instructionType = left.instructionType;
642 if (right.isConstantNull() || left.isPrimitiveOrNull(compiler)) {
643 return newBuiltinVariant(instruction, compiler);
644 }
645 World world = compiler.world;
646 Selector selector =
647 new TypedSelector(instructionType, instruction.selector, world);
648 JavaScriptBackend backend = compiler.backend;
649 Iterable<Element> matches = world.allFunctions.filter(selector);
650 // This test relies the on `Object.==` and `Interceptor.==` always being
651 // implemented because if the selector matches by subtype, it still will be
652 // a regular object or an interceptor.
653 if (matches.every(backend.isDefaultEqualityImplementation)) {
654 return newBuiltinVariant(instruction, compiler);
655 }
656 return null;
657 }
658
659 BinaryOperation operation(ConstantSystem constantSystem) {
660 return constantSystem.equal;
661 }
662
663 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
664 Compiler compiler) {
665 JavaScriptBackend backend = compiler.backend;
666 return new HIdentity(
667 instruction.inputs[1], instruction.inputs[2],
668 instruction.selector, backend.boolType);
669 }
670 }
671
672 class LessSpecializer extends RelationalSpecializer {
673 const LessSpecializer();
674
675 BinaryOperation operation(ConstantSystem constantSystem) {
676 return constantSystem.less;
677 }
678
679 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
680 Compiler compiler) {
681 JavaScriptBackend backend = compiler.backend;
682 return new HLess(
683 instruction.inputs[1], instruction.inputs[2],
684 instruction.selector, backend.boolType);
685 }
686 }
687
688 class GreaterSpecializer extends RelationalSpecializer {
689 const GreaterSpecializer();
690
691 BinaryOperation operation(ConstantSystem constantSystem) {
692 return constantSystem.greater;
693 }
694
695 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
696 Compiler compiler) {
697 JavaScriptBackend backend = compiler.backend;
698 return new HGreater(
699 instruction.inputs[1], instruction.inputs[2],
700 instruction.selector, backend.boolType);
701 }
702 }
703
704 class GreaterEqualSpecializer extends RelationalSpecializer {
705 const GreaterEqualSpecializer();
706
707 BinaryOperation operation(ConstantSystem constantSystem) {
708 return constantSystem.greaterEqual;
709 }
710
711 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
712 Compiler compiler) {
713 JavaScriptBackend backend = compiler.backend;
714 return new HGreaterEqual(
715 instruction.inputs[1], instruction.inputs[2],
716 instruction.selector, backend.boolType);
717 }
718 }
719
720 class LessEqualSpecializer extends RelationalSpecializer {
721 const LessEqualSpecializer();
722
723 BinaryOperation operation(ConstantSystem constantSystem) {
724 return constantSystem.lessEqual;
725 }
726
727 HInstruction newBuiltinVariant(HInvokeDynamic instruction,
728 Compiler compiler) {
729 JavaScriptBackend backend = compiler.backend;
730 return new HLessEqual(
731 instruction.inputs[1], instruction.inputs[2],
732 instruction.selector, backend.boolType);
733 }
734 }
735
736 class CodeUnitAtSpecializer extends InvokeDynamicSpecializer {
737 const CodeUnitAtSpecializer();
738
739 BinaryOperation operation(ConstantSystem constantSystem) {
740 return constantSystem.codeUnitAt;
741 }
742
743 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
744 Compiler compiler) {
745 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index
746 // bounds checking optimizations as for HIndex.
747 return null;
748 }
749 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698