OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/simplified-operator.h" | 5 #include "src/compiler/simplified-operator.h" |
6 | 6 |
7 #include "src/base/lazy-instance.h" | 7 #include "src/base/lazy-instance.h" |
8 #include "src/compiler/opcodes.h" | 8 #include "src/compiler/opcodes.h" |
9 #include "src/compiler/operator.h" | 9 #include "src/compiler/operator.h" |
10 #include "src/types.h" | 10 #include "src/types.h" |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 V(StringLessThanOrEqual, Operator::kNoProperties, 2) | 302 V(StringLessThanOrEqual, Operator::kNoProperties, 2) |
303 | 303 |
304 #define SPECULATIVE_BINOP_LIST(V) \ | 304 #define SPECULATIVE_BINOP_LIST(V) \ |
305 V(SpeculativeNumberAdd) \ | 305 V(SpeculativeNumberAdd) \ |
306 V(SpeculativeNumberSubtract) \ | 306 V(SpeculativeNumberSubtract) \ |
307 V(SpeculativeNumberDivide) \ | 307 V(SpeculativeNumberDivide) \ |
308 V(SpeculativeNumberMultiply) \ | 308 V(SpeculativeNumberMultiply) \ |
309 V(SpeculativeNumberModulus) | 309 V(SpeculativeNumberModulus) |
310 | 310 |
311 #define CHECKED_OP_LIST(V) \ | 311 #define CHECKED_OP_LIST(V) \ |
| 312 V(CheckTaggedPointer) \ |
| 313 V(CheckTaggedSigned) \ |
312 V(CheckedUint32ToInt32) \ | 314 V(CheckedUint32ToInt32) \ |
313 V(CheckedFloat64ToInt32) \ | 315 V(CheckedFloat64ToInt32) \ |
314 V(CheckedTaggedToInt32) \ | 316 V(CheckedTaggedToInt32) \ |
315 V(CheckedTaggedToFloat64) | 317 V(CheckedTaggedToFloat64) |
316 | 318 |
317 struct SimplifiedOperatorGlobalCache final { | 319 struct SimplifiedOperatorGlobalCache final { |
318 #define PURE(Name, properties, input_count) \ | 320 #define PURE(Name, properties, input_count) \ |
319 struct Name##Operator final : public Operator { \ | 321 struct Name##Operator final : public Operator { \ |
320 Name##Operator() \ | 322 Name##Operator() \ |
321 : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \ | 323 : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \ |
322 input_count, 0, 0, 1, 0, 0) {} \ | 324 input_count, 0, 0, 1, 0, 0) {} \ |
323 }; \ | 325 }; \ |
324 Name##Operator k##Name; | 326 Name##Operator k##Name; |
325 PURE_OP_LIST(PURE) | 327 PURE_OP_LIST(PURE) |
326 #undef PURE | 328 #undef PURE |
327 | 329 |
328 #define CHECKED(Name) \ | 330 #define CHECKED(Name) \ |
329 struct Name##Operator final : public Operator { \ | 331 struct Name##Operator final : public Operator { \ |
330 Name##Operator() \ | 332 Name##Operator() \ |
331 : Operator(IrOpcode::k##Name, Operator::kPure, #Name, 1, 1, 1, 1, 1, \ | 333 : Operator(IrOpcode::k##Name, \ |
332 0) {} \ | 334 Operator::kFoldable | Operator::kNoThrow, #Name, 1, 1, 1, \ |
| 335 1, 1, 0) {} \ |
333 }; \ | 336 }; \ |
334 Name##Operator k##Name; | 337 Name##Operator k##Name; |
335 CHECKED_OP_LIST(CHECKED) | 338 CHECKED_OP_LIST(CHECKED) |
336 #undef CHECKED | 339 #undef CHECKED |
337 | 340 |
338 template <CheckFloat64HoleMode kMode> | 341 template <CheckFloat64HoleMode kMode> |
339 struct CheckFloat64HoleNaNOperatortor final | 342 struct CheckFloat64HoleNaNOperatortor final |
340 : public Operator1<CheckFloat64HoleMode> { | 343 : public Operator1<CheckFloat64HoleMode> { |
341 CheckFloat64HoleNaNOperatortor() | 344 CheckFloat64HoleNaNOperatortor() |
342 : Operator1<CheckFloat64HoleMode>(IrOpcode::kCheckFloat64Hole, | 345 : Operator1<CheckFloat64HoleMode>( |
343 Operator::kPure, "CheckFloat64Hole", | 346 IrOpcode::kCheckFloat64Hole, |
344 1, 1, 1, 1, 1, 0, kMode) {} | 347 Operator::kFoldable | Operator::kNoDeopt, "CheckFloat64Hole", 1, |
| 348 1, 1, 1, 1, 0, kMode) {} |
345 }; | 349 }; |
346 CheckFloat64HoleNaNOperatortor<CheckFloat64HoleMode::kAllowReturnHole> | 350 CheckFloat64HoleNaNOperatortor<CheckFloat64HoleMode::kAllowReturnHole> |
347 kCheckFloat64HoleAllowReturnHoleOperator; | 351 kCheckFloat64HoleAllowReturnHoleOperator; |
348 CheckFloat64HoleNaNOperatortor<CheckFloat64HoleMode::kNeverReturnHole> | 352 CheckFloat64HoleNaNOperatortor<CheckFloat64HoleMode::kNeverReturnHole> |
349 kCheckFloat64HoleNeverReturnHoleOperator; | 353 kCheckFloat64HoleNeverReturnHoleOperator; |
350 | 354 |
351 template <CheckTaggedHoleMode kMode> | 355 template <CheckTaggedHoleMode kMode> |
352 struct CheckTaggedHoleOperator final : public Operator1<CheckTaggedHoleMode> { | 356 struct CheckTaggedHoleOperator final : public Operator1<CheckTaggedHoleMode> { |
353 CheckTaggedHoleOperator() | 357 CheckTaggedHoleOperator() |
354 : Operator1<CheckTaggedHoleMode>(IrOpcode::kCheckTaggedHole, | 358 : Operator1<CheckTaggedHoleMode>( |
355 Operator::kPure, "CheckTaggedHole", 1, | 359 IrOpcode::kCheckTaggedHole, |
356 1, 1, 1, 1, 0, kMode) {} | 360 Operator::kFoldable | Operator::kNoDeopt, "CheckTaggedHole", 1, 1, |
| 361 1, 1, 1, 0, kMode) {} |
357 }; | 362 }; |
358 CheckTaggedHoleOperator<CheckTaggedHoleMode::kConvertHoleToUndefined> | 363 CheckTaggedHoleOperator<CheckTaggedHoleMode::kConvertHoleToUndefined> |
359 kCheckTaggedHoleConvertHoleToUndefinedOperator; | 364 kCheckTaggedHoleConvertHoleToUndefinedOperator; |
360 CheckTaggedHoleOperator<CheckTaggedHoleMode::kNeverReturnHole> | 365 CheckTaggedHoleOperator<CheckTaggedHoleMode::kNeverReturnHole> |
361 kCheckTaggedHoleNeverReturnHoleOperator; | 366 kCheckTaggedHoleNeverReturnHoleOperator; |
362 | 367 |
363 struct CheckIfOperator final : public Operator { | 368 struct CheckIfOperator final : public Operator { |
364 CheckIfOperator() | 369 CheckIfOperator() |
365 : Operator(IrOpcode::kCheckIf, Operator::kPure, "CheckIf", 1, 1, 1, 0, | 370 : Operator(IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoDeopt, |
366 1, 0) {} | 371 "CheckIf", 1, 1, 1, 0, 1, 0) {} |
367 }; | 372 }; |
368 CheckIfOperator kCheckIf; | 373 CheckIfOperator kCheckIf; |
369 | 374 |
370 template <PretenureFlag kPretenure> | 375 template <PretenureFlag kPretenure> |
371 struct AllocateOperator final : public Operator1<PretenureFlag> { | 376 struct AllocateOperator final : public Operator1<PretenureFlag> { |
372 AllocateOperator() | 377 AllocateOperator() |
373 : Operator1<PretenureFlag>(IrOpcode::kAllocate, Operator::kNoThrow, | 378 : Operator1<PretenureFlag>( |
374 "Allocate", 1, 1, 1, 1, 1, 0, kPretenure) {} | 379 IrOpcode::kAllocate, |
| 380 Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, |
| 381 "Allocate", 1, 1, 1, 1, 1, 0, kPretenure) {} |
375 }; | 382 }; |
376 AllocateOperator<NOT_TENURED> kAllocateNotTenuredOperator; | 383 AllocateOperator<NOT_TENURED> kAllocateNotTenuredOperator; |
377 AllocateOperator<TENURED> kAllocateTenuredOperator; | 384 AllocateOperator<TENURED> kAllocateTenuredOperator; |
378 | 385 |
379 #define BUFFER_ACCESS(Type, type, TYPE, ctype, size) \ | 386 #define BUFFER_ACCESS(Type, type, TYPE, ctype, size) \ |
380 struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> { \ | 387 struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> { \ |
381 LoadBuffer##Type##Operator() \ | 388 LoadBuffer##Type##Operator() \ |
382 : Operator1<BufferAccess>(IrOpcode::kLoadBuffer, \ | 389 : Operator1<BufferAccess>( \ |
383 Operator::kNoThrow | Operator::kNoWrite, \ | 390 IrOpcode::kLoadBuffer, \ |
384 "LoadBuffer", 3, 1, 1, 1, 1, 0, \ | 391 Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, \ |
385 BufferAccess(kExternal##Type##Array)) {} \ | 392 "LoadBuffer", 3, 1, 1, 1, 1, 0, \ |
| 393 BufferAccess(kExternal##Type##Array)) {} \ |
386 }; \ | 394 }; \ |
387 struct StoreBuffer##Type##Operator final : public Operator1<BufferAccess> { \ | 395 struct StoreBuffer##Type##Operator final : public Operator1<BufferAccess> { \ |
388 StoreBuffer##Type##Operator() \ | 396 StoreBuffer##Type##Operator() \ |
389 : Operator1<BufferAccess>(IrOpcode::kStoreBuffer, \ | 397 : Operator1<BufferAccess>( \ |
390 Operator::kNoRead | Operator::kNoThrow, \ | 398 IrOpcode::kStoreBuffer, \ |
391 "StoreBuffer", 4, 1, 1, 0, 1, 0, \ | 399 Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow, \ |
392 BufferAccess(kExternal##Type##Array)) {} \ | 400 "StoreBuffer", 4, 1, 1, 0, 1, 0, \ |
| 401 BufferAccess(kExternal##Type##Array)) {} \ |
393 }; \ | 402 }; \ |
394 LoadBuffer##Type##Operator kLoadBuffer##Type; \ | 403 LoadBuffer##Type##Operator kLoadBuffer##Type; \ |
395 StoreBuffer##Type##Operator kStoreBuffer##Type; | 404 StoreBuffer##Type##Operator kStoreBuffer##Type; |
396 TYPED_ARRAYS(BUFFER_ACCESS) | 405 TYPED_ARRAYS(BUFFER_ACCESS) |
397 #undef BUFFER_ACCESS | 406 #undef BUFFER_ACCESS |
398 }; | 407 }; |
399 | 408 |
400 | 409 |
401 static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache = | 410 static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache = |
402 LAZY_INSTANCE_INITIALIZER; | 411 LAZY_INSTANCE_INITIALIZER; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 } | 453 } |
445 | 454 |
446 const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) { | 455 const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) { |
447 return new (zone()) Operator(IrOpcode::kReferenceEqual, | 456 return new (zone()) Operator(IrOpcode::kReferenceEqual, |
448 Operator::kCommutative | Operator::kPure, | 457 Operator::kCommutative | Operator::kPure, |
449 "ReferenceEqual", 2, 0, 0, 1, 0, 0); | 458 "ReferenceEqual", 2, 0, 0, 1, 0, 0); |
450 } | 459 } |
451 | 460 |
452 const Operator* SimplifiedOperatorBuilder::CheckBounds() { | 461 const Operator* SimplifiedOperatorBuilder::CheckBounds() { |
453 // TODO(bmeurer): Cache this operator. Make it pure! | 462 // TODO(bmeurer): Cache this operator. Make it pure! |
454 return new (zone()) Operator(IrOpcode::kCheckBounds, Operator::kPure, | 463 return new (zone()) |
455 "CheckBounds", 2, 1, 1, 1, 1, 0); | 464 Operator(IrOpcode::kCheckBounds, Operator::kFoldable | Operator::kNoThrow, |
| 465 "CheckBounds", 2, 1, 1, 1, 1, 0); |
456 } | 466 } |
457 | 467 |
458 const Operator* SimplifiedOperatorBuilder::TypeGuard(Type* type) { | 468 const Operator* SimplifiedOperatorBuilder::TypeGuard(Type* type) { |
459 class TypeGuardOperator final : public Operator1<Type*> { | 469 class TypeGuardOperator final : public Operator1<Type*> { |
460 public: | 470 public: |
461 explicit TypeGuardOperator(Type* type) | 471 explicit TypeGuardOperator(Type* type) |
462 : Operator1<Type*>( // -- | 472 : Operator1<Type*>( // -- |
463 IrOpcode::kTypeGuard, Operator::kPure, // opcode | 473 IrOpcode::kTypeGuard, Operator::kPure, // opcode |
464 "TypeGuard", // name | 474 "TypeGuard", // name |
465 1, 0, 1, 1, 0, 0, // counts | 475 1, 0, 1, 1, 0, 0, // counts |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 #define STORE_BUFFER(Type, type, TYPE, ctype, size) \ | 512 #define STORE_BUFFER(Type, type, TYPE, ctype, size) \ |
503 case kExternal##Type##Array: \ | 513 case kExternal##Type##Array: \ |
504 return &cache_.kStoreBuffer##Type; | 514 return &cache_.kStoreBuffer##Type; |
505 TYPED_ARRAYS(STORE_BUFFER) | 515 TYPED_ARRAYS(STORE_BUFFER) |
506 #undef STORE_BUFFER | 516 #undef STORE_BUFFER |
507 } | 517 } |
508 UNREACHABLE(); | 518 UNREACHABLE(); |
509 return nullptr; | 519 return nullptr; |
510 } | 520 } |
511 | 521 |
512 #define SPECULATIVE_BINOP_DEF(Name) \ | 522 #define SPECULATIVE_BINOP_DEF(Name) \ |
513 const Operator* SimplifiedOperatorBuilder::Name( \ | 523 const Operator* SimplifiedOperatorBuilder::Name( \ |
514 BinaryOperationHints::Hint hint) { \ | 524 BinaryOperationHints::Hint hint) { \ |
515 return new (zone()) Operator1<BinaryOperationHints::Hint>( \ | 525 return new (zone()) Operator1<BinaryOperationHints::Hint>( \ |
516 IrOpcode::k##Name, Operator::kPure, #Name, 2, 1, 1, 1, 1, 1, hint); \ | 526 IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, #Name, 2, \ |
| 527 1, 1, 1, 1, 1, hint); \ |
517 } | 528 } |
518 SPECULATIVE_BINOP_LIST(SPECULATIVE_BINOP_DEF) | 529 SPECULATIVE_BINOP_LIST(SPECULATIVE_BINOP_DEF) |
519 #undef SPECULATIVE_BINOP_DEF | 530 #undef SPECULATIVE_BINOP_DEF |
520 | 531 |
521 const Operator* SimplifiedOperatorBuilder::SpeculativeNumberEqual( | 532 const Operator* SimplifiedOperatorBuilder::SpeculativeNumberEqual( |
522 CompareOperationHints::Hint hint) { | 533 CompareOperationHints::Hint hint) { |
523 return new (zone()) Operator1<CompareOperationHints::Hint>( | 534 return new (zone()) Operator1<CompareOperationHints::Hint>( |
524 IrOpcode::kSpeculativeNumberEqual, Operator::kPure, | 535 IrOpcode::kSpeculativeNumberEqual, |
525 "SpeculativeNumberEqual", 2, 1, 1, 1, 1, 1, hint); | 536 Operator::kFoldable | Operator::kNoThrow, "SpeculativeNumberEqual", 2, 1, |
| 537 1, 1, 1, 1, hint); |
526 } | 538 } |
527 | 539 |
528 const Operator* SimplifiedOperatorBuilder::SpeculativeNumberLessThan( | 540 const Operator* SimplifiedOperatorBuilder::SpeculativeNumberLessThan( |
529 CompareOperationHints::Hint hint) { | 541 CompareOperationHints::Hint hint) { |
530 return new (zone()) Operator1<CompareOperationHints::Hint>( | 542 return new (zone()) Operator1<CompareOperationHints::Hint>( |
531 IrOpcode::kSpeculativeNumberLessThan, Operator::kPure, | 543 IrOpcode::kSpeculativeNumberLessThan, |
532 "SpeculativeNumberLessThan", 2, 1, 1, 1, 1, 1, hint); | 544 Operator::kFoldable | Operator::kNoThrow, "SpeculativeNumberLessThan", 2, |
| 545 1, 1, 1, 1, 1, hint); |
533 } | 546 } |
534 | 547 |
535 const Operator* SimplifiedOperatorBuilder::SpeculativeNumberLessThanOrEqual( | 548 const Operator* SimplifiedOperatorBuilder::SpeculativeNumberLessThanOrEqual( |
536 CompareOperationHints::Hint hint) { | 549 CompareOperationHints::Hint hint) { |
537 return new (zone()) Operator1<CompareOperationHints::Hint>( | 550 return new (zone()) Operator1<CompareOperationHints::Hint>( |
538 IrOpcode::kSpeculativeNumberLessThanOrEqual, Operator::kPure, | 551 IrOpcode::kSpeculativeNumberLessThanOrEqual, |
| 552 Operator::kFoldable | Operator::kNoThrow, |
539 "SpeculativeNumberLessThanOrEqual", 2, 1, 1, 1, 1, 1, hint); | 553 "SpeculativeNumberLessThanOrEqual", 2, 1, 1, 1, 1, 1, hint); |
540 } | 554 } |
541 | 555 |
542 #define ACCESS_OP_LIST(V) \ | 556 #define ACCESS_OP_LIST(V) \ |
543 V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \ | 557 V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \ |
544 V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \ | 558 V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \ |
545 V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \ | 559 V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \ |
546 V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0) | 560 V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0) |
547 | 561 |
548 | |
549 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \ | 562 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \ |
550 output_count) \ | 563 output_count) \ |
551 const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \ | 564 const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \ |
552 return new (zone()) \ | 565 return new (zone()) \ |
553 Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties, \ | 566 Operator1<Type>(IrOpcode::k##Name, \ |
| 567 Operator::kNoDeopt | Operator::kNoThrow | properties, \ |
554 #Name, value_input_count, 1, control_input_count, \ | 568 #Name, value_input_count, 1, control_input_count, \ |
555 output_count, 1, 0, access); \ | 569 output_count, 1, 0, access); \ |
556 } | 570 } |
557 ACCESS_OP_LIST(ACCESS) | 571 ACCESS_OP_LIST(ACCESS) |
558 #undef ACCESS | 572 #undef ACCESS |
559 | 573 |
560 } // namespace compiler | 574 } // namespace compiler |
561 } // namespace internal | 575 } // namespace internal |
562 } // namespace v8 | 576 } // namespace v8 |
OLD | NEW |