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

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

Issue 15724021: Move array and string related HType from const to a field in the backend. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 92
93 class IndexAssignSpecializer extends InvokeDynamicSpecializer { 93 class IndexAssignSpecializer extends InvokeDynamicSpecializer {
94 const IndexAssignSpecializer(); 94 const IndexAssignSpecializer();
95 95
96 HType computeDesiredTypeForInput(HInvokeDynamic instruction, 96 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
97 HInstruction input, 97 HInstruction input,
98 Compiler compiler) { 98 Compiler compiler) {
99 HInstruction index = instruction.inputs[2]; 99 HInstruction index = instruction.inputs[2];
100 if (input == instruction.inputs[1] && 100 if (input == instruction.inputs[1] &&
101 index.instructionType.canBePrimitiveNumber(compiler)) { 101 index.instructionType.canBePrimitiveNumber(compiler)) {
102 return HType.MUTABLE_ARRAY; 102 JavaScriptBackend backend = compiler.backend;
103 return backend.mutableArrayType;
103 } 104 }
104 // The index should be an int when the receiver is a string or array. 105 // The index should be an int when the receiver is a string or array.
105 // However it turns out that inserting an integer check in the optimized 106 // However it turns out that inserting an integer check in the optimized
106 // version is cheaper than having another bailout case. This is true, 107 // version is cheaper than having another bailout case. This is true,
107 // because the integer check will simply throw if it fails. 108 // because the integer check will simply throw if it fails.
108 return HType.UNKNOWN; 109 return HType.UNKNOWN;
109 } 110 }
110 111
111 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, 112 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
112 Compiler compiler) { 113 Compiler compiler) {
(...skipping 13 matching lines...) Expand all
126 127
127 class IndexSpecializer extends InvokeDynamicSpecializer { 128 class IndexSpecializer extends InvokeDynamicSpecializer {
128 const IndexSpecializer(); 129 const IndexSpecializer();
129 130
130 HType computeDesiredTypeForInput(HInvokeDynamic instruction, 131 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
131 HInstruction input, 132 HInstruction input,
132 Compiler compiler) { 133 Compiler compiler) {
133 HInstruction index = instruction.inputs[2]; 134 HInstruction index = instruction.inputs[2];
134 if (input == instruction.inputs[1] && 135 if (input == instruction.inputs[1] &&
135 index.instructionType.canBePrimitiveNumber(compiler)) { 136 index.instructionType.canBePrimitiveNumber(compiler)) {
136 return HType.INDEXABLE_PRIMITIVE; 137 JavaScriptBackend backend = compiler.backend;
138 return backend.indexablePrimitiveType;
137 } 139 }
138 // The index should be an int when the receiver is a string or array. 140 // The index should be an int when the receiver is a string or array.
139 // However it turns out that inserting an integer check in the optimized 141 // However it turns out that inserting an integer check in the optimized
140 // version is cheaper than having another bailout case. This is true, 142 // version is cheaper than having another bailout case. This is true,
141 // because the integer check will simply throw if it fails. 143 // because the integer check will simply throw if it fails.
142 return HType.UNKNOWN; 144 return HType.UNKNOWN;
143 } 145 }
144 146
145 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, 147 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
146 Compiler compiler) { 148 Compiler compiler) {
(...skipping 28 matching lines...) Expand all
175 return HType.INTEGER; 177 return HType.INTEGER;
176 } 178 }
177 } 179 }
178 return HType.UNKNOWN; 180 return HType.UNKNOWN;
179 } 181 }
180 182
181 HType computeTypeFromInputTypes(HInvokeDynamic instruction, 183 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
182 Compiler compiler) { 184 Compiler compiler) {
183 // All bitwise operations on primitive types either produce an 185 // All bitwise operations on primitive types either produce an
184 // integer or throw an error. 186 // integer or throw an error.
185 if (instruction.inputs[1].isPrimitiveOrNull()) return HType.INTEGER; 187 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) return HType.INTEGER;
186 return super.computeTypeFromInputTypes(instruction, compiler); 188 return super.computeTypeFromInputTypes(instruction, compiler);
187 } 189 }
188 190
189 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, 191 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
190 Compiler compiler) { 192 Compiler compiler) {
191 HInstruction input = instruction.inputs[1]; 193 HInstruction input = instruction.inputs[1];
192 if (input.isNumber()) return new HBitNot(input, instruction.selector); 194 if (input.isNumber()) return new HBitNot(input, instruction.selector);
193 return null; 195 return null;
194 } 196 }
195 } 197 }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 } 394 }
393 395
394 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { 396 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
395 const BinaryBitOpSpecializer(); 397 const BinaryBitOpSpecializer();
396 398
397 HType computeTypeFromInputTypes(HInvokeDynamic instruction, 399 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
398 Compiler compiler) { 400 Compiler compiler) {
399 // All bitwise operations on primitive types either produce an 401 // All bitwise operations on primitive types either produce an
400 // integer or throw an error. 402 // integer or throw an error.
401 HInstruction left = instruction.inputs[1]; 403 HInstruction left = instruction.inputs[1];
402 if (left.isPrimitiveOrNull()) return HType.INTEGER; 404 if (left.isPrimitiveOrNull(compiler)) return HType.INTEGER;
403 return super.computeTypeFromInputTypes(instruction, compiler); 405 return super.computeTypeFromInputTypes(instruction, compiler);
404 } 406 }
405 407
406 HType computeDesiredTypeForInput(HInvokeDynamic instruction, 408 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
407 HInstruction input, 409 HInstruction input,
408 Compiler compiler) { 410 Compiler compiler) {
409 if (input == instruction.inputs[0]) return HType.UNKNOWN; 411 if (input == instruction.inputs[0]) return HType.UNKNOWN;
410 // We match the implementation of bit operations on the 412 // We match the implementation of bit operations on the
411 // [:JSNumber:] class by requesting a number if the receiver can 413 // [:JSNumber:] class by requesting a number if the receiver can
412 // be a number. 414 // be a number.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 return new HBitXor( 497 return new HBitXor(
496 instruction.inputs[1], instruction.inputs[2], instruction.selector); 498 instruction.inputs[1], instruction.inputs[2], instruction.selector);
497 } 499 }
498 } 500 }
499 501
500 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { 502 abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
501 const RelationalSpecializer(); 503 const RelationalSpecializer();
502 504
503 HType computeTypeFromInputTypes(HInvokeDynamic instruction, 505 HType computeTypeFromInputTypes(HInvokeDynamic instruction,
504 Compiler compiler) { 506 Compiler compiler) {
505 if (instruction.inputs[1].instructionType.isPrimitiveOrNull()) { 507 if (instruction.inputs[1].instructionType.isPrimitiveOrNull(compiler)) {
506 return HType.BOOLEAN; 508 return HType.BOOLEAN;
507 } 509 }
508 return super.computeTypeFromInputTypes(instruction, compiler); 510 return super.computeTypeFromInputTypes(instruction, compiler);
509 } 511 }
510 512
511 HType computeDesiredTypeForInput(HInvokeDynamic instruction, 513 HType computeDesiredTypeForInput(HInvokeDynamic instruction,
512 HInstruction input, 514 HInstruction input,
513 Compiler compiler) { 515 Compiler compiler) {
514 if (input == instruction.inputs[0]) return HType.UNKNOWN; 516 if (input == instruction.inputs[0]) return HType.UNKNOWN;
515 HType propagatedType = instruction.instructionType; 517 HType propagatedType = instruction.instructionType;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 // All our useful types have 'identical' semantics. But we don't want to 552 // All our useful types have 'identical' semantics. But we don't want to
551 // speculatively test for all possible types. Therefore we try to match 553 // speculatively test for all possible types. Therefore we try to match
552 // the two types. That is, if we see x == 3, then we speculatively test 554 // the two types. That is, if we see x == 3, then we speculatively test
553 // if x is a number and bailout if it isn't. 555 // if x is a number and bailout if it isn't.
554 // If right is a number we don't need more than a number (no need to match 556 // If right is a number we don't need more than a number (no need to match
555 // the exact type of right). 557 // the exact type of right).
556 if (right.isNumber()) return HType.NUMBER; 558 if (right.isNumber()) return HType.NUMBER;
557 return right.instructionType; 559 return right.instructionType;
558 } 560 }
559 // String equality testing is much more common than array equality testing. 561 // String equality testing is much more common than array equality testing.
562 JavaScriptBackend backend = compiler.backend;
560 if (input == left && left.isIndexablePrimitive(compiler)) { 563 if (input == left && left.isIndexablePrimitive(compiler)) {
561 return HType.READABLE_ARRAY; 564 return backend.readableArrayType;
562 } 565 }
563 // String equality testing is much more common than array equality testing. 566 // String equality testing is much more common than array equality testing.
564 if (input == right && right.isIndexablePrimitive(compiler)) { 567 if (input == right && right.isIndexablePrimitive(compiler)) {
565 return HType.STRING; 568 return backend.stringType;
566 } 569 }
567 return HType.UNKNOWN; 570 return HType.UNKNOWN;
568 } 571 }
569 572
570 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, 573 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
571 Compiler compiler) { 574 Compiler compiler) {
572 HInstruction left = instruction.inputs[1]; 575 HInstruction left = instruction.inputs[1];
573 HInstruction right = instruction.inputs[2]; 576 HInstruction right = instruction.inputs[2];
574 HType instructionType = left.instructionType; 577 HType instructionType = left.instructionType;
575 if (right.isConstantNull() || instructionType.isPrimitiveOrNull()) { 578 if (right.isConstantNull() || instructionType.isPrimitiveOrNull(compiler)) {
576 return newBuiltinVariant(instruction); 579 return newBuiltinVariant(instruction);
577 } 580 }
578 Selector selector = instructionType.refine(instruction.selector, compiler); 581 Selector selector = instructionType.refine(instruction.selector, compiler);
579 World world = compiler.world; 582 World world = compiler.world;
580 JavaScriptBackend backend = compiler.backend; 583 JavaScriptBackend backend = compiler.backend;
581 Iterable<Element> matches = world.allFunctions.filter(selector); 584 Iterable<Element> matches = world.allFunctions.filter(selector);
582 // This test relies the on `Object.==` and `Interceptor.==` always being 585 // This test relies the on `Object.==` and `Interceptor.==` always being
583 // implemented because if the selector matches by subtype, it still will be 586 // implemented because if the selector matches by subtype, it still will be
584 // a regular object or an interceptor. 587 // a regular object or an interceptor.
585 if (matches.every(backend.isDefaultEqualityImplementation)) { 588 if (matches.every(backend.isDefaultEqualityImplementation)) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 645
643 BinaryOperation operation(ConstantSystem constantSystem) { 646 BinaryOperation operation(ConstantSystem constantSystem) {
644 return constantSystem.lessEqual; 647 return constantSystem.lessEqual;
645 } 648 }
646 649
647 HInstruction newBuiltinVariant(HInvokeDynamic instruction) { 650 HInstruction newBuiltinVariant(HInvokeDynamic instruction) {
648 return new HLessEqual( 651 return new HLessEqual(
649 instruction.inputs[1], instruction.inputs[2], instruction.selector); 652 instruction.inputs[1], instruction.inputs[2], instruction.selector);
650 } 653 }
651 } 654 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698