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

Side by Side Diff: pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart

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

Powered by Google App Engine
This is Rietveld 408576698