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

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

Issue 2814453005: Merge CommonElements and BackendHelpers! (Closed)
Patch Set: comments and re-merge, take two Created 3 years, 8 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
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 '../common_elements.dart' show CommonElements;
5 import '../constants/constant_system.dart'; 6 import '../constants/constant_system.dart';
6 import '../constants/values.dart'; 7 import '../constants/values.dart';
7 import '../elements/elements.dart' show Name; 8 import '../elements/elements.dart' show Name;
8 import '../elements/entities.dart'; 9 import '../elements/entities.dart';
9 import '../js_backend/backend_helpers.dart';
10 import '../options.dart'; 10 import '../options.dart';
11 import '../types/types.dart'; 11 import '../types/types.dart';
12 import '../universe/call_structure.dart'; 12 import '../universe/call_structure.dart';
13 import '../universe/selector.dart'; 13 import '../universe/selector.dart';
14 import '../world.dart' show ClosedWorld; 14 import '../world.dart' show ClosedWorld;
15 import 'nodes.dart'; 15 import 'nodes.dart';
16 import 'types.dart'; 16 import 'types.dart';
17 17
18 /** 18 /**
19 * [InvokeDynamicSpecializer] and its subclasses are helpers to 19 * [InvokeDynamicSpecializer] and its subclasses are helpers to
20 * optimize intercepted dynamic calls. It knows what input types 20 * optimize intercepted dynamic calls. It knows what input types
21 * would be beneficial for performance, and how to change a invoke 21 * would be beneficial for performance, and how to change a invoke
22 * dynamic to a builtin instruction (e.g. HIndex, HBitNot). 22 * dynamic to a builtin instruction (e.g. HIndex, HBitNot).
23 */ 23 */
24 class InvokeDynamicSpecializer { 24 class InvokeDynamicSpecializer {
25 const InvokeDynamicSpecializer(); 25 const InvokeDynamicSpecializer();
26 26
27 TypeMask computeTypeFromInputTypes( 27 TypeMask computeTypeFromInputTypes(
28 HInvokeDynamic instruction, 28 HInvokeDynamic instruction,
29 GlobalTypeInferenceResults results, 29 GlobalTypeInferenceResults results,
30 CompilerOptions options, 30 CompilerOptions options,
31 BackendHelpers helpers,
32 ClosedWorld closedWorld) { 31 ClosedWorld closedWorld) {
33 return TypeMaskFactory.inferredTypeForSelector( 32 return TypeMaskFactory.inferredTypeForSelector(
34 instruction.selector, instruction.mask, results); 33 instruction.selector, instruction.mask, results);
35 } 34 }
36 35
37 HInstruction tryConvertToBuiltin( 36 HInstruction tryConvertToBuiltin(
38 HInvokeDynamic instruction, 37 HInvokeDynamic instruction,
39 HGraph graph, 38 HGraph graph,
40 GlobalTypeInferenceResults results, 39 GlobalTypeInferenceResults results,
41 CompilerOptions options, 40 CompilerOptions options,
42 BackendHelpers helpers, 41 CommonElements commonElements,
43 ClosedWorld closedWorld) { 42 ClosedWorld closedWorld) {
44 return null; 43 return null;
45 } 44 }
46 45
47 void clearAllSideEffects(HInstruction instruction) { 46 void clearAllSideEffects(HInstruction instruction) {
48 instruction.sideEffects.clearAllSideEffects(); 47 instruction.sideEffects.clearAllSideEffects();
49 instruction.sideEffects.clearAllDependencies(); 48 instruction.sideEffects.clearAllDependencies();
50 instruction.setUseGvn(); 49 instruction.setUseGvn();
51 } 50 }
52 51
53 Selector renameToOptimizedSelector( 52 Selector renameToOptimizedSelector(
54 String name, Selector selector, BackendHelpers helpers) { 53 String name, Selector selector, CommonElements commonElements) {
55 if (selector.name == name) return selector; 54 if (selector.name == name) return selector;
56 return new Selector.call(new Name(name, helpers.interceptorsLibrary), 55 return new Selector.call(new Name(name, commonElements.interceptorsLibrary),
57 new CallStructure(selector.argumentCount)); 56 new CallStructure(selector.argumentCount));
58 } 57 }
59 58
60 Operation operation(ConstantSystem constantSystem) => null; 59 Operation operation(ConstantSystem constantSystem) => null;
61 60
62 static InvokeDynamicSpecializer lookupSpecializer(Selector selector) { 61 static InvokeDynamicSpecializer lookupSpecializer(Selector selector) {
63 if (selector.isIndex) return const IndexSpecializer(); 62 if (selector.isIndex) return const IndexSpecializer();
64 if (selector.isIndexSet) return const IndexAssignSpecializer(); 63 if (selector.isIndexSet) return const IndexAssignSpecializer();
65 String name = selector.name; 64 String name = selector.name;
66 if (selector.isOperator) { 65 if (selector.isOperator) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 } 112 }
114 113
115 class IndexAssignSpecializer extends InvokeDynamicSpecializer { 114 class IndexAssignSpecializer extends InvokeDynamicSpecializer {
116 const IndexAssignSpecializer(); 115 const IndexAssignSpecializer();
117 116
118 HInstruction tryConvertToBuiltin( 117 HInstruction tryConvertToBuiltin(
119 HInvokeDynamic instruction, 118 HInvokeDynamic instruction,
120 HGraph graph, 119 HGraph graph,
121 GlobalTypeInferenceResults results, 120 GlobalTypeInferenceResults results,
122 CompilerOptions options, 121 CompilerOptions options,
123 BackendHelpers helpers, 122 CommonElements commonElements,
124 ClosedWorld closedWorld) { 123 ClosedWorld closedWorld) {
125 if (instruction.inputs[1].isMutableIndexable(closedWorld)) { 124 if (instruction.inputs[1].isMutableIndexable(closedWorld)) {
126 if (!instruction.inputs[2].isInteger(closedWorld) && 125 if (!instruction.inputs[2].isInteger(closedWorld) &&
127 options.enableTypeAssertions) { 126 options.enableTypeAssertions) {
128 // We want the right checked mode error. 127 // We want the right checked mode error.
129 return null; 128 return null;
130 } 129 }
131 return new HIndexAssign(instruction.inputs[1], instruction.inputs[2], 130 return new HIndexAssign(instruction.inputs[1], instruction.inputs[2],
132 instruction.inputs[3], instruction.selector); 131 instruction.inputs[3], instruction.selector);
133 } 132 }
134 return null; 133 return null;
135 } 134 }
136 } 135 }
137 136
138 class IndexSpecializer extends InvokeDynamicSpecializer { 137 class IndexSpecializer extends InvokeDynamicSpecializer {
139 const IndexSpecializer(); 138 const IndexSpecializer();
140 139
141 HInstruction tryConvertToBuiltin( 140 HInstruction tryConvertToBuiltin(
142 HInvokeDynamic instruction, 141 HInvokeDynamic instruction,
143 HGraph graph, 142 HGraph graph,
144 GlobalTypeInferenceResults results, 143 GlobalTypeInferenceResults results,
145 CompilerOptions options, 144 CompilerOptions options,
146 BackendHelpers helpers, 145 CommonElements commonElements,
147 ClosedWorld closedWorld) { 146 ClosedWorld closedWorld) {
148 if (!instruction.inputs[1].isIndexablePrimitive(closedWorld)) return null; 147 if (!instruction.inputs[1].isIndexablePrimitive(closedWorld)) return null;
149 if (!instruction.inputs[2].isInteger(closedWorld) && 148 if (!instruction.inputs[2].isInteger(closedWorld) &&
150 options.enableTypeAssertions) { 149 options.enableTypeAssertions) {
151 // We want the right checked mode error. 150 // We want the right checked mode error.
152 return null; 151 return null;
153 } 152 }
154 TypeMask receiverType = 153 TypeMask receiverType =
155 instruction.getDartReceiver(closedWorld).instructionType; 154 instruction.getDartReceiver(closedWorld).instructionType;
156 TypeMask type = TypeMaskFactory.inferredTypeForSelector( 155 TypeMask type = TypeMaskFactory.inferredTypeForSelector(
157 instruction.selector, receiverType, results); 156 instruction.selector, receiverType, results);
158 return new HIndex(instruction.inputs[1], instruction.inputs[2], 157 return new HIndex(instruction.inputs[1], instruction.inputs[2],
159 instruction.selector, type); 158 instruction.selector, type);
160 } 159 }
161 } 160 }
162 161
163 class BitNotSpecializer extends InvokeDynamicSpecializer { 162 class BitNotSpecializer extends InvokeDynamicSpecializer {
164 const BitNotSpecializer(); 163 const BitNotSpecializer();
165 164
166 UnaryOperation operation(ConstantSystem constantSystem) { 165 UnaryOperation operation(ConstantSystem constantSystem) {
167 return constantSystem.bitNot; 166 return constantSystem.bitNot;
168 } 167 }
169 168
170 TypeMask computeTypeFromInputTypes( 169 TypeMask computeTypeFromInputTypes(
171 HInvokeDynamic instruction, 170 HInvokeDynamic instruction,
172 GlobalTypeInferenceResults results, 171 GlobalTypeInferenceResults results,
173 CompilerOptions options, 172 CompilerOptions options,
174 BackendHelpers helpers,
175 ClosedWorld closedWorld) { 173 ClosedWorld closedWorld) {
176 // All bitwise operations on primitive types either produce an 174 // All bitwise operations on primitive types either produce an
177 // integer or throw an error. 175 // integer or throw an error.
178 if (instruction.inputs[1].isPrimitiveOrNull(closedWorld)) { 176 if (instruction.inputs[1].isPrimitiveOrNull(closedWorld)) {
179 return closedWorld.commonMasks.uint32Type; 177 return closedWorld.commonMasks.uint32Type;
180 } 178 }
181 return super.computeTypeFromInputTypes( 179 return super
182 instruction, results, options, helpers, closedWorld); 180 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
183 } 181 }
184 182
185 HInstruction tryConvertToBuiltin( 183 HInstruction tryConvertToBuiltin(
186 HInvokeDynamic instruction, 184 HInvokeDynamic instruction,
187 HGraph graph, 185 HGraph graph,
188 GlobalTypeInferenceResults results, 186 GlobalTypeInferenceResults results,
189 CompilerOptions options, 187 CompilerOptions options,
190 BackendHelpers helpers, 188 CommonElements commonElements,
191 ClosedWorld closedWorld) { 189 ClosedWorld closedWorld) {
192 HInstruction input = instruction.inputs[1]; 190 HInstruction input = instruction.inputs[1];
193 if (input.isNumber(closedWorld)) { 191 if (input.isNumber(closedWorld)) {
194 return new HBitNot( 192 return new HBitNot(
195 input, 193 input,
196 instruction.selector, 194 instruction.selector,
197 computeTypeFromInputTypes( 195 computeTypeFromInputTypes(
198 instruction, results, options, helpers, closedWorld)); 196 instruction, results, options, closedWorld));
199 } 197 }
200 return null; 198 return null;
201 } 199 }
202 } 200 }
203 201
204 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { 202 class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
205 const UnaryNegateSpecializer(); 203 const UnaryNegateSpecializer();
206 204
207 UnaryOperation operation(ConstantSystem constantSystem) { 205 UnaryOperation operation(ConstantSystem constantSystem) {
208 return constantSystem.negate; 206 return constantSystem.negate;
209 } 207 }
210 208
211 TypeMask computeTypeFromInputTypes( 209 TypeMask computeTypeFromInputTypes(
212 HInvokeDynamic instruction, 210 HInvokeDynamic instruction,
213 GlobalTypeInferenceResults results, 211 GlobalTypeInferenceResults results,
214 CompilerOptions options, 212 CompilerOptions options,
215 BackendHelpers helpers,
216 ClosedWorld closedWorld) { 213 ClosedWorld closedWorld) {
217 TypeMask operandType = instruction.inputs[1].instructionType; 214 TypeMask operandType = instruction.inputs[1].instructionType;
218 if (instruction.inputs[1].isNumberOrNull(closedWorld)) return operandType; 215 if (instruction.inputs[1].isNumberOrNull(closedWorld)) return operandType;
219 return super.computeTypeFromInputTypes( 216 return super
220 instruction, results, options, helpers, closedWorld); 217 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
221 } 218 }
222 219
223 HInstruction tryConvertToBuiltin( 220 HInstruction tryConvertToBuiltin(
224 HInvokeDynamic instruction, 221 HInvokeDynamic instruction,
225 HGraph graph, 222 HGraph graph,
226 GlobalTypeInferenceResults results, 223 GlobalTypeInferenceResults results,
227 CompilerOptions options, 224 CompilerOptions options,
228 BackendHelpers helpers, 225 CommonElements commonElements,
229 ClosedWorld closedWorld) { 226 ClosedWorld closedWorld) {
230 HInstruction input = instruction.inputs[1]; 227 HInstruction input = instruction.inputs[1];
231 if (input.isNumber(closedWorld)) { 228 if (input.isNumber(closedWorld)) {
232 return new HNegate(input, instruction.selector, input.instructionType); 229 return new HNegate(input, instruction.selector, input.instructionType);
233 } 230 }
234 return null; 231 return null;
235 } 232 }
236 } 233 }
237 234
238 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer { 235 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
239 const BinaryArithmeticSpecializer(); 236 const BinaryArithmeticSpecializer();
240 237
241 TypeMask computeTypeFromInputTypes( 238 TypeMask computeTypeFromInputTypes(
242 HInvokeDynamic instruction, 239 HInvokeDynamic instruction,
243 GlobalTypeInferenceResults results, 240 GlobalTypeInferenceResults results,
244 CompilerOptions options, 241 CompilerOptions options,
245 BackendHelpers helpers,
246 ClosedWorld closedWorld) { 242 ClosedWorld closedWorld) {
247 HInstruction left = instruction.inputs[1]; 243 HInstruction left = instruction.inputs[1];
248 HInstruction right = instruction.inputs[2]; 244 HInstruction right = instruction.inputs[2];
249 if (left.isIntegerOrNull(closedWorld) && 245 if (left.isIntegerOrNull(closedWorld) &&
250 right.isIntegerOrNull(closedWorld)) { 246 right.isIntegerOrNull(closedWorld)) {
251 return closedWorld.commonMasks.intType; 247 return closedWorld.commonMasks.intType;
252 } 248 }
253 if (left.isNumberOrNull(closedWorld)) { 249 if (left.isNumberOrNull(closedWorld)) {
254 if (left.isDoubleOrNull(closedWorld) || 250 if (left.isDoubleOrNull(closedWorld) ||
255 right.isDoubleOrNull(closedWorld)) { 251 right.isDoubleOrNull(closedWorld)) {
256 return closedWorld.commonMasks.doubleType; 252 return closedWorld.commonMasks.doubleType;
257 } 253 }
258 return closedWorld.commonMasks.numType; 254 return closedWorld.commonMasks.numType;
259 } 255 }
260 return super.computeTypeFromInputTypes( 256 return super
261 instruction, results, options, helpers, closedWorld); 257 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
262 } 258 }
263 259
264 bool isBuiltin(HInvokeDynamic instruction, ClosedWorld closedWorld) { 260 bool isBuiltin(HInvokeDynamic instruction, ClosedWorld closedWorld) {
265 return instruction.inputs[1].isNumber(closedWorld) && 261 return instruction.inputs[1].isNumber(closedWorld) &&
266 instruction.inputs[2].isNumber(closedWorld); 262 instruction.inputs[2].isNumber(closedWorld);
267 } 263 }
268 264
269 HInstruction tryConvertToBuiltin( 265 HInstruction tryConvertToBuiltin(
270 HInvokeDynamic instruction, 266 HInvokeDynamic instruction,
271 HGraph graph, 267 HGraph graph,
272 GlobalTypeInferenceResults results, 268 GlobalTypeInferenceResults results,
273 CompilerOptions options, 269 CompilerOptions options,
274 BackendHelpers helpers, 270 CommonElements commonElements,
275 ClosedWorld closedWorld) { 271 ClosedWorld closedWorld) {
276 if (isBuiltin(instruction, closedWorld)) { 272 if (isBuiltin(instruction, closedWorld)) {
277 HInstruction builtin = newBuiltinVariant( 273 HInstruction builtin =
278 instruction, results, options, helpers, closedWorld); 274 newBuiltinVariant(instruction, results, options, closedWorld);
279 if (builtin != null) return builtin; 275 if (builtin != null) return builtin;
280 // Even if there is no builtin equivalent instruction, we know 276 // Even if there is no builtin equivalent instruction, we know
281 // the instruction does not have any side effect, and that it 277 // the instruction does not have any side effect, and that it
282 // can be GVN'ed. 278 // can be GVN'ed.
283 clearAllSideEffects(instruction); 279 clearAllSideEffects(instruction);
284 } 280 }
285 return null; 281 return null;
286 } 282 }
287 283
288 bool inputsArePositiveIntegers( 284 bool inputsArePositiveIntegers(
289 HInstruction instruction, ClosedWorld closedWorld) { 285 HInstruction instruction, ClosedWorld closedWorld) {
290 HInstruction left = instruction.inputs[1]; 286 HInstruction left = instruction.inputs[1];
291 HInstruction right = instruction.inputs[2]; 287 HInstruction right = instruction.inputs[2];
292 return left.isPositiveIntegerOrNull(closedWorld) && 288 return left.isPositiveIntegerOrNull(closedWorld) &&
293 right.isPositiveIntegerOrNull(closedWorld); 289 right.isPositiveIntegerOrNull(closedWorld);
294 } 290 }
295 291
296 bool inputsAreUInt31(HInstruction instruction, ClosedWorld closedWorld) { 292 bool inputsAreUInt31(HInstruction instruction, ClosedWorld closedWorld) {
297 HInstruction left = instruction.inputs[1]; 293 HInstruction left = instruction.inputs[1];
298 HInstruction right = instruction.inputs[2]; 294 HInstruction right = instruction.inputs[2];
299 return left.isUInt31(closedWorld) && right.isUInt31(closedWorld); 295 return left.isUInt31(closedWorld) && right.isUInt31(closedWorld);
300 } 296 }
301 297
302 HInstruction newBuiltinVariant( 298 HInstruction newBuiltinVariant(
303 HInvokeDynamic instruction, 299 HInvokeDynamic instruction,
304 GlobalTypeInferenceResults results, 300 GlobalTypeInferenceResults results,
305 CompilerOptions options, 301 CompilerOptions options,
306 BackendHelpers helpers,
307 ClosedWorld closedWorld); 302 ClosedWorld closedWorld);
308 } 303 }
309 304
310 class AddSpecializer extends BinaryArithmeticSpecializer { 305 class AddSpecializer extends BinaryArithmeticSpecializer {
311 const AddSpecializer(); 306 const AddSpecializer();
312 307
313 TypeMask computeTypeFromInputTypes( 308 TypeMask computeTypeFromInputTypes(
314 HInvokeDynamic instruction, 309 HInvokeDynamic instruction,
315 GlobalTypeInferenceResults results, 310 GlobalTypeInferenceResults results,
316 CompilerOptions options, 311 CompilerOptions options,
317 BackendHelpers helpers,
318 ClosedWorld closedWorld) { 312 ClosedWorld closedWorld) {
319 if (inputsAreUInt31(instruction, closedWorld)) { 313 if (inputsAreUInt31(instruction, closedWorld)) {
320 return closedWorld.commonMasks.uint32Type; 314 return closedWorld.commonMasks.uint32Type;
321 } 315 }
322 if (inputsArePositiveIntegers(instruction, closedWorld)) { 316 if (inputsArePositiveIntegers(instruction, closedWorld)) {
323 return closedWorld.commonMasks.positiveIntType; 317 return closedWorld.commonMasks.positiveIntType;
324 } 318 }
325 return super.computeTypeFromInputTypes( 319 return super
326 instruction, results, options, helpers, closedWorld); 320 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
327 } 321 }
328 322
329 BinaryOperation operation(ConstantSystem constantSystem) { 323 BinaryOperation operation(ConstantSystem constantSystem) {
330 return constantSystem.add; 324 return constantSystem.add;
331 } 325 }
332 326
333 HInstruction newBuiltinVariant( 327 HInstruction newBuiltinVariant(
334 HInvokeDynamic instruction, 328 HInvokeDynamic instruction,
335 GlobalTypeInferenceResults results, 329 GlobalTypeInferenceResults results,
336 CompilerOptions options, 330 CompilerOptions options,
337 BackendHelpers helpers,
338 ClosedWorld closedWorld) { 331 ClosedWorld closedWorld) {
339 return new HAdd( 332 return new HAdd(
340 instruction.inputs[1], 333 instruction.inputs[1],
341 instruction.inputs[2], 334 instruction.inputs[2],
342 instruction.selector, 335 instruction.selector,
343 computeTypeFromInputTypes( 336 computeTypeFromInputTypes(instruction, results, options, closedWorld));
344 instruction, results, options, helpers, closedWorld));
345 } 337 }
346 } 338 }
347 339
348 class DivideSpecializer extends BinaryArithmeticSpecializer { 340 class DivideSpecializer extends BinaryArithmeticSpecializer {
349 const DivideSpecializer(); 341 const DivideSpecializer();
350 342
351 BinaryOperation operation(ConstantSystem constantSystem) { 343 BinaryOperation operation(ConstantSystem constantSystem) {
352 return constantSystem.divide; 344 return constantSystem.divide;
353 } 345 }
354 346
355 TypeMask computeTypeFromInputTypes( 347 TypeMask computeTypeFromInputTypes(
356 HInstruction instruction, 348 HInstruction instruction,
357 GlobalTypeInferenceResults results, 349 GlobalTypeInferenceResults results,
358 CompilerOptions options, 350 CompilerOptions options,
359 BackendHelpers helpers,
360 ClosedWorld closedWorld) { 351 ClosedWorld closedWorld) {
361 HInstruction left = instruction.inputs[1]; 352 HInstruction left = instruction.inputs[1];
362 if (left.isNumberOrNull(closedWorld)) { 353 if (left.isNumberOrNull(closedWorld)) {
363 return closedWorld.commonMasks.doubleType; 354 return closedWorld.commonMasks.doubleType;
364 } 355 }
365 return super.computeTypeFromInputTypes( 356 return super
366 instruction, results, options, helpers, closedWorld); 357 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
367 } 358 }
368 359
369 HInstruction newBuiltinVariant( 360 HInstruction newBuiltinVariant(
370 HInvokeDynamic instruction, 361 HInvokeDynamic instruction,
371 GlobalTypeInferenceResults results, 362 GlobalTypeInferenceResults results,
372 CompilerOptions options, 363 CompilerOptions options,
373 BackendHelpers helpers,
374 ClosedWorld closedWorld) { 364 ClosedWorld closedWorld) {
375 return new HDivide(instruction.inputs[1], instruction.inputs[2], 365 return new HDivide(instruction.inputs[1], instruction.inputs[2],
376 instruction.selector, closedWorld.commonMasks.doubleType); 366 instruction.selector, closedWorld.commonMasks.doubleType);
377 } 367 }
378 } 368 }
379 369
380 class ModuloSpecializer extends BinaryArithmeticSpecializer { 370 class ModuloSpecializer extends BinaryArithmeticSpecializer {
381 const ModuloSpecializer(); 371 const ModuloSpecializer();
382 372
383 TypeMask computeTypeFromInputTypes( 373 TypeMask computeTypeFromInputTypes(
384 HInvokeDynamic instruction, 374 HInvokeDynamic instruction,
385 GlobalTypeInferenceResults results, 375 GlobalTypeInferenceResults results,
386 CompilerOptions options, 376 CompilerOptions options,
387 BackendHelpers helpers,
388 ClosedWorld closedWorld) { 377 ClosedWorld closedWorld) {
389 if (inputsArePositiveIntegers(instruction, closedWorld)) { 378 if (inputsArePositiveIntegers(instruction, closedWorld)) {
390 return closedWorld.commonMasks.positiveIntType; 379 return closedWorld.commonMasks.positiveIntType;
391 } 380 }
392 return super.computeTypeFromInputTypes( 381 return super
393 instruction, results, options, helpers, closedWorld); 382 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
394 } 383 }
395 384
396 BinaryOperation operation(ConstantSystem constantSystem) { 385 BinaryOperation operation(ConstantSystem constantSystem) {
397 return constantSystem.modulo; 386 return constantSystem.modulo;
398 } 387 }
399 388
400 HInstruction newBuiltinVariant( 389 HInstruction newBuiltinVariant(
401 HInvokeDynamic instruction, 390 HInvokeDynamic instruction,
402 GlobalTypeInferenceResults results, 391 GlobalTypeInferenceResults results,
403 CompilerOptions options, 392 CompilerOptions options,
404 BackendHelpers helpers,
405 ClosedWorld closedWorld) { 393 ClosedWorld closedWorld) {
406 // Modulo cannot be mapped to the native operator (different semantics). 394 // Modulo cannot be mapped to the native operator (different semantics).
407 395
408 // We can use HRemainder if both inputs are non-negative and the receiver 396 // We can use HRemainder if both inputs are non-negative and the receiver
409 // cannot be -0.0. Note that -0.0 is considered to be an int, so until we 397 // cannot be -0.0. Note that -0.0 is considered to be an int, so until we
410 // track -0.0 precisely, we have to syntatically filter inputs that cannot 398 // track -0.0 precisely, we have to syntatically filter inputs that cannot
411 // generate -0.0. 399 // generate -0.0.
412 bool canBePositiveZero(HInstruction input) { 400 bool canBePositiveZero(HInstruction input) {
413 if (input is HConstant) { 401 if (input is HConstant) {
414 ConstantValue value = input.constant; 402 ConstantValue value = input.constant;
(...skipping 28 matching lines...) Expand all
443 return true; 431 return true;
444 } 432 }
445 433
446 if (inputsArePositiveIntegers(instruction, closedWorld) && 434 if (inputsArePositiveIntegers(instruction, closedWorld) &&
447 !canBeNegativeZero(instruction.getDartReceiver(closedWorld))) { 435 !canBeNegativeZero(instruction.getDartReceiver(closedWorld))) {
448 return new HRemainder( 436 return new HRemainder(
449 instruction.inputs[1], 437 instruction.inputs[1],
450 instruction.inputs[2], 438 instruction.inputs[2],
451 instruction.selector, 439 instruction.selector,
452 computeTypeFromInputTypes( 440 computeTypeFromInputTypes(
453 instruction, results, options, helpers, closedWorld)); 441 instruction, results, options, closedWorld));
454 } 442 }
455 // TODO(sra): 443 // TODO(sra):
456 // a % N --> a & (N-1), N=2^k, where a>=0, does not have -0.0 problem. 444 // a % N --> a & (N-1), N=2^k, where a>=0, does not have -0.0 problem.
457 445
458 // TODO(sra): We could avoid problems with -0.0 if we generate x % y as (x + 446 // TODO(sra): We could avoid problems with -0.0 if we generate x % y as (x +
459 // 0) % y, but we would have to fix HAdd optimizations. 447 // 0) % y, but we would have to fix HAdd optimizations.
460 448
461 // TODO(sra): We could replace $mod with HRemainder when we don't care about 449 // TODO(sra): We could replace $mod with HRemainder when we don't care about
462 // a -0.0 result (e.g. a % 10 == 0, a[i % 3]). This is tricky, since we 450 // a -0.0 result (e.g. a % 10 == 0, a[i % 3]). This is tricky, since we
463 // don't want to ruin GVN opportunities. 451 // don't want to ruin GVN opportunities.
464 return null; 452 return null;
465 } 453 }
466 } 454 }
467 455
468 class RemainderSpecializer extends BinaryArithmeticSpecializer { 456 class RemainderSpecializer extends BinaryArithmeticSpecializer {
469 const RemainderSpecializer(); 457 const RemainderSpecializer();
470 458
471 TypeMask computeTypeFromInputTypes( 459 TypeMask computeTypeFromInputTypes(
472 HInvokeDynamic instruction, 460 HInvokeDynamic instruction,
473 GlobalTypeInferenceResults results, 461 GlobalTypeInferenceResults results,
474 CompilerOptions options, 462 CompilerOptions options,
475 BackendHelpers helpers,
476 ClosedWorld closedWorld) { 463 ClosedWorld closedWorld) {
477 if (inputsArePositiveIntegers(instruction, closedWorld)) { 464 if (inputsArePositiveIntegers(instruction, closedWorld)) {
478 return closedWorld.commonMasks.positiveIntType; 465 return closedWorld.commonMasks.positiveIntType;
479 } 466 }
480 return super.computeTypeFromInputTypes( 467 return super
481 instruction, results, options, helpers, closedWorld); 468 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
482 } 469 }
483 470
484 BinaryOperation operation(ConstantSystem constantSystem) { 471 BinaryOperation operation(ConstantSystem constantSystem) {
485 return constantSystem.remainder; 472 return constantSystem.remainder;
486 } 473 }
487 474
488 HInstruction newBuiltinVariant( 475 HInstruction newBuiltinVariant(
489 HInvokeDynamic instruction, 476 HInvokeDynamic instruction,
490 GlobalTypeInferenceResults results, 477 GlobalTypeInferenceResults results,
491 CompilerOptions options, 478 CompilerOptions options,
492 BackendHelpers helpers,
493 ClosedWorld closedWorld) { 479 ClosedWorld closedWorld) {
494 return new HRemainder( 480 return new HRemainder(
495 instruction.inputs[1], 481 instruction.inputs[1],
496 instruction.inputs[2], 482 instruction.inputs[2],
497 instruction.selector, 483 instruction.selector,
498 computeTypeFromInputTypes( 484 computeTypeFromInputTypes(instruction, results, options, closedWorld));
499 instruction, results, options, helpers, closedWorld));
500 } 485 }
501 } 486 }
502 487
503 class MultiplySpecializer extends BinaryArithmeticSpecializer { 488 class MultiplySpecializer extends BinaryArithmeticSpecializer {
504 const MultiplySpecializer(); 489 const MultiplySpecializer();
505 490
506 BinaryOperation operation(ConstantSystem constantSystem) { 491 BinaryOperation operation(ConstantSystem constantSystem) {
507 return constantSystem.multiply; 492 return constantSystem.multiply;
508 } 493 }
509 494
510 TypeMask computeTypeFromInputTypes( 495 TypeMask computeTypeFromInputTypes(
511 HInvokeDynamic instruction, 496 HInvokeDynamic instruction,
512 GlobalTypeInferenceResults results, 497 GlobalTypeInferenceResults results,
513 CompilerOptions options, 498 CompilerOptions options,
514 BackendHelpers helpers,
515 ClosedWorld closedWorld) { 499 ClosedWorld closedWorld) {
516 if (inputsArePositiveIntegers(instruction, closedWorld)) { 500 if (inputsArePositiveIntegers(instruction, closedWorld)) {
517 return closedWorld.commonMasks.positiveIntType; 501 return closedWorld.commonMasks.positiveIntType;
518 } 502 }
519 return super.computeTypeFromInputTypes( 503 return super
520 instruction, results, options, helpers, closedWorld); 504 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
521 } 505 }
522 506
523 HInstruction newBuiltinVariant( 507 HInstruction newBuiltinVariant(
524 HInvokeDynamic instruction, 508 HInvokeDynamic instruction,
525 GlobalTypeInferenceResults results, 509 GlobalTypeInferenceResults results,
526 CompilerOptions options, 510 CompilerOptions options,
527 BackendHelpers helpers,
528 ClosedWorld closedWorld) { 511 ClosedWorld closedWorld) {
529 return new HMultiply( 512 return new HMultiply(
530 instruction.inputs[1], 513 instruction.inputs[1],
531 instruction.inputs[2], 514 instruction.inputs[2],
532 instruction.selector, 515 instruction.selector,
533 computeTypeFromInputTypes( 516 computeTypeFromInputTypes(instruction, results, options, closedWorld));
534 instruction, results, options, helpers, closedWorld));
535 } 517 }
536 } 518 }
537 519
538 class SubtractSpecializer extends BinaryArithmeticSpecializer { 520 class SubtractSpecializer extends BinaryArithmeticSpecializer {
539 const SubtractSpecializer(); 521 const SubtractSpecializer();
540 522
541 BinaryOperation operation(ConstantSystem constantSystem) { 523 BinaryOperation operation(ConstantSystem constantSystem) {
542 return constantSystem.subtract; 524 return constantSystem.subtract;
543 } 525 }
544 526
545 HInstruction newBuiltinVariant( 527 HInstruction newBuiltinVariant(
546 HInvokeDynamic instruction, 528 HInvokeDynamic instruction,
547 GlobalTypeInferenceResults results, 529 GlobalTypeInferenceResults results,
548 CompilerOptions options, 530 CompilerOptions options,
549 BackendHelpers helpers,
550 ClosedWorld closedWorld) { 531 ClosedWorld closedWorld) {
551 return new HSubtract( 532 return new HSubtract(
552 instruction.inputs[1], 533 instruction.inputs[1],
553 instruction.inputs[2], 534 instruction.inputs[2],
554 instruction.selector, 535 instruction.selector,
555 computeTypeFromInputTypes( 536 computeTypeFromInputTypes(instruction, results, options, closedWorld));
556 instruction, results, options, helpers, closedWorld));
557 } 537 }
558 } 538 }
559 539
560 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer { 540 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
561 const TruncatingDivideSpecializer(); 541 const TruncatingDivideSpecializer();
562 542
563 BinaryOperation operation(ConstantSystem constantSystem) { 543 BinaryOperation operation(ConstantSystem constantSystem) {
564 return constantSystem.truncatingDivide; 544 return constantSystem.truncatingDivide;
565 } 545 }
566 546
567 TypeMask computeTypeFromInputTypes( 547 TypeMask computeTypeFromInputTypes(
568 HInvokeDynamic instruction, 548 HInvokeDynamic instruction,
569 GlobalTypeInferenceResults results, 549 GlobalTypeInferenceResults results,
570 CompilerOptions options, 550 CompilerOptions options,
571 BackendHelpers helpers,
572 ClosedWorld closedWorld) { 551 ClosedWorld closedWorld) {
573 if (hasUint31Result(instruction, closedWorld)) { 552 if (hasUint31Result(instruction, closedWorld)) {
574 return closedWorld.commonMasks.uint31Type; 553 return closedWorld.commonMasks.uint31Type;
575 } 554 }
576 if (inputsArePositiveIntegers(instruction, closedWorld)) { 555 if (inputsArePositiveIntegers(instruction, closedWorld)) {
577 return closedWorld.commonMasks.positiveIntType; 556 return closedWorld.commonMasks.positiveIntType;
578 } 557 }
579 return super.computeTypeFromInputTypes( 558 return super
580 instruction, results, options, helpers, closedWorld); 559 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
581 } 560 }
582 561
583 bool isNotZero(HInstruction instruction) { 562 bool isNotZero(HInstruction instruction) {
584 if (!instruction.isConstantInteger()) return false; 563 if (!instruction.isConstantInteger()) return false;
585 HConstant rightConstant = instruction; 564 HConstant rightConstant = instruction;
586 IntConstantValue intConstant = rightConstant.constant; 565 IntConstantValue intConstant = rightConstant.constant;
587 int count = intConstant.primitiveValue; 566 int count = intConstant.primitiveValue;
588 return count != 0; 567 return count != 0;
589 } 568 }
590 569
(...skipping 17 matching lines...) Expand all
608 } 587 }
609 } 588 }
610 return false; 589 return false;
611 } 590 }
612 591
613 HInstruction tryConvertToBuiltin( 592 HInstruction tryConvertToBuiltin(
614 HInvokeDynamic instruction, 593 HInvokeDynamic instruction,
615 HGraph graph, 594 HGraph graph,
616 GlobalTypeInferenceResults results, 595 GlobalTypeInferenceResults results,
617 CompilerOptions options, 596 CompilerOptions options,
618 BackendHelpers helpers, 597 CommonElements commonElements,
619 ClosedWorld closedWorld) { 598 ClosedWorld closedWorld) {
620 HInstruction right = instruction.inputs[2]; 599 HInstruction right = instruction.inputs[2];
621 if (isBuiltin(instruction, closedWorld)) { 600 if (isBuiltin(instruction, closedWorld)) {
622 if (right.isPositiveInteger(closedWorld) && isNotZero(right)) { 601 if (right.isPositiveInteger(closedWorld) && isNotZero(right)) {
623 if (hasUint31Result(instruction, closedWorld)) { 602 if (hasUint31Result(instruction, closedWorld)) {
624 return newBuiltinVariant( 603 return newBuiltinVariant(instruction, results, options, closedWorld);
625 instruction, results, options, helpers, closedWorld);
626 } 604 }
627 // We can call _tdivFast because the rhs is a 32bit integer 605 // We can call _tdivFast because the rhs is a 32bit integer
628 // and not 0, nor -1. 606 // and not 0, nor -1.
629 instruction.selector = renameToOptimizedSelector( 607 instruction.selector = renameToOptimizedSelector(
630 '_tdivFast', instruction.selector, helpers); 608 '_tdivFast', instruction.selector, commonElements);
631 } 609 }
632 clearAllSideEffects(instruction); 610 clearAllSideEffects(instruction);
633 } 611 }
634 return null; 612 return null;
635 } 613 }
636 614
637 HInstruction newBuiltinVariant( 615 HInstruction newBuiltinVariant(
638 HInvokeDynamic instruction, 616 HInvokeDynamic instruction,
639 GlobalTypeInferenceResults results, 617 GlobalTypeInferenceResults results,
640 CompilerOptions options, 618 CompilerOptions options,
641 BackendHelpers helpers,
642 ClosedWorld closedWorld) { 619 ClosedWorld closedWorld) {
643 return new HTruncatingDivide( 620 return new HTruncatingDivide(
644 instruction.inputs[1], 621 instruction.inputs[1],
645 instruction.inputs[2], 622 instruction.inputs[2],
646 instruction.selector, 623 instruction.selector,
647 computeTypeFromInputTypes( 624 computeTypeFromInputTypes(instruction, results, options, closedWorld));
648 instruction, results, options, helpers, closedWorld));
649 } 625 }
650 } 626 }
651 627
652 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer { 628 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
653 const BinaryBitOpSpecializer(); 629 const BinaryBitOpSpecializer();
654 630
655 TypeMask computeTypeFromInputTypes( 631 TypeMask computeTypeFromInputTypes(
656 HInvokeDynamic instruction, 632 HInvokeDynamic instruction,
657 GlobalTypeInferenceResults results, 633 GlobalTypeInferenceResults results,
658 CompilerOptions options, 634 CompilerOptions options,
659 BackendHelpers helpers,
660 ClosedWorld closedWorld) { 635 ClosedWorld closedWorld) {
661 // All bitwise operations on primitive types either produce an 636 // All bitwise operations on primitive types either produce an
662 // integer or throw an error. 637 // integer or throw an error.
663 HInstruction left = instruction.inputs[1]; 638 HInstruction left = instruction.inputs[1];
664 if (left.isPrimitiveOrNull(closedWorld)) { 639 if (left.isPrimitiveOrNull(closedWorld)) {
665 return closedWorld.commonMasks.uint32Type; 640 return closedWorld.commonMasks.uint32Type;
666 } 641 }
667 return super.computeTypeFromInputTypes( 642 return super
668 instruction, results, options, helpers, closedWorld); 643 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
669 } 644 }
670 645
671 bool argumentLessThan32(HInstruction instruction) { 646 bool argumentLessThan32(HInstruction instruction) {
672 return argumentInRange(instruction, 0, 31); 647 return argumentInRange(instruction, 0, 31);
673 } 648 }
674 649
675 bool argumentInRange(HInstruction instruction, int low, int high) { 650 bool argumentInRange(HInstruction instruction, int low, int high) {
676 if (instruction.isConstantInteger()) { 651 if (instruction.isConstantInteger()) {
677 HConstant rightConstant = instruction; 652 HConstant rightConstant = instruction;
678 IntConstantValue intConstant = rightConstant.constant; 653 IntConstantValue intConstant = rightConstant.constant;
(...skipping 21 matching lines...) Expand all
700 675
701 BinaryOperation operation(ConstantSystem constantSystem) { 676 BinaryOperation operation(ConstantSystem constantSystem) {
702 return constantSystem.shiftLeft; 677 return constantSystem.shiftLeft;
703 } 678 }
704 679
705 HInstruction tryConvertToBuiltin( 680 HInstruction tryConvertToBuiltin(
706 HInvokeDynamic instruction, 681 HInvokeDynamic instruction,
707 HGraph graph, 682 HGraph graph,
708 GlobalTypeInferenceResults results, 683 GlobalTypeInferenceResults results,
709 CompilerOptions options, 684 CompilerOptions options,
710 BackendHelpers helpers, 685 CommonElements commonElements,
711 ClosedWorld closedWorld) { 686 ClosedWorld closedWorld) {
712 HInstruction left = instruction.inputs[1]; 687 HInstruction left = instruction.inputs[1];
713 HInstruction right = instruction.inputs[2]; 688 HInstruction right = instruction.inputs[2];
714 if (left.isNumber(closedWorld)) { 689 if (left.isNumber(closedWorld)) {
715 if (argumentLessThan32(right)) { 690 if (argumentLessThan32(right)) {
716 return newBuiltinVariant( 691 return newBuiltinVariant(instruction, results, options, closedWorld);
717 instruction, results, options, helpers, closedWorld);
718 } 692 }
719 // Even if there is no builtin equivalent instruction, we know 693 // Even if there is no builtin equivalent instruction, we know
720 // the instruction does not have any side effect, and that it 694 // the instruction does not have any side effect, and that it
721 // can be GVN'ed. 695 // can be GVN'ed.
722 clearAllSideEffects(instruction); 696 clearAllSideEffects(instruction);
723 if (isPositive(right, closedWorld)) { 697 if (isPositive(right, closedWorld)) {
724 instruction.selector = renameToOptimizedSelector( 698 instruction.selector = renameToOptimizedSelector(
725 '_shlPositive', instruction.selector, helpers); 699 '_shlPositive', instruction.selector, commonElements);
726 } 700 }
727 } 701 }
728 return null; 702 return null;
729 } 703 }
730 704
731 HInstruction newBuiltinVariant( 705 HInstruction newBuiltinVariant(
732 HInvokeDynamic instruction, 706 HInvokeDynamic instruction,
733 GlobalTypeInferenceResults results, 707 GlobalTypeInferenceResults results,
734 CompilerOptions options, 708 CompilerOptions options,
735 BackendHelpers helpers,
736 ClosedWorld closedWorld) { 709 ClosedWorld closedWorld) {
737 return new HShiftLeft( 710 return new HShiftLeft(
738 instruction.inputs[1], 711 instruction.inputs[1],
739 instruction.inputs[2], 712 instruction.inputs[2],
740 instruction.selector, 713 instruction.selector,
741 computeTypeFromInputTypes( 714 computeTypeFromInputTypes(instruction, results, options, closedWorld));
742 instruction, results, options, helpers, closedWorld));
743 } 715 }
744 } 716 }
745 717
746 class ShiftRightSpecializer extends BinaryBitOpSpecializer { 718 class ShiftRightSpecializer extends BinaryBitOpSpecializer {
747 const ShiftRightSpecializer(); 719 const ShiftRightSpecializer();
748 720
749 TypeMask computeTypeFromInputTypes( 721 TypeMask computeTypeFromInputTypes(
750 HInvokeDynamic instruction, 722 HInvokeDynamic instruction,
751 GlobalTypeInferenceResults results, 723 GlobalTypeInferenceResults results,
752 CompilerOptions options, 724 CompilerOptions options,
753 BackendHelpers helpers,
754 ClosedWorld closedWorld) { 725 ClosedWorld closedWorld) {
755 HInstruction left = instruction.inputs[1]; 726 HInstruction left = instruction.inputs[1];
756 if (left.isUInt32(closedWorld)) return left.instructionType; 727 if (left.isUInt32(closedWorld)) return left.instructionType;
757 return super.computeTypeFromInputTypes( 728 return super
758 instruction, results, options, helpers, closedWorld); 729 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
759 } 730 }
760 731
761 HInstruction tryConvertToBuiltin( 732 HInstruction tryConvertToBuiltin(
762 HInvokeDynamic instruction, 733 HInvokeDynamic instruction,
763 HGraph graph, 734 HGraph graph,
764 GlobalTypeInferenceResults results, 735 GlobalTypeInferenceResults results,
765 CompilerOptions options, 736 CompilerOptions options,
766 BackendHelpers helpers, 737 CommonElements commonElements,
767 ClosedWorld closedWorld) { 738 ClosedWorld closedWorld) {
768 HInstruction left = instruction.inputs[1]; 739 HInstruction left = instruction.inputs[1];
769 HInstruction right = instruction.inputs[2]; 740 HInstruction right = instruction.inputs[2];
770 if (left.isNumber(closedWorld)) { 741 if (left.isNumber(closedWorld)) {
771 if (argumentLessThan32(right) && isPositive(left, closedWorld)) { 742 if (argumentLessThan32(right) && isPositive(left, closedWorld)) {
772 return newBuiltinVariant( 743 return newBuiltinVariant(instruction, results, options, closedWorld);
773 instruction, results, options, helpers, closedWorld);
774 } 744 }
775 // Even if there is no builtin equivalent instruction, we know 745 // Even if there is no builtin equivalent instruction, we know
776 // the instruction does not have any side effect, and that it 746 // the instruction does not have any side effect, and that it
777 // can be GVN'ed. 747 // can be GVN'ed.
778 clearAllSideEffects(instruction); 748 clearAllSideEffects(instruction);
779 if (isPositive(right, closedWorld) && isPositive(left, closedWorld)) { 749 if (isPositive(right, closedWorld) && isPositive(left, closedWorld)) {
780 instruction.selector = renameToOptimizedSelector( 750 instruction.selector = renameToOptimizedSelector(
781 '_shrBothPositive', instruction.selector, helpers); 751 '_shrBothPositive', instruction.selector, commonElements);
782 } else if (isPositive(left, closedWorld) && right.isNumber(closedWorld)) { 752 } else if (isPositive(left, closedWorld) && right.isNumber(closedWorld)) {
783 instruction.selector = renameToOptimizedSelector( 753 instruction.selector = renameToOptimizedSelector(
784 '_shrReceiverPositive', instruction.selector, helpers); 754 '_shrReceiverPositive', instruction.selector, commonElements);
785 } else if (isPositive(right, closedWorld)) { 755 } else if (isPositive(right, closedWorld)) {
786 instruction.selector = renameToOptimizedSelector( 756 instruction.selector = renameToOptimizedSelector(
787 '_shrOtherPositive', instruction.selector, helpers); 757 '_shrOtherPositive', instruction.selector, commonElements);
788 } 758 }
789 } 759 }
790 return null; 760 return null;
791 } 761 }
792 762
793 HInstruction newBuiltinVariant( 763 HInstruction newBuiltinVariant(
794 HInvokeDynamic instruction, 764 HInvokeDynamic instruction,
795 GlobalTypeInferenceResults results, 765 GlobalTypeInferenceResults results,
796 CompilerOptions options, 766 CompilerOptions options,
797 BackendHelpers helpers,
798 ClosedWorld closedWorld) { 767 ClosedWorld closedWorld) {
799 return new HShiftRight( 768 return new HShiftRight(
800 instruction.inputs[1], 769 instruction.inputs[1],
801 instruction.inputs[2], 770 instruction.inputs[2],
802 instruction.selector, 771 instruction.selector,
803 computeTypeFromInputTypes( 772 computeTypeFromInputTypes(instruction, results, options, closedWorld));
804 instruction, results, options, helpers, closedWorld));
805 } 773 }
806 774
807 BinaryOperation operation(ConstantSystem constantSystem) { 775 BinaryOperation operation(ConstantSystem constantSystem) {
808 return constantSystem.shiftRight; 776 return constantSystem.shiftRight;
809 } 777 }
810 } 778 }
811 779
812 class BitOrSpecializer extends BinaryBitOpSpecializer { 780 class BitOrSpecializer extends BinaryBitOpSpecializer {
813 const BitOrSpecializer(); 781 const BitOrSpecializer();
814 782
815 BinaryOperation operation(ConstantSystem constantSystem) { 783 BinaryOperation operation(ConstantSystem constantSystem) {
816 return constantSystem.bitOr; 784 return constantSystem.bitOr;
817 } 785 }
818 786
819 TypeMask computeTypeFromInputTypes( 787 TypeMask computeTypeFromInputTypes(
820 HInvokeDynamic instruction, 788 HInvokeDynamic instruction,
821 GlobalTypeInferenceResults results, 789 GlobalTypeInferenceResults results,
822 CompilerOptions options, 790 CompilerOptions options,
823 BackendHelpers helpers,
824 ClosedWorld closedWorld) { 791 ClosedWorld closedWorld) {
825 HInstruction left = instruction.inputs[1]; 792 HInstruction left = instruction.inputs[1];
826 HInstruction right = instruction.inputs[2]; 793 HInstruction right = instruction.inputs[2];
827 if (left.isUInt31(closedWorld) && right.isUInt31(closedWorld)) { 794 if (left.isUInt31(closedWorld) && right.isUInt31(closedWorld)) {
828 return closedWorld.commonMasks.uint31Type; 795 return closedWorld.commonMasks.uint31Type;
829 } 796 }
830 return super.computeTypeFromInputTypes( 797 return super
831 instruction, results, options, helpers, closedWorld); 798 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
832 } 799 }
833 800
834 HInstruction newBuiltinVariant( 801 HInstruction newBuiltinVariant(
835 HInvokeDynamic instruction, 802 HInvokeDynamic instruction,
836 GlobalTypeInferenceResults results, 803 GlobalTypeInferenceResults results,
837 CompilerOptions options, 804 CompilerOptions options,
838 BackendHelpers helpers,
839 ClosedWorld closedWorld) { 805 ClosedWorld closedWorld) {
840 return new HBitOr( 806 return new HBitOr(
841 instruction.inputs[1], 807 instruction.inputs[1],
842 instruction.inputs[2], 808 instruction.inputs[2],
843 instruction.selector, 809 instruction.selector,
844 computeTypeFromInputTypes( 810 computeTypeFromInputTypes(instruction, results, options, closedWorld));
845 instruction, results, options, helpers, closedWorld));
846 } 811 }
847 } 812 }
848 813
849 class BitAndSpecializer extends BinaryBitOpSpecializer { 814 class BitAndSpecializer extends BinaryBitOpSpecializer {
850 const BitAndSpecializer(); 815 const BitAndSpecializer();
851 816
852 BinaryOperation operation(ConstantSystem constantSystem) { 817 BinaryOperation operation(ConstantSystem constantSystem) {
853 return constantSystem.bitAnd; 818 return constantSystem.bitAnd;
854 } 819 }
855 820
856 TypeMask computeTypeFromInputTypes( 821 TypeMask computeTypeFromInputTypes(
857 HInvokeDynamic instruction, 822 HInvokeDynamic instruction,
858 GlobalTypeInferenceResults results, 823 GlobalTypeInferenceResults results,
859 CompilerOptions options, 824 CompilerOptions options,
860 BackendHelpers helpers,
861 ClosedWorld closedWorld) { 825 ClosedWorld closedWorld) {
862 HInstruction left = instruction.inputs[1]; 826 HInstruction left = instruction.inputs[1];
863 HInstruction right = instruction.inputs[2]; 827 HInstruction right = instruction.inputs[2];
864 if (left.isPrimitiveOrNull(closedWorld) && 828 if (left.isPrimitiveOrNull(closedWorld) &&
865 (left.isUInt31(closedWorld) || right.isUInt31(closedWorld))) { 829 (left.isUInt31(closedWorld) || right.isUInt31(closedWorld))) {
866 return closedWorld.commonMasks.uint31Type; 830 return closedWorld.commonMasks.uint31Type;
867 } 831 }
868 return super.computeTypeFromInputTypes( 832 return super
869 instruction, results, options, helpers, closedWorld); 833 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
870 } 834 }
871 835
872 HInstruction newBuiltinVariant( 836 HInstruction newBuiltinVariant(
873 HInvokeDynamic instruction, 837 HInvokeDynamic instruction,
874 GlobalTypeInferenceResults results, 838 GlobalTypeInferenceResults results,
875 CompilerOptions options, 839 CompilerOptions options,
876 BackendHelpers helpers,
877 ClosedWorld closedWorld) { 840 ClosedWorld closedWorld) {
878 return new HBitAnd( 841 return new HBitAnd(
879 instruction.inputs[1], 842 instruction.inputs[1],
880 instruction.inputs[2], 843 instruction.inputs[2],
881 instruction.selector, 844 instruction.selector,
882 computeTypeFromInputTypes( 845 computeTypeFromInputTypes(instruction, results, options, closedWorld));
883 instruction, results, options, helpers, closedWorld));
884 } 846 }
885 } 847 }
886 848
887 class BitXorSpecializer extends BinaryBitOpSpecializer { 849 class BitXorSpecializer extends BinaryBitOpSpecializer {
888 const BitXorSpecializer(); 850 const BitXorSpecializer();
889 851
890 BinaryOperation operation(ConstantSystem constantSystem) { 852 BinaryOperation operation(ConstantSystem constantSystem) {
891 return constantSystem.bitXor; 853 return constantSystem.bitXor;
892 } 854 }
893 855
894 TypeMask computeTypeFromInputTypes( 856 TypeMask computeTypeFromInputTypes(
895 HInvokeDynamic instruction, 857 HInvokeDynamic instruction,
896 GlobalTypeInferenceResults results, 858 GlobalTypeInferenceResults results,
897 CompilerOptions options, 859 CompilerOptions options,
898 BackendHelpers helpers,
899 ClosedWorld closedWorld) { 860 ClosedWorld closedWorld) {
900 HInstruction left = instruction.inputs[1]; 861 HInstruction left = instruction.inputs[1];
901 HInstruction right = instruction.inputs[2]; 862 HInstruction right = instruction.inputs[2];
902 if (left.isUInt31(closedWorld) && right.isUInt31(closedWorld)) { 863 if (left.isUInt31(closedWorld) && right.isUInt31(closedWorld)) {
903 return closedWorld.commonMasks.uint31Type; 864 return closedWorld.commonMasks.uint31Type;
904 } 865 }
905 return super.computeTypeFromInputTypes( 866 return super
906 instruction, results, options, helpers, closedWorld); 867 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
907 } 868 }
908 869
909 HInstruction newBuiltinVariant( 870 HInstruction newBuiltinVariant(
910 HInvokeDynamic instruction, 871 HInvokeDynamic instruction,
911 GlobalTypeInferenceResults results, 872 GlobalTypeInferenceResults results,
912 CompilerOptions options, 873 CompilerOptions options,
913 BackendHelpers helpers,
914 ClosedWorld closedWorld) { 874 ClosedWorld closedWorld) {
915 return new HBitXor( 875 return new HBitXor(
916 instruction.inputs[1], 876 instruction.inputs[1],
917 instruction.inputs[2], 877 instruction.inputs[2],
918 instruction.selector, 878 instruction.selector,
919 computeTypeFromInputTypes( 879 computeTypeFromInputTypes(instruction, results, options, closedWorld));
920 instruction, results, options, helpers, closedWorld));
921 } 880 }
922 } 881 }
923 882
924 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { 883 abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
925 const RelationalSpecializer(); 884 const RelationalSpecializer();
926 885
927 TypeMask computeTypeFromInputTypes( 886 TypeMask computeTypeFromInputTypes(
928 HInvokeDynamic instruction, 887 HInvokeDynamic instruction,
929 GlobalTypeInferenceResults results, 888 GlobalTypeInferenceResults results,
930 CompilerOptions options, 889 CompilerOptions options,
931 BackendHelpers helpers,
932 ClosedWorld closedWorld) { 890 ClosedWorld closedWorld) {
933 if (instruction.inputs[1].isPrimitiveOrNull(closedWorld)) { 891 if (instruction.inputs[1].isPrimitiveOrNull(closedWorld)) {
934 return closedWorld.commonMasks.boolType; 892 return closedWorld.commonMasks.boolType;
935 } 893 }
936 return super.computeTypeFromInputTypes( 894 return super
937 instruction, results, options, helpers, closedWorld); 895 .computeTypeFromInputTypes(instruction, results, options, closedWorld);
938 } 896 }
939 897
940 HInstruction tryConvertToBuiltin( 898 HInstruction tryConvertToBuiltin(
941 HInvokeDynamic instruction, 899 HInvokeDynamic instruction,
942 HGraph graph, 900 HGraph graph,
943 GlobalTypeInferenceResults results, 901 GlobalTypeInferenceResults results,
944 CompilerOptions options, 902 CompilerOptions options,
945 BackendHelpers helpers, 903 CommonElements commonElements,
946 ClosedWorld closedWorld) { 904 ClosedWorld closedWorld) {
947 HInstruction left = instruction.inputs[1]; 905 HInstruction left = instruction.inputs[1];
948 HInstruction right = instruction.inputs[2]; 906 HInstruction right = instruction.inputs[2];
949 if (left.isNumber(closedWorld) && right.isNumber(closedWorld)) { 907 if (left.isNumber(closedWorld) && right.isNumber(closedWorld)) {
950 return newBuiltinVariant(instruction, closedWorld); 908 return newBuiltinVariant(instruction, closedWorld);
951 } 909 }
952 return null; 910 return null;
953 } 911 }
954 912
955 HInstruction newBuiltinVariant( 913 HInstruction newBuiltinVariant(
956 HInvokeDynamic instruction, ClosedWorld closedWorld); 914 HInvokeDynamic instruction, ClosedWorld closedWorld);
957 } 915 }
958 916
959 class EqualsSpecializer extends RelationalSpecializer { 917 class EqualsSpecializer extends RelationalSpecializer {
960 const EqualsSpecializer(); 918 const EqualsSpecializer();
961 919
962 HInstruction tryConvertToBuiltin( 920 HInstruction tryConvertToBuiltin(
963 HInvokeDynamic instruction, 921 HInvokeDynamic instruction,
964 HGraph graph, 922 HGraph graph,
965 GlobalTypeInferenceResults results, 923 GlobalTypeInferenceResults results,
966 CompilerOptions options, 924 CompilerOptions options,
967 BackendHelpers helpers, 925 CommonElements commonElements,
968 ClosedWorld closedWorld) { 926 ClosedWorld closedWorld) {
969 HInstruction left = instruction.inputs[1]; 927 HInstruction left = instruction.inputs[1];
970 HInstruction right = instruction.inputs[2]; 928 HInstruction right = instruction.inputs[2];
971 TypeMask instructionType = left.instructionType; 929 TypeMask instructionType = left.instructionType;
972 if (right.isConstantNull() || left.isPrimitiveOrNull(closedWorld)) { 930 if (right.isConstantNull() || left.isPrimitiveOrNull(closedWorld)) {
973 return newBuiltinVariant(instruction, closedWorld); 931 return newBuiltinVariant(instruction, closedWorld);
974 } 932 }
975 Iterable<MemberEntity> matches = 933 Iterable<MemberEntity> matches =
976 closedWorld.allFunctions.filter(instruction.selector, instructionType); 934 closedWorld.allFunctions.filter(instruction.selector, instructionType);
977 // This test relies the on `Object.==` and `Interceptor.==` always being 935 // This test relies the on `Object.==` and `Interceptor.==` always being
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 1014
1057 BinaryOperation operation(ConstantSystem constantSystem) { 1015 BinaryOperation operation(ConstantSystem constantSystem) {
1058 return constantSystem.codeUnitAt; 1016 return constantSystem.codeUnitAt;
1059 } 1017 }
1060 1018
1061 HInstruction tryConvertToBuiltin( 1019 HInstruction tryConvertToBuiltin(
1062 HInvokeDynamic instruction, 1020 HInvokeDynamic instruction,
1063 HGraph graph, 1021 HGraph graph,
1064 GlobalTypeInferenceResults results, 1022 GlobalTypeInferenceResults results,
1065 CompilerOptions options, 1023 CompilerOptions options,
1066 BackendHelpers helpers, 1024 CommonElements commonElements,
1067 ClosedWorld closedWorld) { 1025 ClosedWorld closedWorld) {
1068 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index 1026 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index
1069 // bounds checking optimizations as for HIndex. 1027 // bounds checking optimizations as for HIndex.
1070 HInstruction receiver = instruction.getDartReceiver(closedWorld); 1028 HInstruction receiver = instruction.getDartReceiver(closedWorld);
1071 if (receiver.isStringOrNull(closedWorld)) { 1029 if (receiver.isStringOrNull(closedWorld)) {
1072 // Even if there is no builtin equivalent instruction, we know 1030 // Even if there is no builtin equivalent instruction, we know
1073 // String.codeUnitAt does not have any side effect (other than throwing), 1031 // String.codeUnitAt does not have any side effect (other than throwing),
1074 // and that it can be GVN'ed. 1032 // and that it can be GVN'ed.
1075 clearAllSideEffects(instruction); 1033 clearAllSideEffects(instruction);
1076 if (instruction.inputs.last.isPositiveInteger(closedWorld)) { 1034 if (instruction.inputs.last.isPositiveInteger(closedWorld)) {
1077 instruction.selector = renameToOptimizedSelector( 1035 instruction.selector = renameToOptimizedSelector(
1078 '_codeUnitAt', instruction.selector, helpers); 1036 '_codeUnitAt', instruction.selector, commonElements);
1079 } 1037 }
1080 } 1038 }
1081 return null; 1039 return null;
1082 } 1040 }
1083 } 1041 }
1084 1042
1085 class CompareToSpecializer extends InvokeDynamicSpecializer { 1043 class CompareToSpecializer extends InvokeDynamicSpecializer {
1086 const CompareToSpecializer(); 1044 const CompareToSpecializer();
1087 1045
1088 HInstruction tryConvertToBuiltin( 1046 HInstruction tryConvertToBuiltin(
1089 HInvokeDynamic instruction, 1047 HInvokeDynamic instruction,
1090 HGraph graph, 1048 HGraph graph,
1091 GlobalTypeInferenceResults results, 1049 GlobalTypeInferenceResults results,
1092 CompilerOptions options, 1050 CompilerOptions options,
1093 BackendHelpers helpers, 1051 CommonElements commonElements,
1094 ClosedWorld closedWorld) { 1052 ClosedWorld closedWorld) {
1095 HInstruction receiver = instruction.getDartReceiver(closedWorld); 1053 HInstruction receiver = instruction.getDartReceiver(closedWorld);
1096 // `compareTo` has no side-effect (other than throwing) and can be GVN'ed 1054 // `compareTo` has no side-effect (other than throwing) and can be GVN'ed
1097 // for some known types. 1055 // for some known types.
1098 if (receiver.isStringOrNull(closedWorld) || 1056 if (receiver.isStringOrNull(closedWorld) ||
1099 receiver.isNumberOrNull(closedWorld)) { 1057 receiver.isNumberOrNull(closedWorld)) {
1100 // Replace `a.compareTo(a)` with `0`, but only if receiver and argument 1058 // Replace `a.compareTo(a)` with `0`, but only if receiver and argument
1101 // are such that no exceptions can be thrown. 1059 // are such that no exceptions can be thrown.
1102 HInstruction argument = instruction.inputs.last; 1060 HInstruction argument = instruction.inputs.last;
1103 if ((receiver.isNumber(closedWorld) && argument.isNumber(closedWorld)) || 1061 if ((receiver.isNumber(closedWorld) && argument.isNumber(closedWorld)) ||
1104 (receiver.isString(closedWorld) && argument.isString(closedWorld))) { 1062 (receiver.isString(closedWorld) && argument.isString(closedWorld))) {
1105 if (identical(receiver.nonCheck(), argument.nonCheck())) { 1063 if (identical(receiver.nonCheck(), argument.nonCheck())) {
1106 return graph.addConstantInt(0, closedWorld); 1064 return graph.addConstantInt(0, closedWorld);
1107 } 1065 }
1108 } 1066 }
1109 clearAllSideEffects(instruction); 1067 clearAllSideEffects(instruction);
1110 } 1068 }
1111 return null; 1069 return null;
1112 } 1070 }
1113 } 1071 }
1114 1072
1115 class IdempotentStringOperationSpecializer extends InvokeDynamicSpecializer { 1073 class IdempotentStringOperationSpecializer extends InvokeDynamicSpecializer {
1116 const IdempotentStringOperationSpecializer(); 1074 const IdempotentStringOperationSpecializer();
1117 1075
1118 HInstruction tryConvertToBuiltin( 1076 HInstruction tryConvertToBuiltin(
1119 HInvokeDynamic instruction, 1077 HInvokeDynamic instruction,
1120 HGraph graph, 1078 HGraph graph,
1121 GlobalTypeInferenceResults results, 1079 GlobalTypeInferenceResults results,
1122 CompilerOptions options, 1080 CompilerOptions options,
1123 BackendHelpers helpers, 1081 CommonElements commonElements,
1124 ClosedWorld closedWorld) { 1082 ClosedWorld closedWorld) {
1125 HInstruction receiver = instruction.getDartReceiver(closedWorld); 1083 HInstruction receiver = instruction.getDartReceiver(closedWorld);
1126 if (receiver.isStringOrNull(closedWorld)) { 1084 if (receiver.isStringOrNull(closedWorld)) {
1127 // String.xxx does not have any side effect (other than throwing), and it 1085 // String.xxx does not have any side effect (other than throwing), and it
1128 // can be GVN'ed. 1086 // can be GVN'ed.
1129 clearAllSideEffects(instruction); 1087 clearAllSideEffects(instruction);
1130 } 1088 }
1131 return null; 1089 return null;
1132 } 1090 }
1133 } 1091 }
1134 1092
1135 class SubstringSpecializer extends IdempotentStringOperationSpecializer { 1093 class SubstringSpecializer extends IdempotentStringOperationSpecializer {
1136 const SubstringSpecializer(); 1094 const SubstringSpecializer();
1137 } 1095 }
1138 1096
1139 class TrimSpecializer extends IdempotentStringOperationSpecializer { 1097 class TrimSpecializer extends IdempotentStringOperationSpecializer {
1140 const TrimSpecializer(); 1098 const TrimSpecializer();
1141 } 1099 }
1142 1100
1143 class PatternMatchSpecializer extends InvokeDynamicSpecializer { 1101 class PatternMatchSpecializer extends InvokeDynamicSpecializer {
1144 const PatternMatchSpecializer(); 1102 const PatternMatchSpecializer();
1145 1103
1146 HInstruction tryConvertToBuiltin( 1104 HInstruction tryConvertToBuiltin(
1147 HInvokeDynamic instruction, 1105 HInvokeDynamic instruction,
1148 HGraph graph, 1106 HGraph graph,
1149 GlobalTypeInferenceResults results, 1107 GlobalTypeInferenceResults results,
1150 CompilerOptions options, 1108 CompilerOptions options,
1151 BackendHelpers helpers, 1109 CommonElements commonElements,
1152 ClosedWorld closedWorld) { 1110 ClosedWorld closedWorld) {
1153 HInstruction receiver = instruction.getDartReceiver(closedWorld); 1111 HInstruction receiver = instruction.getDartReceiver(closedWorld);
1154 HInstruction pattern = instruction.inputs[2]; 1112 HInstruction pattern = instruction.inputs[2];
1155 if (receiver.isStringOrNull(closedWorld) && 1113 if (receiver.isStringOrNull(closedWorld) &&
1156 pattern.isStringOrNull(closedWorld)) { 1114 pattern.isStringOrNull(closedWorld)) {
1157 // String.contains(String s) does not have any side effect (other than 1115 // String.contains(String s) does not have any side effect (other than
1158 // throwing), and it can be GVN'ed. 1116 // throwing), and it can be GVN'ed.
1159 clearAllSideEffects(instruction); 1117 clearAllSideEffects(instruction);
1160 } 1118 }
1161 return null; 1119 return null;
1162 } 1120 }
1163 } 1121 }
1164 1122
1165 class RoundSpecializer extends InvokeDynamicSpecializer { 1123 class RoundSpecializer extends InvokeDynamicSpecializer {
1166 const RoundSpecializer(); 1124 const RoundSpecializer();
1167 1125
1168 UnaryOperation operation(ConstantSystem constantSystem) { 1126 UnaryOperation operation(ConstantSystem constantSystem) {
1169 return constantSystem.round; 1127 return constantSystem.round;
1170 } 1128 }
1171 1129
1172 HInstruction tryConvertToBuiltin( 1130 HInstruction tryConvertToBuiltin(
1173 HInvokeDynamic instruction, 1131 HInvokeDynamic instruction,
1174 HGraph graph, 1132 HGraph graph,
1175 GlobalTypeInferenceResults results, 1133 GlobalTypeInferenceResults results,
1176 CompilerOptions options, 1134 CompilerOptions options,
1177 BackendHelpers helpers, 1135 CommonElements commonElements,
1178 ClosedWorld closedWorld) { 1136 ClosedWorld closedWorld) {
1179 HInstruction receiver = instruction.getDartReceiver(closedWorld); 1137 HInstruction receiver = instruction.getDartReceiver(closedWorld);
1180 if (receiver.isNumberOrNull(closedWorld)) { 1138 if (receiver.isNumberOrNull(closedWorld)) {
1181 // Even if there is no builtin equivalent instruction, we know the 1139 // Even if there is no builtin equivalent instruction, we know the
1182 // instruction does not have any side effect, and that it can be GVN'ed. 1140 // instruction does not have any side effect, and that it can be GVN'ed.
1183 clearAllSideEffects(instruction); 1141 clearAllSideEffects(instruction);
1184 } 1142 }
1185 return null; 1143 return null;
1186 } 1144 }
1187 } 1145 }
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