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

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

Issue 12974002: Convert a == to a builtin identity check if the receiver type can only hit Object==. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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(HInvokeDynamic instruction, 16 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
17 HInstruction input, 17 HInstruction input,
18 Compiler compiler) { 18 Compiler compiler) {
19 return HType.UNKNOWN; 19 return HType.UNKNOWN;
20 } 20 }
21 21
22 HType computeTypeFromInputTypes(HInvokeDynamic instruction, 22 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
23 Compiler compiler) { 23 Compiler compiler) {
24 return instruction.instructionType; 24 return instruction.instructionType;
25 } 25 }
26 26
27 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) { 27 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
28 Compiler compiler) {
28 return null; 29 return null;
29 } 30 }
30 31
31 Operation operation(ConstantSystem constantSystem) => null; 32 Operation operation(ConstantSystem constantSystem) => null;
32 33
33 static InvokeDynamicSpecializer lookupSpecializer(Selector selector) { 34 static InvokeDynamicSpecializer lookupSpecializer(Selector selector) {
34 if (selector.kind == SelectorKind.INDEX) { 35 if (selector.kind == SelectorKind.INDEX) {
35 return selector.name == const SourceString('[]') 36 return selector.name == const SourceString('[]')
36 ? const IndexSpecializer() 37 ? const IndexSpecializer()
37 : const IndexAssignSpecializer(); 38 : const IndexAssignSpecializer();
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 index.instructionType.canBePrimitiveNumber(compiler)) { 90 index.instructionType.canBePrimitiveNumber(compiler)) {
90 return HType.MUTABLE_ARRAY; 91 return HType.MUTABLE_ARRAY;
91 } 92 }
92 // The index should be an int when the receiver is a string or array. 93 // The index should be an int when the receiver is a string or array.
93 // However it turns out that inserting an integer check in the optimized 94 // However it turns out that inserting an integer check in the optimized
94 // version is cheaper than having another bailout case. This is true, 95 // version is cheaper than having another bailout case. This is true,
95 // because the integer check will simply throw if it fails. 96 // because the integer check will simply throw if it fails.
96 return HType.UNKNOWN; 97 return HType.UNKNOWN;
97 } 98 }
98 99
99 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) { 100 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
101 Compiler compiler) {
100 if (instruction.inputs[1].isMutableArray()) { 102 if (instruction.inputs[1].isMutableArray()) {
101 return new HIndexAssign(instruction.inputs[1], 103 return new HIndexAssign(instruction.inputs[1],
102 instruction.inputs[2], 104 instruction.inputs[2],
103 instruction.inputs[3]); 105 instruction.inputs[3]);
104 } 106 }
105 return null; 107 return null;
106 } 108 }
107 } 109 }
108 110
109 class IndexSpecializer extends InvokeDynamicSpecializer { 111 class IndexSpecializer extends InvokeDynamicSpecializer {
110 const IndexSpecializer(); 112 const IndexSpecializer();
111 113
112 HType computeDesiredTypeForInput(HInvokeDynamic instruction, 114 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
113 HInstruction input, 115 HInstruction input,
114 Compiler compiler) { 116 Compiler compiler) {
115 HInstruction index = instruction.inputs[2]; 117 HInstruction index = instruction.inputs[2];
116 if (input == instruction.inputs[1] && 118 if (input == instruction.inputs[1] &&
117 index.instructionType.canBePrimitiveNumber(compiler)) { 119 index.instructionType.canBePrimitiveNumber(compiler)) {
118 return HType.INDEXABLE_PRIMITIVE; 120 return HType.INDEXABLE_PRIMITIVE;
119 } 121 }
120 // The index should be an int when the receiver is a string or array. 122 // The index should be an int when the receiver is a string or array.
121 // However it turns out that inserting an integer check in the optimized 123 // However it turns out that inserting an integer check in the optimized
122 // version is cheaper than having another bailout case. This is true, 124 // version is cheaper than having another bailout case. This is true,
123 // because the integer check will simply throw if it fails. 125 // because the integer check will simply throw if it fails.
124 return HType.UNKNOWN; 126 return HType.UNKNOWN;
125 } 127 }
126 128
127 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) { 129 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
130 Compiler compiler) {
128 if (instruction.inputs[1].isIndexablePrimitive()) { 131 if (instruction.inputs[1].isIndexablePrimitive()) {
129 return new HIndex(instruction.inputs[1], instruction.inputs[2]); 132 return new HIndex(instruction.inputs[1], instruction.inputs[2]);
130 } 133 }
131 return null; 134 return null;
132 } 135 }
133 } 136 }
134 137
135 class BitNotSpecializer extends InvokeDynamicSpecializer { 138 class BitNotSpecializer extends InvokeDynamicSpecializer {
136 const BitNotSpecializer(); 139 const BitNotSpecializer();
137 140
(...skipping 14 matching lines...) Expand all
152 } 155 }
153 156
154 HType computeTypeFromInputTypes(HInvokeDynamic instruction, 157 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
155 Compiler compiler) { 158 Compiler compiler) {
156 // All bitwise operations on primitive types either produce an 159 // All bitwise operations on primitive types either produce an
157 // integer or throw an error. 160 // integer or throw an error.
158 if (instruction.inputs[1].isPrimitive()) return HType.INTEGER; 161 if (instruction.inputs[1].isPrimitive()) return HType.INTEGER;
159 return instruction.instructionType; 162 return instruction.instructionType;
160 } 163 }
161 164
162 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) { 165 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
166 Compiler compiler) {
163 HInstruction input = instruction.inputs[1]; 167 HInstruction input = instruction.inputs[1];
164 if (input.isNumber()) return new HBitNot(input); 168 if (input.isNumber()) return new HBitNot(input);
165 return null; 169 return null;
166 } 170 }
167 } 171 }
168 172
169 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { 173 class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
170 const UnaryNegateSpecializer(); 174 const UnaryNegateSpecializer();
171 175
172 UnaryOperation operation(ConstantSystem constantSystem) { 176 UnaryOperation operation(ConstantSystem constantSystem) {
(...skipping 14 matching lines...) Expand all
187 return HType.UNKNOWN; 191 return HType.UNKNOWN;
188 } 192 }
189 193
190 HType computeTypeFromInputTypes(HInvokeDynamic instruction, 194 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
191 Compiler compiler) { 195 Compiler compiler) {
192 HType operandType = instruction.inputs[1].instructionType; 196 HType operandType = instruction.inputs[1].instructionType;
193 if (operandType.isNumber()) return operandType; 197 if (operandType.isNumber()) return operandType;
194 return instruction.instructionType; 198 return instruction.instructionType;
195 } 199 }
196 200
197 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) { 201 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
202 Compiler compiler) {
198 HInstruction input = instruction.inputs[1]; 203 HInstruction input = instruction.inputs[1];
199 if (input.isNumber()) return new HNegate(input); 204 if (input.isNumber()) return new HNegate(input);
200 return null; 205 return null;
201 } 206 }
202 } 207 }
203 208
204 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { 209 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
205 const BinaryArithmeticSpecializer(); 210 const BinaryArithmeticSpecializer();
206 211
207 HType computeTypeFromInputTypes(HInvokeDynamic instruction, 212 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 HInstruction right = instruction.inputs[2]; 247 HInstruction right = instruction.inputs[2];
243 if (input == right && left.isNumber()) return HType.NUMBER; 248 if (input == right && left.isNumber()) return HType.NUMBER;
244 return HType.UNKNOWN; 249 return HType.UNKNOWN;
245 } 250 }
246 251
247 bool isBuiltin(HInvokeDynamic instruction) { 252 bool isBuiltin(HInvokeDynamic instruction) {
248 return instruction.inputs[1].isNumber() 253 return instruction.inputs[1].isNumber()
249 && instruction.inputs[2].isNumber(); 254 && instruction.inputs[2].isNumber();
250 } 255 }
251 256
252 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) { 257 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
258 Compiler compiler) {
253 if (isBuiltin(instruction)) { 259 if (isBuiltin(instruction)) {
254 HInstruction builtin = 260 HInstruction builtin =
255 newBuiltinVariant(instruction.inputs[1], instruction.inputs[2]); 261 newBuiltinVariant(instruction.inputs[1], instruction.inputs[2]);
256 if (builtin != null) return builtin; 262 if (builtin != null) return builtin;
257 // Even if there is no builtin equivalent instruction, we know 263 // Even if there is no builtin equivalent instruction, we know
258 // the instruction does not have any side effect, and that it 264 // the instruction does not have any side effect, and that it
259 // can be GVN'ed. 265 // can be GVN'ed.
260 instruction.clearAllSideEffects(); 266 instruction.clearAllSideEffects();
261 instruction.clearAllDependencies(); 267 instruction.clearAllDependencies();
262 instruction.setUseGvn(); 268 instruction.setUseGvn();
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 } 391 }
386 } 392 }
387 393
388 class ShiftLeftSpecializer extends BinaryBitOpSpecializer { 394 class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
389 const ShiftLeftSpecializer(); 395 const ShiftLeftSpecializer();
390 396
391 BinaryOperation operation(ConstantSystem constantSystem) { 397 BinaryOperation operation(ConstantSystem constantSystem) {
392 return constantSystem.shiftLeft; 398 return constantSystem.shiftLeft;
393 } 399 }
394 400
395 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) { 401 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
402 Compiler compiler) {
396 HInstruction left = instruction.inputs[1]; 403 HInstruction left = instruction.inputs[1];
397 HInstruction right = instruction.inputs[2]; 404 HInstruction right = instruction.inputs[2];
398 if (!left.isNumber() || !right.isConstantInteger()) return null; 405 if (!left.isNumber() || !right.isConstantInteger()) return null;
399 HConstant rightConstant = right; 406 HConstant rightConstant = right;
400 IntConstant intConstant = rightConstant.constant; 407 IntConstant intConstant = rightConstant.constant;
401 int count = intConstant.value; 408 int count = intConstant.value;
402 if (count >= 0 && count <= 31) { 409 if (count >= 0 && count <= 31) {
403 return newBuiltinVariant(left, right); 410 return newBuiltinVariant(left, right);
404 } 411 }
405 return null; 412 return null;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 // is desired, then numbers are incorrect, though. 487 // is desired, then numbers are incorrect, though.
481 if (propagatedType.canBePrimitiveBoolean(compiler)) { 488 if (propagatedType.canBePrimitiveBoolean(compiler)) {
482 HInstruction left = instruction.inputs[1]; 489 HInstruction left = instruction.inputs[1];
483 if (left.instructionType.canBePrimitiveNumber(compiler)) { 490 if (left.instructionType.canBePrimitiveNumber(compiler)) {
484 return HType.NUMBER; 491 return HType.NUMBER;
485 } 492 }
486 } 493 }
487 return HType.UNKNOWN; 494 return HType.UNKNOWN;
488 } 495 }
489 496
490 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) { 497 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
498 Compiler compiler) {
491 HInstruction left = instruction.inputs[1]; 499 HInstruction left = instruction.inputs[1];
492 HInstruction right = instruction.inputs[2]; 500 HInstruction right = instruction.inputs[2];
493 if (left.isNumber() && right.isNumber()) { 501 if (left.isNumber() && right.isNumber()) {
494 return newBuiltinVariant(left, right); 502 return newBuiltinVariant(left, right);
495 } 503 }
496 return null; 504 return null;
497 } 505 }
498 506
499 HInstruction newBuiltinVariant(HInstruction left, HInstruction right); 507 HInstruction newBuiltinVariant(HInstruction left, HInstruction right);
500 } 508 }
(...skipping 20 matching lines...) Expand all
521 if (input == left && left.isIndexablePrimitive()) { 529 if (input == left && left.isIndexablePrimitive()) {
522 return HType.READABLE_ARRAY; 530 return HType.READABLE_ARRAY;
523 } 531 }
524 // String equality testing is much more common than array equality testing. 532 // String equality testing is much more common than array equality testing.
525 if (input == right && right.isIndexablePrimitive()) { 533 if (input == right && right.isIndexablePrimitive()) {
526 return HType.STRING; 534 return HType.STRING;
527 } 535 }
528 return HType.UNKNOWN; 536 return HType.UNKNOWN;
529 } 537 }
530 538
531 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) { 539 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
540 Compiler compiler) {
532 HInstruction left = instruction.inputs[1]; 541 HInstruction left = instruction.inputs[1];
533 HInstruction right = instruction.inputs[2]; 542 HInstruction right = instruction.inputs[2];
534 if (left.instructionType.isPrimitiveOrNull() || right.isConstantNull()) { 543 HType instructionType = left.instructionType;
544 if (right.isConstantNull() || instructionType.isPrimitiveOrNull()) {
545 return newBuiltinVariant(left, right);
546 }
547 // Make the mask non-nullable to avoid finding a potential
548 // JSNull::operator==.
kasperl 2013/03/21 07:07:04 Do we need the JSNull operator ==? If we ignore it
ngeoffray 2013/03/21 08:59:01 We can't get rid of it. If we have no clue what th
sra1 2013/03/21 08:59:07 I'm not sure whether you mean get rid of this chec
549 TypeMask mask = instructionType.computeMask(compiler).nonNullable();
550 Selector selector = new TypedSelector(mask, instruction.selector);
551 World world = compiler.world;
552 JavaScriptBackend backend = compiler.backend;
553 if (world.locateSingleElement(selector) == backend.objectEquals) {
535 return newBuiltinVariant(left, right); 554 return newBuiltinVariant(left, right);
536 } 555 }
537 return null; 556 return null;
538 } 557 }
539 558
540 BinaryOperation operation(ConstantSystem constantSystem) { 559 BinaryOperation operation(ConstantSystem constantSystem) {
541 return constantSystem.equal; 560 return constantSystem.equal;
542 } 561 }
543 562
544 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { 563 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 const LessEqualSpecializer(); 605 const LessEqualSpecializer();
587 606
588 BinaryOperation operation(ConstantSystem constantSystem) { 607 BinaryOperation operation(ConstantSystem constantSystem) {
589 return constantSystem.lessEqual; 608 return constantSystem.lessEqual;
590 } 609 }
591 610
592 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { 611 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) {
593 return new HLessEqual(left, right); 612 return new HLessEqual(left, right);
594 } 613 }
595 } 614 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698