| 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 |