1 // Copyright 2013 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_CRANKSHAFT_ARM64_LITHIUM_ARM64_H_ 6 #define V8_CRANKSHAFT_ARM64_LITHIUM_ARM64_H_ 7 8 #include "src/crankshaft/hydrogen.h" 9 #include "src/crankshaft/lithium.h" 10 #include "src/crankshaft/lithium-allocator.h" 11 #include "src/safepoint-table.h" 12 #include "src/utils.h" 13 14 namespace v8 { 15 namespace internal { 16 17 // Forward declarations. 18 class LCodeGen; 19 20 #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \ 21 V(AccessArgumentsAt) \ 22 V(AddE) \ 23 V(AddI) \ 24 V(AddS) \ 25 V(Allocate) \ 26 V(ApplyArguments) \ 27 V(ArgumentsElements) \ 28 V(ArgumentsLength) \ 29 V(ArithmeticD) \ 30 V(ArithmeticT) \ 31 V(BitI) \ 32 V(BitS) \ 33 V(BoundsCheck) \ 34 V(Branch) \ 35 V(CallNewArray) \ 36 V(CallRuntime) \ 37 V(CallWithDescriptor) \ 38 V(CheckArrayBufferNotNeutered) \ 39 V(CheckInstanceType) \ 40 V(CheckMapValue) \ 41 V(CheckMaps) \ 42 V(CheckNonSmi) \ 43 V(CheckSmi) \ 44 V(CheckValue) \ 45 V(ClampDToUint8) \ 46 V(ClampIToUint8) \ 47 V(ClampTToUint8) \ 48 V(ClassOfTestAndBranch) \ 49 V(CmpHoleAndBranchD) \ 50 V(CmpHoleAndBranchT) \ 51 V(CmpMapAndBranch) \ 52 V(CmpObjectEqAndBranch) \ 53 V(CmpT) \ 54 V(CompareNumericAndBranch) \ 55 V(ConstantD) \ 56 V(ConstantE) \ 57 V(ConstantI) \ 58 V(ConstantS) \ 59 V(ConstantT) \ 60 V(Context) \ 61 V(DebugBreak) \ 62 V(DeclareGlobals) \ 63 V(Deoptimize) \ 64 V(DivByConstI) \ 65 V(DivByPowerOf2I) \ 66 V(DivI) \ 67 V(DoubleBits) \ 68 V(DoubleToIntOrSmi) \ 69 V(Drop) \ 70 V(Dummy) \ 71 V(DummyUse) \ 72 V(FastAllocate) \ 73 V(FlooringDivByConstI) \ 74 V(FlooringDivByPowerOf2I) \ 75 V(FlooringDivI) \ 76 V(ForInCacheArray) \ 77 V(ForInPrepareMap) \ 78 V(GetCachedArrayIndex) \ 79 V(Goto) \ 80 V(HasCachedArrayIndexAndBranch) \ 81 V(HasInPrototypeChainAndBranch) \ 82 V(HasInstanceTypeAndBranch) \ 83 V(InnerAllocatedObject) \ 84 V(InstructionGap) \ 85 V(Integer32ToDouble) \ 86 V(InvokeFunction) \ 87 V(IsSmiAndBranch) \ 88 V(IsStringAndBranch) \ 89 V(IsUndetectableAndBranch) \ 90 V(Label) \ 91 V(LazyBailout) \ 92 V(LoadContextSlot) \ 93 V(LoadFieldByIndex) \ 94 V(LoadFunctionPrototype) \ 95 V(LoadGlobalGeneric) \ 96 V(LoadKeyedExternal) \ 97 V(LoadKeyedFixed) \ 98 V(LoadKeyedFixedDouble) \ 99 V(LoadKeyedGeneric) \ 100 V(LoadNamedField) \ 101 V(LoadNamedGeneric) \ 102 V(LoadRoot) \ 103 V(MathAbs) \ 104 V(MathAbsTagged) \ 105 V(MathClz32) \ 106 V(MathCos) \ 107 V(MathSin) \ 108 V(MathExp) \ 109 V(MathFloorD) \ 110 V(MathFloorI) \ 111 V(MathFround) \ 112 V(MathLog) \ 113 V(MathMinMax) \ 114 V(MathPowHalf) \ 115 V(MathRoundD) \ 116 V(MathRoundI) \ 117 V(MathSqrt) \ 118 V(MaybeGrowElements) \ 119 V(ModByConstI) \ 120 V(ModByPowerOf2I) \ 121 V(ModI) \ 122 V(MulConstIS) \ 123 V(MulI) \ 124 V(MulS) \ 125 V(NumberTagD) \ 126 V(NumberTagU) \ 127 V(NumberUntagD) \ 128 V(OsrEntry) \ 129 V(Parameter) \ 130 V(Power) \ 131 V(Prologue) \ 132 V(PreparePushArguments) \ 133 V(PushArguments) \ 134 V(Return) \ 135 V(SeqStringGetChar) \ 136 V(SeqStringSetChar) \ 137 V(ShiftI) \ 138 V(ShiftS) \ 139 V(SmiTag) \ 140 V(SmiUntag) \ 141 V(StackCheck) \ 142 V(StoreCodeEntry) \ 143 V(StoreContextSlot) \ 144 V(StoreKeyedExternal) \ 145 V(StoreKeyedFixed) \ 146 V(StoreKeyedFixedDouble) \ 147 V(StoreKeyedGeneric) \ 148 V(StoreNamedField) \ 149 V(StoreNamedGeneric) \ 150 V(StringAdd) \ 151 V(StringCharCodeAt) \ 152 V(StringCharFromCode) \ 153 V(StringCompareAndBranch) \ 154 V(SubI) \ 155 V(SubS) \ 156 V(TaggedToI) \ 157 V(ThisFunction) \ 158 V(TransitionElementsKind) \ 159 V(TrapAllocationMemento) \ 160 V(TruncateDoubleToIntOrSmi) \ 161 V(Typeof) \ 162 V(TypeofIsAndBranch) \ 163 V(Uint32ToDouble) \ 164 V(UnknownOSRValue) \ 165 V(WrapReceiver) 166 167 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \ 168 Opcode opcode() const final { return LInstruction::k##type; } \ 169 void CompileToNative(LCodeGen* generator) final; \ 170 const char* Mnemonic() const final { return mnemonic; } \ 171 static L##type* cast(LInstruction* instr) { \ 172 DCHECK(instr->Is##type()); \ 173 return reinterpret_cast<L##type*>(instr); \ 174 } 175 176 177 #define DECLARE_HYDROGEN_ACCESSOR(type) \ 178 H##type* hydrogen() const { \ 179 return H##type::cast(this->hydrogen_value()); \ 180 } 181 182 183 class LInstruction : public ZoneObject { 184 public: 185 LInstruction() 186 : environment_(NULL), 187 hydrogen_value_(NULL), 188 bit_field_(IsCallBits::encode(false)) { } 189 190 virtual ~LInstruction() { } 191 192 virtual void CompileToNative(LCodeGen* generator) = 0; 193 virtual const char* Mnemonic() const = 0; 194 virtual void PrintTo(StringStream* stream); 195 virtual void PrintDataTo(StringStream* stream); 196 virtual void PrintOutputOperandTo(StringStream* stream); 197 198 enum Opcode { 199 // Declare a unique enum value for each instruction. 200 #define DECLARE_OPCODE(type) k##type, 201 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE) 202 kNumberOfInstructions 203 #undef DECLARE_OPCODE 204 }; 205 206 virtual Opcode opcode() const = 0; 207 208 // Declare non-virtual type testers for all leaf IR classes. 209 #define DECLARE_PREDICATE(type) \ 210 bool Is##type() const { return opcode() == k##type; } 211 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE) 212 #undef DECLARE_PREDICATE 213 214 // Declare virtual predicates for instructions that don't have 215 // an opcode. 216 virtual bool IsGap() const { return false; } 217 218 virtual bool IsControl() const { return false; } 219 220 // Try deleting this instruction if possible. 221 virtual bool TryDelete() { return false; } 222 223 void set_environment(LEnvironment* env) { environment_ = env; } 224 LEnvironment* environment() const { return environment_; } 225 bool HasEnvironment() const { return environment_ != NULL; } 226 227 void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); } 228 LPointerMap* pointer_map() const { return pointer_map_.get(); } 229 bool HasPointerMap() const { return pointer_map_.is_set(); } 230 231 void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; } 232 HValue* hydrogen_value() const { return hydrogen_value_; } 233 234 void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); } 235 bool IsCall() const { return IsCallBits::decode(bit_field_); } 236 237 void MarkAsSyntacticTailCall() { 238 bit_field_ = IsSyntacticTailCallBits::update(bit_field_, true); 239 } 240 bool IsSyntacticTailCall() const { 241 return IsSyntacticTailCallBits::decode(bit_field_); 242 } 243 244 // Interface to the register allocator and iterators. 245 bool ClobbersTemps() const { return IsCall(); } 246 bool ClobbersRegisters() const { return IsCall(); } 247 virtual bool ClobbersDoubleRegisters(Isolate* isolate) const { 248 return IsCall(); 249 } 250 bool IsMarkedAsCall() const { return IsCall(); } 251 252 virtual bool HasResult() const = 0; 253 virtual LOperand* result() const = 0; 254 255 virtual int InputCount() = 0; 256 virtual LOperand* InputAt(int i) = 0; 257 virtual int TempCount() = 0; 258 virtual LOperand* TempAt(int i) = 0; 259 260 LOperand* FirstInput() { return InputAt(0); } 261 LOperand* Output() { return HasResult() ? result() : NULL; } 262 263 virtual bool HasInterestingComment(LCodeGen* gen) const { return true; } 264 265 #ifdef DEBUG 266 void VerifyCall(); 267 #endif 268 269 private: 270 class IsCallBits: public BitField<bool, 0, 1> {}; 271 class IsSyntacticTailCallBits : public BitField<bool, IsCallBits::kNext, 1> { 272 }; 273 274 LEnvironment* environment_; 275 SetOncePointer<LPointerMap> pointer_map_; 276 HValue* hydrogen_value_; 277 int32_t bit_field_; 278 }; 279 280 281 // R = number of result operands (0 or 1). 282 template<int R> 283 class LTemplateResultInstruction : public LInstruction { 284 public: 285 // Allow 0 or 1 output operands. 286 STATIC_ASSERT(R == 0 || R == 1); 287 bool HasResult() const final { return (R != 0) && (result() != NULL); } 288 void set_result(LOperand* operand) { results_[0] = operand; } 289 LOperand* result() const override { return results_[0]; } 290 291 protected: 292 EmbeddedContainer<LOperand*, R> results_; 293 }; 294 295 296 // R = number of result operands (0 or 1). 297 // I = number of input operands. 298 // T = number of temporary operands. 299 template<int R, int I, int T> 300 class LTemplateInstruction : public LTemplateResultInstruction<R> { 301 protected: 302 EmbeddedContainer<LOperand*, I> inputs_; 303 EmbeddedContainer<LOperand*, T> temps_; 304 305 private: 306 // Iterator support. 307 int InputCount() final { return I; } 308 LOperand* InputAt(int i) final { return inputs_[i]; } 309 310 int TempCount() final { return T; } 311 LOperand* TempAt(int i) final { return temps_[i]; } 312 }; 313 314 315 class LUnknownOSRValue final : public LTemplateInstruction<1, 0, 0> { 316 public: 317 bool HasInterestingComment(LCodeGen* gen) const override { return false; } 318 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value") 319 }; 320 321 322 template<int I, int T> 323 class LControlInstruction : public LTemplateInstruction<0, I, T> { 324 public: 325 LControlInstruction() : false_label_(NULL), true_label_(NULL) { } 326 327 bool IsControl() const final { return true; } 328 329 int SuccessorCount() { return hydrogen()->SuccessorCount(); } 330 HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); } 331 332 int TrueDestination(LChunk* chunk) { 333 return chunk->LookupDestination(true_block_id()); 334 } 335 336 int FalseDestination(LChunk* chunk) { 337 return chunk->LookupDestination(false_block_id()); 338 } 339 340 Label* TrueLabel(LChunk* chunk) { 341 if (true_label_ == NULL) { 342 true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk)); 343 } 344 return true_label_; 345 } 346 347 Label* FalseLabel(LChunk* chunk) { 348 if (false_label_ == NULL) { 349 false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk)); 350 } 351 return false_label_; 352 } 353 354 protected: 355 int true_block_id() { return SuccessorAt(0)->block_id(); } 356 int false_block_id() { return SuccessorAt(1)->block_id(); } 357 358 private: 359 DECLARE_HYDROGEN_ACCESSOR(ControlInstruction); 360 361 Label* false_label_; 362 Label* true_label_; 363 }; 364 365 366 class LGap : public LTemplateInstruction<0, 0, 0> { 367 public: 368 explicit LGap(HBasicBlock* block) 369 : block_(block) { 370 parallel_moves_[BEFORE] = NULL; 371 parallel_moves_[START] = NULL; 372 parallel_moves_[END] = NULL; 373 parallel_moves_[AFTER] = NULL; 374 } 375 376 // Can't use the DECLARE-macro here because of sub-classes. 377 bool IsGap() const override { return true; } 378 void PrintDataTo(StringStream* stream) override; 379 static LGap* cast(LInstruction* instr) { 380 DCHECK(instr->IsGap()); 381 return reinterpret_cast<LGap*>(instr); 382 } 383 384 bool IsRedundant() const; 385 386 HBasicBlock* block() const { return block_; } 387 388 enum InnerPosition { 389 BEFORE, 390 START, 391 END, 392 AFTER, 393 FIRST_INNER_POSITION = BEFORE, 394 LAST_INNER_POSITION = AFTER 395 }; 396 397 LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) { 398 if (parallel_moves_[pos] == NULL) { 399 parallel_moves_[pos] = new(zone) LParallelMove(zone); 400 } 401 return parallel_moves_[pos]; 402 } 403 404 LParallelMove* GetParallelMove(InnerPosition pos) { 405 return parallel_moves_[pos]; 406 } 407 408 private: 409 LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1]; 410 HBasicBlock* block_; 411 }; 412 413 414 class LInstructionGap final : public LGap { 415 public: 416 explicit LInstructionGap(HBasicBlock* block) : LGap(block) { } 417 418 bool HasInterestingComment(LCodeGen* gen) const override { 419 return !IsRedundant(); 420 } 421 422 DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap") 423 }; 424 425 426 class LDrop final : public LTemplateInstruction<0, 0, 0> { 427 public: 428 explicit LDrop(int count) : count_(count) { } 429 430 int count() const { return count_; } 431 432 DECLARE_CONCRETE_INSTRUCTION(Drop, "drop") 433 434 private: 435 int count_; 436 }; 437 438 439 class LDummy final : public LTemplateInstruction<1, 0, 0> { 440 public: 441 LDummy() {} 442 DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy") 443 }; 444 445 446 class LDummyUse final : public LTemplateInstruction<1, 1, 0> { 447 public: 448 explicit LDummyUse(LOperand* value) { 449 inputs_[0] = value; 450 } 451 DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use") 452 }; 453 454 455 class LGoto final : public LTemplateInstruction<0, 0, 0> { 456 public: 457 explicit LGoto(HBasicBlock* block) : block_(block) { } 458 459 bool HasInterestingComment(LCodeGen* gen) const override; 460 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto") 461 void PrintDataTo(StringStream* stream) override; 462 bool IsControl() const override { return true; } 463 464 int block_id() const { return block_->block_id(); } 465 466 private: 467 HBasicBlock* block_; 468 }; 469 470 471 class LPrologue final : public LTemplateInstruction<0, 0, 0> { 472 public: 473 DECLARE_CONCRETE_INSTRUCTION(Prologue, "prologue") 474 }; 475 476 477 class LLazyBailout final : public LTemplateInstruction<0, 0, 0> { 478 public: 479 LLazyBailout() : gap_instructions_size_(0) { } 480 481 DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout") 482 483 void set_gap_instructions_size(int gap_instructions_size) { 484 gap_instructions_size_ = gap_instructions_size; 485 } 486 int gap_instructions_size() { return gap_instructions_size_; } 487 488 private: 489 int gap_instructions_size_; 490 }; 491 492 493 class LLabel final : public LGap { 494 public: 495 explicit LLabel(HBasicBlock* block) 496 : LGap(block), replacement_(NULL) { } 497 498 bool HasInterestingComment(LCodeGen* gen) const override { return false; } 499 DECLARE_CONCRETE_INSTRUCTION(Label, "label") 500 501 void PrintDataTo(StringStream* stream) override; 502 503 int block_id() const { return block()->block_id(); } 504 bool is_loop_header() const { return block()->IsLoopHeader(); } 505 bool is_osr_entry() const { return block()->is_osr_entry(); } 506 Label* label() { return &label_; } 507 LLabel* replacement() const { return replacement_; } 508 void set_replacement(LLabel* label) { replacement_ = label; } 509 bool HasReplacement() const { return replacement_ != NULL; } 510 511 private: 512 Label label_; 513 LLabel* replacement_; 514 }; 515 516 517 class LOsrEntry final : public LTemplateInstruction<0, 0, 0> { 518 public: 519 LOsrEntry() {} 520 521 bool HasInterestingComment(LCodeGen* gen) const override { return false; } 522 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry") 523 }; 524 525 526 class LAccessArgumentsAt final : public LTemplateInstruction<1, 3, 0> { 527 public: 528 LAccessArgumentsAt(LOperand* arguments, 529 LOperand* length, 530 LOperand* index) { 531 inputs_[0] = arguments; 532 inputs_[1] = length; 533 inputs_[2] = index; 534 } 535 536 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at") 537 538 LOperand* arguments() { return inputs_[0]; } 539 LOperand* length() { return inputs_[1]; } 540 LOperand* index() { return inputs_[2]; } 541 542 void PrintDataTo(StringStream* stream) override; 543 }; 544 545 546 class LAddE final : public LTemplateInstruction<1, 2, 0> { 547 public: 548 LAddE(LOperand* left, LOperand* right) { 549 inputs_[0] = left; 550 inputs_[1] = right; 551 } 552 553 LOperand* left() { return inputs_[0]; } 554 LOperand* right() { return inputs_[1]; } 555 556 DECLARE_CONCRETE_INSTRUCTION(AddE, "add-e") 557 DECLARE_HYDROGEN_ACCESSOR(Add) 558 }; 559 560 561 class LAddI final : public LTemplateInstruction<1, 2, 0> { 562 public: 563 LAddI(LOperand* left, LOperand* right) 564 : shift_(NO_SHIFT), shift_amount_(0) { 565 inputs_[0] = left; 566 inputs_[1] = right; 567 } 568 569 LAddI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount) 570 : shift_(shift), shift_amount_(shift_amount) { 571 inputs_[0] = left; 572 inputs_[1] = right; 573 } 574 575 LOperand* left() { return inputs_[0]; } 576 LOperand* right() { return inputs_[1]; } 577 578 Shift shift() const { return shift_; } 579 LOperand* shift_amount() const { return shift_amount_; } 580 581 DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i") 582 DECLARE_HYDROGEN_ACCESSOR(Add) 583 584 protected: 585 Shift shift_; 586 LOperand* shift_amount_; 587 }; 588 589 590 class LAddS final : public LTemplateInstruction<1, 2, 0> { 591 public: 592 LAddS(LOperand* left, LOperand* right) { 593 inputs_[0] = left; 594 inputs_[1] = right; 595 } 596 597 LOperand* left() { return inputs_[0]; } 598 LOperand* right() { return inputs_[1]; } 599 600 DECLARE_CONCRETE_INSTRUCTION(AddS, "add-s") 601 DECLARE_HYDROGEN_ACCESSOR(Add) 602 }; 603 604 605 class LAllocate final : public LTemplateInstruction<1, 2, 3> { 606 public: 607 LAllocate(LOperand* context, 608 LOperand* size, 609 LOperand* temp1, 610 LOperand* temp2, 611 LOperand* temp3) { 612 inputs_[0] = context; 613 inputs_[1] = size; 614 temps_[0] = temp1; 615 temps_[1] = temp2; 616 temps_[2] = temp3; 617 } 618 619 LOperand* context() { return inputs_[0]; } 620 LOperand* size() { return inputs_[1]; } 621 LOperand* temp1() { return temps_[0]; } 622 LOperand* temp2() { return temps_[1]; } 623 LOperand* temp3() { return temps_[2]; } 624 625 DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate") 626 DECLARE_HYDROGEN_ACCESSOR(Allocate) 627 }; 628 629 class LFastAllocate final : public LTemplateInstruction<1, 1, 2> { 630 public: 631 LFastAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) { 632 inputs_[0] = size; 633 temps_[0] = temp1; 634 temps_[1] = temp2; 635 } 636 637 LOperand* size() { return inputs_[0]; } 638 LOperand* temp1() { return temps_[0]; } 639 LOperand* temp2() { return temps_[1]; } 640 641 DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate") 642 DECLARE_HYDROGEN_ACCESSOR(Allocate) 643 }; 644 645 class LApplyArguments final : public LTemplateInstruction<1, 4, 0> { 646 public: 647 LApplyArguments(LOperand* function, 648 LOperand* receiver, 649 LOperand* length, 650 LOperand* elements) { 651 inputs_[0] = function; 652 inputs_[1] = receiver; 653 inputs_[2] = length; 654 inputs_[3] = elements; 655 } 656 657 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments") 658 DECLARE_HYDROGEN_ACCESSOR(ApplyArguments) 659 660 LOperand* function() { return inputs_[0]; } 661 LOperand* receiver() { return inputs_[1]; } 662 LOperand* length() { return inputs_[2]; } 663 LOperand* elements() { return inputs_[3]; } 664 }; 665 666 667 class LArgumentsElements final : public LTemplateInstruction<1, 0, 1> { 668 public: 669 explicit LArgumentsElements(LOperand* temp) { 670 temps_[0] = temp; 671 } 672 673 LOperand* temp() { return temps_[0]; } 674 675 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements") 676 DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements) 677 }; 678 679 680 class LArgumentsLength final : public LTemplateInstruction<1, 1, 0> { 681 public: 682 explicit LArgumentsLength(LOperand* elements) { 683 inputs_[0] = elements; 684 } 685 686 LOperand* elements() { return inputs_[0]; } 687 688 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length") 689 }; 690 691 692 class LArithmeticD final : public LTemplateInstruction<1, 2, 0> { 693 public: 694 LArithmeticD(Token::Value op, 695 LOperand* left, 696 LOperand* right) 697 : op_(op) { 698 inputs_[0] = left; 699 inputs_[1] = right; 700 } 701 702 Token::Value op() const { return op_; } 703 LOperand* left() { return inputs_[0]; } 704 LOperand* right() { return inputs_[1]; } 705 706 Opcode opcode() const override { return LInstruction::kArithmeticD; } 707 void CompileToNative(LCodeGen* generator) override; 708 const char* Mnemonic() const override; 709 710 private: 711 Token::Value op_; 712 }; 713 714 715 class LArithmeticT final : public LTemplateInstruction<1, 3, 0> { 716 public: 717 LArithmeticT(Token::Value op, 718 LOperand* context, 719 LOperand* left, 720 LOperand* right) 721 : op_(op) { 722 inputs_[0] = context; 723 inputs_[1] = left; 724 inputs_[2] = right; 725 } 726 727 LOperand* context() { return inputs_[0]; } 728 LOperand* left() { return inputs_[1]; } 729 LOperand* right() { return inputs_[2]; } 730 Token::Value op() const { return op_; } 731 732 Opcode opcode() const override { return LInstruction::kArithmeticT; } 733 void CompileToNative(LCodeGen* generator) override; 734 const char* Mnemonic() const override; 735 736 DECLARE_HYDROGEN_ACCESSOR(BinaryOperation) 737 738 private: 739 Token::Value op_; 740 }; 741 742 743 class LBoundsCheck final : public LTemplateInstruction<0, 2, 0> { 744 public: 745 explicit LBoundsCheck(LOperand* index, LOperand* length) { 746 inputs_[0] = index; 747 inputs_[1] = length; 748 } 749 750 LOperand* index() { return inputs_[0]; } 751 LOperand* length() { return inputs_[1]; } 752 753 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check") 754 DECLARE_HYDROGEN_ACCESSOR(BoundsCheck) 755 }; 756 757 758 class LBitI final : public LTemplateInstruction<1, 2, 0> { 759 public: 760 LBitI(LOperand* left, LOperand* right) 761 : shift_(NO_SHIFT), shift_amount_(0) { 762 inputs_[0] = left; 763 inputs_[1] = right; 764 } 765 766 LBitI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount) 767 : shift_(shift), shift_amount_(shift_amount) { 768 inputs_[0] = left; 769 inputs_[1] = right; 770 } 771 772 LOperand* left() { return inputs_[0]; } 773 LOperand* right() { return inputs_[1]; } 774 775 Shift shift() const { return shift_; } 776 LOperand* shift_amount() const { return shift_amount_; } 777 778 Token::Value op() const { return hydrogen()->op(); } 779 780 DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i") 781 DECLARE_HYDROGEN_ACCESSOR(Bitwise) 782 783 protected: 784 Shift shift_; 785 LOperand* shift_amount_; 786 }; 787 788 789 class LBitS final : public LTemplateInstruction<1, 2, 0> { 790 public: 791 LBitS(LOperand* left, LOperand* right) { 792 inputs_[0] = left; 793 inputs_[1] = right; 794 } 795 796 LOperand* left() { return inputs_[0]; } 797 LOperand* right() { return inputs_[1]; } 798 799 Token::Value op() const { return hydrogen()->op(); } 800 801 DECLARE_CONCRETE_INSTRUCTION(BitS, "bit-s") 802 DECLARE_HYDROGEN_ACCESSOR(Bitwise) 803 }; 804 805 806 class LBranch final : public LControlInstruction<1, 2> { 807 public: 808 explicit LBranch(LOperand* value, LOperand *temp1, LOperand *temp2) { 809 inputs_[0] = value; 810 temps_[0] = temp1; 811 temps_[1] = temp2; 812 } 813 814 LOperand* value() { return inputs_[0]; } 815 LOperand* temp1() { return temps_[0]; } 816 LOperand* temp2() { return temps_[1]; } 817 818 DECLARE_CONCRETE_INSTRUCTION(Branch, "branch") 819 DECLARE_HYDROGEN_ACCESSOR(Branch) 820 821 void PrintDataTo(StringStream* stream) override; 822 }; 823 824 825 class LCallNewArray final : public LTemplateInstruction<1, 2, 0> { 826 public: 827 LCallNewArray(LOperand* context, LOperand* constructor) { 828 inputs_[0] = context; 829 inputs_[1] = constructor; 830 } 831 832 LOperand* context() { return inputs_[0]; } 833 LOperand* constructor() { return inputs_[1]; } 834 835 DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array") 836 DECLARE_HYDROGEN_ACCESSOR(CallNewArray) 837 838 void PrintDataTo(StringStream* stream) override; 839 840 int arity() const { return hydrogen()->argument_count() - 1; } 841 }; 842 843 844 class LCallRuntime final : public LTemplateInstruction<1, 1, 0> { 845 public: 846 explicit LCallRuntime(LOperand* context) { 847 inputs_[0] = context; 848 } 849 850 LOperand* context() { return inputs_[0]; } 851 852 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime") 853 DECLARE_HYDROGEN_ACCESSOR(CallRuntime) 854 855 bool ClobbersDoubleRegisters(Isolate* isolate) const override { 856 return save_doubles() == kDontSaveFPRegs; 857 } 858 859 const Runtime::Function* function() const { return hydrogen()->function(); } 860 int arity() const { return hydrogen()->argument_count(); } 861 SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); } 862 }; 863 864 865 class LCheckArrayBufferNotNeutered final 866 : public LTemplateInstruction<0, 1, 0> { 867 public: 868 explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; } 869 870 LOperand* view() { return inputs_[0]; } 871 872 DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered, 873 "check-array-buffer-not-neutered") 874 DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered) 875 }; 876 877 878 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 1> { 879 public: 880 explicit LCheckInstanceType(LOperand* value, LOperand* temp) { 881 inputs_[0] = value; 882 temps_[0] = temp; 883 } 884 885 LOperand* value() { return inputs_[0]; } 886 LOperand* temp() { return temps_[0]; } 887 888 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type") 889 DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType) 890 }; 891 892 893 class LCheckMaps final : public LTemplateInstruction<0, 1, 1> { 894 public: 895 explicit LCheckMaps(LOperand* value = NULL, LOperand* temp = NULL) { 896 inputs_[0] = value; 897 temps_[0] = temp; 898 } 899 900 LOperand* value() { return inputs_[0]; } 901 LOperand* temp() { return temps_[0]; } 902 903 DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps") 904 DECLARE_HYDROGEN_ACCESSOR(CheckMaps) 905 }; 906 907 908 class LCheckNonSmi final : public LTemplateInstruction<0, 1, 0> { 909 public: 910 explicit LCheckNonSmi(LOperand* value) { 911 inputs_[0] = value; 912 } 913 914 LOperand* value() { return inputs_[0]; } 915 916 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi") 917 DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject) 918 }; 919 920 921 class LCheckSmi final : public LTemplateInstruction<1, 1, 0> { 922 public: 923 explicit LCheckSmi(LOperand* value) { 924 inputs_[0] = value; 925 } 926 927 LOperand* value() { return inputs_[0]; } 928 929 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi") 930 }; 931 932 933 class LCheckValue final : public LTemplateInstruction<0, 1, 0> { 934 public: 935 explicit LCheckValue(LOperand* value) { 936 inputs_[0] = value; 937 } 938 939 LOperand* value() { return inputs_[0]; } 940 941 DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value") 942 DECLARE_HYDROGEN_ACCESSOR(CheckValue) 943 }; 944 945 946 class LClampDToUint8 final : public LTemplateInstruction<1, 1, 0> { 947 public: 948 explicit LClampDToUint8(LOperand* unclamped) { 949 inputs_[0] = unclamped; 950 } 951 952 LOperand* unclamped() { return inputs_[0]; } 953 954 DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8") 955 }; 956 957 958 class LClampIToUint8 final : public LTemplateInstruction<1, 1, 0> { 959 public: 960 explicit LClampIToUint8(LOperand* unclamped) { 961 inputs_[0] = unclamped; 962 } 963 964 LOperand* unclamped() { return inputs_[0]; } 965 966 DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8") 967 }; 968 969 970 class LClampTToUint8 final : public LTemplateInstruction<1, 1, 1> { 971 public: 972 LClampTToUint8(LOperand* unclamped, LOperand* temp1) { 973 inputs_[0] = unclamped; 974 temps_[0] = temp1; 975 } 976 977 LOperand* unclamped() { return inputs_[0]; } 978 LOperand* temp1() { return temps_[0]; } 979 980 DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8") 981 }; 982 983 984 class LDoubleBits final : public LTemplateInstruction<1, 1, 0> { 985 public: 986 explicit LDoubleBits(LOperand* value) { 987 inputs_[0] = value; 988 } 989 990 LOperand* value() { return inputs_[0]; } 991 992 DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits") 993 DECLARE_HYDROGEN_ACCESSOR(DoubleBits) 994 }; 995 996 997 class LClassOfTestAndBranch final : public LControlInstruction<1, 2> { 998 public: 999 LClassOfTestAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) { 1000 inputs_[0] = value; 1001 temps_[0] = temp1; 1002 temps_[1] = temp2; 1003 } 1004 1005 LOperand* value() { return inputs_[0]; } 1006 LOperand* temp1() { return temps_[0]; } 1007 LOperand* temp2() { return temps_[1]; } 1008 1009 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch, 1010 "class-of-test-and-branch") 1011 DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch) 1012 1013 void PrintDataTo(StringStream* stream) override; 1014 }; 1015 1016 1017 class LCmpHoleAndBranchD final : public LControlInstruction<1, 1> { 1018 public: 1019 explicit LCmpHoleAndBranchD(LOperand* object, LOperand* temp) { 1020 inputs_[0] = object; 1021 temps_[0] = temp; 1022 } 1023 1024 LOperand* object() { return inputs_[0]; } 1025 LOperand* temp() { return temps_[0]; } 1026 1027 DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchD, "cmp-hole-and-branch-d") 1028 DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch) 1029 }; 1030 1031 1032 class LCmpHoleAndBranchT final : public LControlInstruction<1, 0> { 1033 public: 1034 explicit LCmpHoleAndBranchT(LOperand* object) { 1035 inputs_[0] = object; 1036 } 1037 1038 LOperand* object() { return inputs_[0]; } 1039 1040 DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchT, "cmp-hole-and-branch-t") 1041 DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch) 1042 }; 1043 1044 1045 class LCmpMapAndBranch final : public LControlInstruction<1, 1> { 1046 public: 1047 LCmpMapAndBranch(LOperand* value, LOperand* temp) { 1048 inputs_[0] = value; 1049 temps_[0] = temp; 1050 } 1051 1052 LOperand* value() { return inputs_[0]; } 1053 LOperand* temp() { return temps_[0]; } 1054 1055 DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch") 1056 DECLARE_HYDROGEN_ACCESSOR(CompareMap) 1057 1058 Handle<Map> map() const { return hydrogen()->map().handle(); } 1059 }; 1060 1061 1062 class LCmpObjectEqAndBranch final : public LControlInstruction<2, 0> { 1063 public: 1064 LCmpObjectEqAndBranch(LOperand* left, LOperand* right) { 1065 inputs_[0] = left; 1066 inputs_[1] = right; 1067 } 1068 1069 LOperand* left() { return inputs_[0]; } 1070 LOperand* right() { return inputs_[1]; } 1071 1072 DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch") 1073 DECLARE_HYDROGEN_ACCESSOR(CompareObjectEqAndBranch) 1074 }; 1075 1076 1077 class LCmpT final : public LTemplateInstruction<1, 3, 0> { 1078 public: 1079 LCmpT(LOperand* context, LOperand* left, LOperand* right) { 1080 inputs_[0] = context; 1081 inputs_[1] = left; 1082 inputs_[2] = right; 1083 } 1084 1085 LOperand* context() { return inputs_[0]; } 1086 LOperand* left() { return inputs_[1]; } 1087 LOperand* right() { return inputs_[2]; } 1088 1089 DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t") 1090 DECLARE_HYDROGEN_ACCESSOR(CompareGeneric) 1091 1092 Token::Value op() const { return hydrogen()->token(); } 1093 }; 1094 1095 1096 class LCompareNumericAndBranch final : public LControlInstruction<2, 0> { 1097 public: 1098 LCompareNumericAndBranch(LOperand* left, LOperand* right) { 1099 inputs_[0] = left; 1100 inputs_[1] = right; 1101 } 1102 1103 LOperand* left() { return inputs_[0]; } 1104 LOperand* right() { return inputs_[1]; } 1105 1106 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch, 1107 "compare-numeric-and-branch") 1108 DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch) 1109 1110 Token::Value op() const { return hydrogen()->token(); } 1111 bool is_double() const { 1112 return hydrogen()->representation().IsDouble(); 1113 } 1114 1115 void PrintDataTo(StringStream* stream) override; 1116 }; 1117 1118 1119 class LConstantD final : public LTemplateInstruction<1, 0, 0> { 1120 public: 1121 DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d") 1122 DECLARE_HYDROGEN_ACCESSOR(Constant) 1123 1124 double value() const { return hydrogen()->DoubleValue(); } 1125 }; 1126 1127 1128 class LConstantE final : public LTemplateInstruction<1, 0, 0> { 1129 public: 1130 DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e") 1131 DECLARE_HYDROGEN_ACCESSOR(Constant) 1132 1133 ExternalReference value() const { 1134 return hydrogen()->ExternalReferenceValue(); 1135 } 1136 }; 1137 1138 1139 class LConstantI final : public LTemplateInstruction<1, 0, 0> { 1140 public: 1141 DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i") 1142 DECLARE_HYDROGEN_ACCESSOR(Constant) 1143 1144 int32_t value() const { return hydrogen()->Integer32Value(); } 1145 }; 1146 1147 1148 class LConstantS final : public LTemplateInstruction<1, 0, 0> { 1149 public: 1150 DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s") 1151 DECLARE_HYDROGEN_ACCESSOR(Constant) 1152 1153 Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); } 1154 }; 1155 1156 1157 class LConstantT final : public LTemplateInstruction<1, 0, 0> { 1158 public: 1159 DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t") 1160 DECLARE_HYDROGEN_ACCESSOR(Constant) 1161 1162 Handle<Object> value(Isolate* isolate) const { 1163 return hydrogen()->handle(isolate); 1164 } 1165 }; 1166 1167 1168 class LContext final : public LTemplateInstruction<1, 0, 0> { 1169 public: 1170 DECLARE_CONCRETE_INSTRUCTION(Context, "context") 1171 DECLARE_HYDROGEN_ACCESSOR(Context) 1172 }; 1173 1174 1175 class LDebugBreak final : public LTemplateInstruction<0, 0, 0> { 1176 public: 1177 DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break") 1178 }; 1179 1180 1181 class LDeclareGlobals final : public LTemplateInstruction<0, 1, 0> { 1182 public: 1183 explicit LDeclareGlobals(LOperand* context) { 1184 inputs_[0] = context; 1185 } 1186 1187 LOperand* context() { return inputs_[0]; } 1188 1189 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals") 1190 DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals) 1191 }; 1192 1193 1194 class LDeoptimize final : public LTemplateInstruction<0, 0, 0> { 1195 public: 1196 bool IsControl() const override { return true; } 1197 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize") 1198 DECLARE_HYDROGEN_ACCESSOR(Deoptimize) 1199 }; 1200 1201 1202 class LDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> { 1203 public: 1204 LDivByPowerOf2I(LOperand* dividend, int32_t divisor) { 1205 inputs_[0] = dividend; 1206 divisor_ = divisor; 1207 } 1208 1209 LOperand* dividend() { return inputs_[0]; } 1210 int32_t divisor() const { return divisor_; } 1211 1212 DECLARE_CONCRETE_INSTRUCTION(DivByPowerOf2I, "div-by-power-of-2-i") 1213 DECLARE_HYDROGEN_ACCESSOR(Div) 1214 1215 private: 1216 int32_t divisor_; 1217 }; 1218 1219 1220 class LDivByConstI final : public LTemplateInstruction<1, 1, 1> { 1221 public: 1222 LDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) { 1223 inputs_[0] = dividend; 1224 divisor_ = divisor; 1225 temps_[0] = temp; 1226 } 1227 1228 LOperand* dividend() { return inputs_[0]; } 1229 int32_t divisor() const { return divisor_; } 1230 LOperand* temp() { return temps_[0]; } 1231 1232 DECLARE_CONCRETE_INSTRUCTION(DivByConstI, "div-by-const-i") 1233 DECLARE_HYDROGEN_ACCESSOR(Div) 1234 1235 private: 1236 int32_t divisor_; 1237 }; 1238 1239 1240 class LDivI final : public LTemplateInstruction<1, 2, 1> { 1241 public: 1242 LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) { 1243 inputs_[0] = dividend; 1244 inputs_[1] = divisor; 1245 temps_[0] = temp; 1246 } 1247 1248 LOperand* dividend() { return inputs_[0]; } 1249 LOperand* divisor() { return inputs_[1]; } 1250 LOperand* temp() { return temps_[0]; } 1251 1252 DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i") 1253 DECLARE_HYDROGEN_ACCESSOR(BinaryOperation) 1254 }; 1255 1256 1257 class LDoubleToIntOrSmi final : public LTemplateInstruction<1, 1, 0> { 1258 public: 1259 explicit LDoubleToIntOrSmi(LOperand* value) { 1260 inputs_[0] = value; 1261 } 1262 1263 LOperand* value() { return inputs_[0]; } 1264 1265 DECLARE_CONCRETE_INSTRUCTION(DoubleToIntOrSmi, "double-to-int-or-smi") 1266 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) 1267 1268 bool tag_result() { return hydrogen()->representation().IsSmi(); } 1269 }; 1270 1271 1272 class LForInCacheArray final : public LTemplateInstruction<1, 1, 0> { 1273 public: 1274 explicit LForInCacheArray(LOperand* map) { 1275 inputs_[0] = map; 1276 } 1277 1278 LOperand* map() { return inputs_[0]; } 1279 1280 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array") 1281 1282 int idx() { 1283 return HForInCacheArray::cast(this->hydrogen_value())->idx(); 1284 } 1285 }; 1286 1287 1288 class LForInPrepareMap final : public LTemplateInstruction<1, 2, 0> { 1289 public: 1290 LForInPrepareMap(LOperand* context, LOperand* object) { 1291 inputs_[0] = context; 1292 inputs_[1] = object; 1293 } 1294 1295 LOperand* context() { return inputs_[0]; } 1296 LOperand* object() { return inputs_[1]; } 1297 1298 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map") 1299 }; 1300 1301 1302 class LGetCachedArrayIndex final : public LTemplateInstruction<1, 1, 0> { 1303 public: 1304 explicit LGetCachedArrayIndex(LOperand* value) { 1305 inputs_[0] = value; 1306 } 1307 1308 LOperand* value() { return inputs_[0]; } 1309 1310 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index") 1311 DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex) 1312 }; 1313 1314 1315 class LHasCachedArrayIndexAndBranch final : public LControlInstruction<1, 1> { 1316 public: 1317 LHasCachedArrayIndexAndBranch(LOperand* value, LOperand* temp) { 1318 inputs_[0] = value; 1319 temps_[0] = temp; 1320 } 1321 1322 LOperand* value() { return inputs_[0]; } 1323 LOperand* temp() { return temps_[0]; } 1324 1325 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch, 1326 "has-cached-array-index-and-branch") 1327 DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndexAndBranch) 1328 1329 void PrintDataTo(StringStream* stream) override; 1330 }; 1331 1332 1333 class LHasInstanceTypeAndBranch final : public LControlInstruction<1, 1> { 1334 public: 1335 LHasInstanceTypeAndBranch(LOperand* value, LOperand* temp) { 1336 inputs_[0] = value; 1337 temps_[0] = temp; 1338 } 1339 1340 LOperand* value() { return inputs_[0]; } 1341 LOperand* temp() { return temps_[0]; } 1342 1343 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch, 1344 "has-instance-type-and-branch") 1345 DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch) 1346 1347 void PrintDataTo(StringStream* stream) override; 1348 }; 1349 1350 1351 class LInnerAllocatedObject final : public LTemplateInstruction<1, 2, 0> { 1352 public: 1353 LInnerAllocatedObject(LOperand* base_object, LOperand* offset) { 1354 inputs_[0] = base_object; 1355 inputs_[1] = offset; 1356 } 1357 1358 LOperand* base_object() const { return inputs_[0]; } 1359 LOperand* offset() const { return inputs_[1]; } 1360 1361 void PrintDataTo(StringStream* stream) override; 1362 1363 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object") 1364 }; 1365 1366 1367 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 2> { 1368 public: 1369 LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype, 1370 LOperand* scratch1, LOperand* scratch2) { 1371 inputs_[0] = object; 1372 inputs_[1] = prototype; 1373 temps_[0] = scratch1; 1374 temps_[1] = scratch2; 1375 } 1376 1377 LOperand* object() const { return inputs_[0]; } 1378 LOperand* prototype() const { return inputs_[1]; } 1379 LOperand* scratch1() const { return temps_[0]; } 1380 LOperand* scratch2() const { return temps_[1]; } 1381 1382 DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch, 1383 "has-in-prototype-chain-and-branch") 1384 DECLARE_HYDROGEN_ACCESSOR(HasInPrototypeChainAndBranch) 1385 }; 1386 1387 1388 class LInteger32ToDouble final : public LTemplateInstruction<1, 1, 0> { 1389 public: 1390 explicit LInteger32ToDouble(LOperand* value) { 1391 inputs_[0] = value; 1392 } 1393 1394 LOperand* value() { return inputs_[0]; } 1395 1396 DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double") 1397 }; 1398 1399 1400 class LCallWithDescriptor final : public LTemplateResultInstruction<1> { 1401 public: 1402 LCallWithDescriptor(CallInterfaceDescriptor descriptor, 1403 const ZoneList<LOperand*>& operands, Zone* zone) 1404 : descriptor_(descriptor), 1405 inputs_(descriptor.GetRegisterParameterCount() + 1406 kImplicitRegisterParameterCount, 1407 zone) { 1408 DCHECK(descriptor.GetRegisterParameterCount() + 1409 kImplicitRegisterParameterCount == 1410 operands.length()); 1411 inputs_.AddAll(operands, zone); 1412 } 1413 1414 LOperand* target() const { return inputs_[0]; } 1415 1416 CallInterfaceDescriptor descriptor() { return descriptor_; } 1417 1418 DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor) 1419 1420 // The target and context are passed as implicit parameters that are not 1421 // explicitly listed in the descriptor. 1422 static const int kImplicitRegisterParameterCount = 2; 1423 1424 private: 1425 DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor") 1426 1427 void PrintDataTo(StringStream* stream) override; 1428 1429 int arity() const { return hydrogen()->argument_count() - 1; } 1430 1431 CallInterfaceDescriptor descriptor_; 1432 ZoneList<LOperand*> inputs_; 1433 1434 // Iterator support. 1435 int InputCount() final { return inputs_.length(); } 1436 LOperand* InputAt(int i) final { return inputs_[i]; } 1437 1438 int TempCount() final { return 0; } 1439 LOperand* TempAt(int i) final { return NULL; } 1440 }; 1441 1442 1443 class LInvokeFunction final : public LTemplateInstruction<1, 2, 0> { 1444 public: 1445 LInvokeFunction(LOperand* context, LOperand* function) { 1446 inputs_[0] = context; 1447 inputs_[1] = function; 1448 } 1449 1450 LOperand* context() { return inputs_[0]; } 1451 LOperand* function() { return inputs_[1]; } 1452 1453 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function") 1454 DECLARE_HYDROGEN_ACCESSOR(InvokeFunction) 1455 1456 void PrintDataTo(StringStream* stream) override; 1457 1458 int arity() const { return hydrogen()->argument_count() - 1; } 1459 }; 1460 1461 1462 class LIsStringAndBranch final : public LControlInstruction<1, 1> { 1463 public: 1464 LIsStringAndBranch(LOperand* value, LOperand* temp) { 1465 inputs_[0] = value; 1466 temps_[0] = temp; 1467 } 1468 1469 LOperand* value() { return inputs_[0]; } 1470 LOperand* temp() { return temps_[0]; } 1471 1472 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch") 1473 DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch) 1474 1475 void PrintDataTo(StringStream* stream) override; 1476 }; 1477 1478 1479 class LIsSmiAndBranch final : public LControlInstruction<1, 0> { 1480 public: 1481 explicit LIsSmiAndBranch(LOperand* value) { 1482 inputs_[0] = value; 1483 } 1484 1485 LOperand* value() { return inputs_[0]; } 1486 1487 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch") 1488 DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch) 1489 1490 void PrintDataTo(StringStream* stream) override; 1491 }; 1492 1493 1494 class LIsUndetectableAndBranch final : public LControlInstruction<1, 1> { 1495 public: 1496 explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) { 1497 inputs_[0] = value; 1498 temps_[0] = temp; 1499 } 1500 1501 LOperand* value() { return inputs_[0]; } 1502 LOperand* temp() { return temps_[0]; } 1503 1504 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch, 1505 "is-undetectable-and-branch") 1506 DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch) 1507 1508 void PrintDataTo(StringStream* stream) override; 1509 }; 1510 1511 1512 class LLoadContextSlot final : public LTemplateInstruction<1, 1, 0> { 1513 public: 1514 explicit LLoadContextSlot(LOperand* context) { 1515 inputs_[0] = context; 1516 } 1517 1518 LOperand* context() { return inputs_[0]; } 1519 1520 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot") 1521 DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot) 1522 1523 int slot_index() const { return hydrogen()->slot_index(); } 1524 1525 void PrintDataTo(StringStream* stream) override; 1526 }; 1527 1528 1529 class LLoadNamedField final : public LTemplateInstruction<1, 1, 0> { 1530 public: 1531 explicit LLoadNamedField(LOperand* object) { 1532 inputs_[0] = object; 1533 } 1534 1535 LOperand* object() { return inputs_[0]; } 1536 1537 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field") 1538 DECLARE_HYDROGEN_ACCESSOR(LoadNamedField) 1539 }; 1540 1541 1542 class LLoadFunctionPrototype final : public LTemplateInstruction<1, 1, 1> { 1543 public: 1544 LLoadFunctionPrototype(LOperand* function, LOperand* temp) { 1545 inputs_[0] = function; 1546 temps_[0] = temp; 1547 } 1548 1549 LOperand* function() { return inputs_[0]; } 1550 LOperand* temp() { return temps_[0]; } 1551 1552 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype") 1553 DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype) 1554 }; 1555 1556 class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> { 1557 public: 1558 LLoadGlobalGeneric(LOperand* context, LOperand* vector) { 1559 inputs_[0] = context; 1560 temps_[0] = vector; 1561 } 1562 1563 LOperand* context() { return inputs_[0]; } 1564 LOperand* temp_vector() { return temps_[0]; } 1565 1566 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic") 1567 DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric) 1568 1569 Handle<Object> name() const { return hydrogen()->name(); } 1570 TypeofMode typeof_mode() const { return hydrogen()->typeof_mode(); } 1571 }; 1572 1573 1574 template <int T> 1575 class LLoadKeyed : public LTemplateInstruction<1, 3, T> { 1576 public: 1577 LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) { 1578 this->inputs_[0] = elements; 1579 this->inputs_[1] = key; 1580 this->inputs_[2] = backing_store_owner; 1581 } 1582 1583 LOperand* elements() { return this->inputs_[0]; } 1584 LOperand* key() { return this->inputs_[1]; } 1585 LOperand* backing_store_owner() { return this->inputs_[2]; } 1586 ElementsKind elements_kind() const { 1587 return this->hydrogen()->elements_kind(); 1588 } 1589 bool is_external() const { 1590 return this->hydrogen()->is_external(); 1591 } 1592 bool is_fixed_typed_array() const { 1593 return hydrogen()->is_fixed_typed_array(); 1594 } 1595 bool is_typed_elements() const { 1596 return is_external() || is_fixed_typed_array(); 1597 } 1598 uint32_t base_offset() const { 1599 return this->hydrogen()->base_offset(); 1600 } 1601 void PrintDataTo(StringStream* stream) override { 1602 this->elements()->PrintTo(stream); 1603 stream->Add("["); 1604 this->key()->PrintTo(stream); 1605 if (this->base_offset() != 0) { 1606 stream->Add(" + %d]", this->base_offset()); 1607 } else { 1608 stream->Add("]"); 1609 } 1610 } 1611 1612 DECLARE_HYDROGEN_ACCESSOR(LoadKeyed) 1613 }; 1614 1615 1616 class LLoadKeyedExternal: public LLoadKeyed<1> { 1617 public: 1618 LLoadKeyedExternal(LOperand* elements, LOperand* key, 1619 LOperand* backing_store_owner, LOperand* temp) 1620 : LLoadKeyed<1>(elements, key, backing_store_owner) { 1621 temps_[0] = temp; 1622 } 1623 1624 LOperand* temp() { return temps_[0]; } 1625 1626 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedExternal, "load-keyed-external"); 1627 }; 1628 1629 1630 class LLoadKeyedFixed: public LLoadKeyed<1> { 1631 public: 1632 LLoadKeyedFixed(LOperand* elements, LOperand* key, LOperand* temp) 1633 : LLoadKeyed<1>(elements, key, nullptr) { 1634 temps_[0] = temp; 1635 } 1636 1637 LOperand* temp() { return temps_[0]; } 1638 1639 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixed, "load-keyed-fixed"); 1640 }; 1641 1642 1643 class LLoadKeyedFixedDouble: public LLoadKeyed<1> { 1644 public: 1645 LLoadKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* temp) 1646 : LLoadKeyed<1>(elements, key, nullptr) { 1647 temps_[0] = temp; 1648 } 1649 1650 LOperand* temp() { return temps_[0]; } 1651 1652 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixedDouble, "load-keyed-fixed-double"); 1653 }; 1654 1655 1656 class LLoadKeyedGeneric final : public LTemplateInstruction<1, 3, 1> { 1657 public: 1658 LLoadKeyedGeneric(LOperand* context, LOperand* object, LOperand* key, 1659 LOperand* vector) { 1660 inputs_[0] = context; 1661 inputs_[1] = object; 1662 inputs_[2] = key; 1663 temps_[0] = vector; 1664 } 1665 1666 LOperand* context() { return inputs_[0]; } 1667 LOperand* object() { return inputs_[1]; } 1668 LOperand* key() { return inputs_[2]; } 1669 LOperand* temp_vector() { return temps_[0]; } 1670 1671 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic") 1672 DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric) 1673 }; 1674 1675 1676 class LLoadNamedGeneric final : public LTemplateInstruction<1, 2, 1> { 1677 public: 1678 LLoadNamedGeneric(LOperand* context, LOperand* object, LOperand* vector) { 1679 inputs_[0] = context; 1680 inputs_[1] = object; 1681 temps_[0] = vector; 1682 } 1683 1684 LOperand* context() { return inputs_[0]; } 1685 LOperand* object() { return inputs_[1]; } 1686 LOperand* temp_vector() { return temps_[0]; } 1687 1688 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic") 1689 DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric) 1690 1691 Handle<Object> name() const { return hydrogen()->name(); } 1692 }; 1693 1694 1695 class LLoadRoot final : public LTemplateInstruction<1, 0, 0> { 1696 public: 1697 DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root") 1698 DECLARE_HYDROGEN_ACCESSOR(LoadRoot) 1699 1700 Heap::RootListIndex index() const { return hydrogen()->index(); } 1701 }; 1702 1703 1704 template<int T> 1705 class LUnaryMathOperation : public LTemplateInstruction<1, 1, T> { 1706 public: 1707 explicit LUnaryMathOperation(LOperand* value) { 1708 this->inputs_[0] = value; 1709 } 1710 1711 LOperand* value() { return this->inputs_[0]; } 1712 BuiltinFunctionId op() const { return this->hydrogen()->op(); } 1713 1714 void PrintDataTo(StringStream* stream) override; 1715 1716 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation) 1717 }; 1718 1719 1720 class LMathAbs final : public LUnaryMathOperation<0> { 1721 public: 1722 explicit LMathAbs(LOperand* value) : LUnaryMathOperation<0>(value) {} 1723 1724 DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs") 1725 }; 1726 1727 1728 class LMathAbsTagged: public LTemplateInstruction<1, 2, 3> { 1729 public: 1730 LMathAbsTagged(LOperand* context, LOperand* value, 1731 LOperand* temp1, LOperand* temp2, LOperand* temp3) { 1732 inputs_[0] = context; 1733 inputs_[1] = value; 1734 temps_[0] = temp1; 1735 temps_[1] = temp2; 1736 temps_[2] = temp3; 1737 } 1738 1739 LOperand* context() { return inputs_[0]; } 1740 LOperand* value() { return inputs_[1]; } 1741 LOperand* temp1() { return temps_[0]; } 1742 LOperand* temp2() { return temps_[1]; } 1743 LOperand* temp3() { return temps_[2]; } 1744 1745 DECLARE_CONCRETE_INSTRUCTION(MathAbsTagged, "math-abs-tagged") 1746 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation) 1747 }; 1748 1749 class LMathCos final : public LUnaryMathOperation<0> { 1750 public: 1751 explicit LMathCos(LOperand* value) : LUnaryMathOperation<0>(value) {} 1752 1753 DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos") 1754 }; 1755 1756 class LMathSin final : public LUnaryMathOperation<0> { 1757 public: 1758 explicit LMathSin(LOperand* value) : LUnaryMathOperation<0>(value) {} 1759 1760 DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin") 1761 }; 1762 1763 class LMathExp final : public LUnaryMathOperation<0> { 1764 public: 1765 explicit LMathExp(LOperand* value) : LUnaryMathOperation<0>(value) {} 1766 1767 DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp") 1768 }; 1769 1770 1771 // Math.floor with a double result. 1772 class LMathFloorD final : public LUnaryMathOperation<0> { 1773 public: 1774 explicit LMathFloorD(LOperand* value) : LUnaryMathOperation<0>(value) { } 1775 DECLARE_CONCRETE_INSTRUCTION(MathFloorD, "math-floor-d") 1776 }; 1777 1778 1779 // Math.floor with an integer result. 1780 class LMathFloorI final : public LUnaryMathOperation<0> { 1781 public: 1782 explicit LMathFloorI(LOperand* value) : LUnaryMathOperation<0>(value) { } 1783 DECLARE_CONCRETE_INSTRUCTION(MathFloorI, "math-floor-i") 1784 }; 1785 1786 1787 class LFlooringDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> { 1788 public: 1789 LFlooringDivByPowerOf2I(LOperand* dividend, int32_t divisor) { 1790 inputs_[0] = dividend; 1791 divisor_ = divisor; 1792 } 1793 1794 LOperand* dividend() { return inputs_[0]; } 1795 int32_t divisor() const { return divisor_; } 1796 1797 DECLARE_CONCRETE_INSTRUCTION(FlooringDivByPowerOf2I, 1798 "flooring-div-by-power-of-2-i") 1799 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv) 1800 1801 private: 1802 int32_t divisor_; 1803 }; 1804 1805 1806 class LFlooringDivByConstI final : public LTemplateInstruction<1, 1, 2> { 1807 public: 1808 LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) { 1809 inputs_[0] = dividend; 1810 divisor_ = divisor; 1811 temps_[0] = temp; 1812 } 1813 1814 LOperand* dividend() { return inputs_[0]; } 1815 int32_t divisor() const { return divisor_; } 1816 LOperand* temp() { return temps_[0]; } 1817 1818 DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i") 1819 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv) 1820 1821 private: 1822 int32_t divisor_; 1823 }; 1824 1825 1826 class LFlooringDivI final : public LTemplateInstruction<1, 2, 1> { 1827 public: 1828 LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) { 1829 inputs_[0] = dividend; 1830 inputs_[1] = divisor; 1831 temps_[0] = temp; 1832 } 1833 1834 LOperand* dividend() { return inputs_[0]; } 1835 LOperand* divisor() { return inputs_[1]; } 1836 LOperand* temp() { return temps_[0]; } 1837 1838 DECLARE_CONCRETE_INSTRUCTION(FlooringDivI, "flooring-div-i") 1839 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv) 1840 }; 1841 1842 1843 class LMathLog final : public LUnaryMathOperation<0> { 1844 public: 1845 explicit LMathLog(LOperand* value) : LUnaryMathOperation<0>(value) { } 1846 DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log") 1847 }; 1848 1849 1850 class LMathClz32 final : public LUnaryMathOperation<0> { 1851 public: 1852 explicit LMathClz32(LOperand* value) : LUnaryMathOperation<0>(value) { } 1853 DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32") 1854 }; 1855 1856 1857 class LMathMinMax final : public LTemplateInstruction<1, 2, 0> { 1858 public: 1859 LMathMinMax(LOperand* left, LOperand* right) { 1860 inputs_[0] = left; 1861 inputs_[1] = right; 1862 } 1863 1864 LOperand* left() { return inputs_[0]; } 1865 LOperand* right() { return inputs_[1]; } 1866 1867 DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max") 1868 DECLARE_HYDROGEN_ACCESSOR(MathMinMax) 1869 }; 1870 1871 1872 class LMathPowHalf final : public LUnaryMathOperation<0> { 1873 public: 1874 explicit LMathPowHalf(LOperand* value) : LUnaryMathOperation<0>(value) { } 1875 DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half") 1876 }; 1877 1878 1879 // Math.round with an integer result. 1880 class LMathRoundD final : public LUnaryMathOperation<0> { 1881 public: 1882 explicit LMathRoundD(LOperand* value) 1883 : LUnaryMathOperation<0>(value) { 1884 } 1885 1886 DECLARE_CONCRETE_INSTRUCTION(MathRoundD, "math-round-d") 1887 }; 1888 1889 1890 // Math.round with an integer result. 1891 class LMathRoundI final : public LUnaryMathOperation<1> { 1892 public: 1893 LMathRoundI(LOperand* value, LOperand* temp1) 1894 : LUnaryMathOperation<1>(value) { 1895 temps_[0] = temp1; 1896 } 1897 1898 LOperand* temp1() { return temps_[0]; } 1899 1900 DECLARE_CONCRETE_INSTRUCTION(MathRoundI, "math-round-i") 1901 }; 1902 1903 1904 class LMathFround final : public LUnaryMathOperation<0> { 1905 public: 1906 explicit LMathFround(LOperand* value) : LUnaryMathOperation<0>(value) {} 1907 1908 DECLARE_CONCRETE_INSTRUCTION(MathFround, "math-fround") 1909 }; 1910 1911 1912 class LMathSqrt final : public LUnaryMathOperation<0> { 1913 public: 1914 explicit LMathSqrt(LOperand* value) : LUnaryMathOperation<0>(value) { } 1915 DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt") 1916 }; 1917 1918 1919 class LModByPowerOf2I final : public LTemplateInstruction<1, 1, 0> { 1920 public: 1921 LModByPowerOf2I(LOperand* dividend, int32_t divisor) { 1922 inputs_[0] = dividend; 1923 divisor_ = divisor; 1924 } 1925 1926 LOperand* dividend() { return inputs_[0]; } 1927 int32_t divisor() const { return divisor_; } 1928 1929 DECLARE_CONCRETE_INSTRUCTION(ModByPowerOf2I, "mod-by-power-of-2-i") 1930 DECLARE_HYDROGEN_ACCESSOR(Mod) 1931 1932 private: 1933 int32_t divisor_; 1934 }; 1935 1936 1937 class LModByConstI final : public LTemplateInstruction<1, 1, 1> { 1938 public: 1939 LModByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) { 1940 inputs_[0] = dividend; 1941 divisor_ = divisor; 1942 temps_[0] = temp; 1943 } 1944 1945 LOperand* dividend() { return inputs_[0]; } 1946 int32_t divisor() const { return divisor_; } 1947 LOperand* temp() { return temps_[0]; } 1948 1949 DECLARE_CONCRETE_INSTRUCTION(ModByConstI, "mod-by-const-i") 1950 DECLARE_HYDROGEN_ACCESSOR(Mod) 1951 1952 private: 1953 int32_t divisor_; 1954 }; 1955 1956 1957 class LModI final : public LTemplateInstruction<1, 2, 0> { 1958 public: 1959 LModI(LOperand* left, LOperand* right) { 1960 inputs_[0] = left; 1961 inputs_[1] = right; 1962 } 1963 1964 LOperand* left() { return inputs_[0]; } 1965 LOperand* right() { return inputs_[1]; } 1966 1967 DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i") 1968 DECLARE_HYDROGEN_ACCESSOR(Mod) 1969 }; 1970 1971 1972 class LMulConstIS final : public LTemplateInstruction<1, 2, 0> { 1973 public: 1974 LMulConstIS(LOperand* left, LConstantOperand* right) { 1975 inputs_[0] = left; 1976 inputs_[1] = right; 1977 } 1978 1979 LOperand* left() { return inputs_[0]; } 1980 LConstantOperand* right() { return LConstantOperand::cast(inputs_[1]); } 1981 1982 DECLARE_CONCRETE_INSTRUCTION(MulConstIS, "mul-const-i-s") 1983 DECLARE_HYDROGEN_ACCESSOR(Mul) 1984 }; 1985 1986 1987 class LMulI final : public LTemplateInstruction<1, 2, 0> { 1988 public: 1989 LMulI(LOperand* left, LOperand* right) { 1990 inputs_[0] = left; 1991 inputs_[1] = right; 1992 } 1993 1994 LOperand* left() { return inputs_[0]; } 1995 LOperand* right() { return inputs_[1]; } 1996 1997 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i") 1998 DECLARE_HYDROGEN_ACCESSOR(Mul) 1999 }; 2000 2001 2002 class LMulS final : public LTemplateInstruction<1, 2, 0> { 2003 public: 2004 LMulS(LOperand* left, LOperand* right) { 2005 inputs_[0] = left; 2006 inputs_[1] = right; 2007 } 2008 2009 LOperand* left() { return inputs_[0]; } 2010 LOperand* right() { return inputs_[1]; } 2011 2012 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-s") 2013 DECLARE_HYDROGEN_ACCESSOR(Mul) 2014 }; 2015 2016 2017 class LNumberTagD final : public LTemplateInstruction<1, 1, 2> { 2018 public: 2019 LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2) { 2020 inputs_[0] = value; 2021 temps_[0] = temp1; 2022 temps_[1] = temp2; 2023 } 2024 2025 LOperand* value() { return inputs_[0]; } 2026 LOperand* temp1() { return temps_[0]; } 2027 LOperand* temp2() { return temps_[1]; } 2028 2029 DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d") 2030 DECLARE_HYDROGEN_ACCESSOR(Change) 2031 }; 2032 2033 2034 class LNumberTagU final : public LTemplateInstruction<1, 1, 2> { 2035 public: 2036 explicit LNumberTagU(LOperand* value, 2037 LOperand* temp1, 2038 LOperand* temp2) { 2039 inputs_[0] = value; 2040 temps_[0] = temp1; 2041 temps_[1] = temp2; 2042 } 2043 2044 LOperand* value() { return inputs_[0]; } 2045 LOperand* temp1() { return temps_[0]; } 2046 LOperand* temp2() { return temps_[1]; } 2047 2048 DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u") 2049 }; 2050 2051 2052 class LNumberUntagD final : public LTemplateInstruction<1, 1, 1> { 2053 public: 2054 LNumberUntagD(LOperand* value, LOperand* temp) { 2055 inputs_[0] = value; 2056 temps_[0] = temp; 2057 } 2058 2059 LOperand* value() { return inputs_[0]; } 2060 2061 LOperand* temp() { return temps_[0]; } 2062 2063 DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag") 2064 DECLARE_HYDROGEN_ACCESSOR(Change) 2065 }; 2066 2067 2068 class LParameter final : public LTemplateInstruction<1, 0, 0> { 2069 public: 2070 bool HasInterestingComment(LCodeGen* gen) const override { return false; } 2071 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter") 2072 }; 2073 2074 2075 class LPower final : public LTemplateInstruction<1, 2, 0> { 2076 public: 2077 LPower(LOperand* left, LOperand* right) { 2078 inputs_[0] = left; 2079 inputs_[1] = right; 2080 } 2081 2082 LOperand* left() { return inputs_[0]; } 2083 LOperand* right() { return inputs_[1]; } 2084 2085 DECLARE_CONCRETE_INSTRUCTION(Power, "power") 2086 DECLARE_HYDROGEN_ACCESSOR(Power) 2087 }; 2088 2089 2090 class LPreparePushArguments final : public LTemplateInstruction<0, 0, 0> { 2091 public: 2092 explicit LPreparePushArguments(int argc) : argc_(argc) {} 2093 2094 inline int argc() const { return argc_; } 2095 2096 DECLARE_CONCRETE_INSTRUCTION(PreparePushArguments, "prepare-push-arguments") 2097 2098 protected: 2099 int argc_; 2100 }; 2101 2102 2103 class LPushArguments final : public LTemplateResultInstruction<0> { 2104 public: 2105 explicit LPushArguments(Zone* zone, 2106 int capacity = kRecommendedMaxPushedArgs) 2107 : zone_(zone), inputs_(capacity, zone) {} 2108 2109 LOperand* argument(int i) { return inputs_[i]; } 2110 int ArgumentCount() const { return inputs_.length(); } 2111 2112 void AddArgument(LOperand* arg) { inputs_.Add(arg, zone_); } 2113 2114 DECLARE_CONCRETE_INSTRUCTION(PushArguments, "push-arguments") 2115 2116 // It is better to limit the number of arguments pushed simultaneously to 2117 // avoid pressure on the register allocator. 2118 static const int kRecommendedMaxPushedArgs = 4; 2119 bool ShouldSplitPush() const { 2120 return inputs_.length() >= kRecommendedMaxPushedArgs; 2121 } 2122 2123 protected: 2124 Zone* zone_; 2125 ZoneList<LOperand*> inputs_; 2126 2127 private: 2128 // Iterator support. 2129 int InputCount() final { return inputs_.length(); } 2130 LOperand* InputAt(int i) final { return inputs_[i]; } 2131 2132 int TempCount() final { return 0; } 2133 LOperand* TempAt(int i) final { return NULL; } 2134 }; 2135 2136 2137 class LReturn final : public LTemplateInstruction<0, 3, 0> { 2138 public: 2139 LReturn(LOperand* value, LOperand* context, LOperand* parameter_count) { 2140 inputs_[0] = value; 2141 inputs_[1] = context; 2142 inputs_[2] = parameter_count; 2143 } 2144 2145 LOperand* value() { return inputs_[0]; } 2146 LOperand* parameter_count() { return inputs_[2]; } 2147 2148 bool has_constant_parameter_count() { 2149 return parameter_count()->IsConstantOperand(); 2150 } 2151 LConstantOperand* constant_parameter_count() { 2152 DCHECK(has_constant_parameter_count()); 2153 return LConstantOperand::cast(parameter_count()); 2154 } 2155 2156 DECLARE_CONCRETE_INSTRUCTION(Return, "return") 2157 }; 2158 2159 2160 class LSeqStringGetChar final : public LTemplateInstruction<1, 2, 1> { 2161 public: 2162 LSeqStringGetChar(LOperand* string, 2163 LOperand* index, 2164 LOperand* temp) { 2165 inputs_[0] = string; 2166 inputs_[1] = index; 2167 temps_[0] = temp; 2168 } 2169 2170 LOperand* string() { return inputs_[0]; } 2171 LOperand* index() { return inputs_[1]; } 2172 LOperand* temp() { return temps_[0]; } 2173 2174 DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char") 2175 DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar) 2176 }; 2177 2178 2179 class LSeqStringSetChar final : public LTemplateInstruction<1, 4, 1> { 2180 public: 2181 LSeqStringSetChar(LOperand* context, 2182 LOperand* string, 2183 LOperand* index, 2184 LOperand* value, 2185 LOperand* temp) { 2186 inputs_[0] = context; 2187 inputs_[1] = string; 2188 inputs_[2] = index; 2189 inputs_[3] = value; 2190 temps_[0] = temp; 2191 } 2192 2193 LOperand* context() { return inputs_[0]; } 2194 LOperand* string() { return inputs_[1]; } 2195 LOperand* index() { return inputs_[2]; } 2196 LOperand* value() { return inputs_[3]; } 2197 LOperand* temp() { return temps_[0]; } 2198 2199 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char") 2200 DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar) 2201 }; 2202 2203 2204 class LSmiTag final : public LTemplateInstruction<1, 1, 0> { 2205 public: 2206 explicit LSmiTag(LOperand* value) { 2207 inputs_[0] = value; 2208 } 2209 2210 LOperand* value() { return inputs_[0]; } 2211 2212 DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag") 2213 DECLARE_HYDROGEN_ACCESSOR(Change) 2214 }; 2215 2216 2217 class LSmiUntag final : public LTemplateInstruction<1, 1, 0> { 2218 public: 2219 LSmiUntag(LOperand* value, bool needs_check) 2220 : needs_check_(needs_check) { 2221 inputs_[0] = value; 2222 } 2223 2224 LOperand* value() { return inputs_[0]; } 2225 bool needs_check() const { return needs_check_; } 2226 2227 DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag") 2228 2229 private: 2230 bool needs_check_; 2231 }; 2232 2233 2234 class LStackCheck final : public LTemplateInstruction<0, 1, 0> { 2235 public: 2236 explicit LStackCheck(LOperand* context) { 2237 inputs_[0] = context; 2238 } 2239 2240 LOperand* context() { return inputs_[0]; } 2241 2242 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check") 2243 DECLARE_HYDROGEN_ACCESSOR(StackCheck) 2244 2245 Label* done_label() { return &done_label_; } 2246 2247 private: 2248 Label done_label_; 2249 }; 2250 2251 2252 template <int T> 2253 class LStoreKeyed : public LTemplateInstruction<0, 4, T> { 2254 public: 2255 LStoreKeyed(LOperand* elements, LOperand* key, LOperand* value, 2256 LOperand* backing_store_owner) { 2257 this->inputs_[0] = elements; 2258 this->inputs_[1] = key; 2259 this->inputs_[2] = value; 2260 this->inputs_[3] = backing_store_owner; 2261 } 2262 2263 bool is_external() const { return this->hydrogen()->is_external(); } 2264 bool is_fixed_typed_array() const { 2265 return hydrogen()->is_fixed_typed_array(); 2266 } 2267 bool is_typed_elements() const { 2268 return is_external() || is_fixed_typed_array(); 2269 } 2270 LOperand* elements() { return this->inputs_[0]; } 2271 LOperand* key() { return this->inputs_[1]; } 2272 LOperand* value() { return this->inputs_[2]; } 2273 LOperand* backing_store_owner() { return this->inputs_[3]; } 2274 ElementsKind elements_kind() const { 2275 return this->hydrogen()->elements_kind(); 2276 } 2277 2278 bool NeedsCanonicalization() { 2279 if (hydrogen()->value()->IsAdd() || hydrogen()->value()->IsSub() || 2280 hydrogen()->value()->IsMul() || hydrogen()->value()->IsDiv()) { 2281 return false; 2282 } 2283 return this->hydrogen()->NeedsCanonicalization(); 2284 } 2285 uint32_t base_offset() const { return this->hydrogen()->base_offset(); } 2286 2287 void PrintDataTo(StringStream* stream) override { 2288 this->elements()->PrintTo(stream); 2289 stream->Add("["); 2290 this->key()->PrintTo(stream); 2291 if (this->base_offset() != 0) { 2292 stream->Add(" + %d] <-", this->base_offset()); 2293 } else { 2294 stream->Add("] <- "); 2295 } 2296 2297 if (this->value() == NULL) { 2298 DCHECK(hydrogen()->IsConstantHoleStore() && 2299 hydrogen()->value()->representation().IsDouble()); 2300 stream->Add("<the hole(nan)>"); 2301 } else { 2302 this->value()->PrintTo(stream); 2303 } 2304 } 2305 2306 DECLARE_HYDROGEN_ACCESSOR(StoreKeyed) 2307 }; 2308 2309 2310 class LStoreKeyedExternal final : public LStoreKeyed<1> { 2311 public: 2312 LStoreKeyedExternal(LOperand* elements, LOperand* key, LOperand* value, 2313 LOperand* backing_store_owner, LOperand* temp) 2314 : LStoreKeyed<1>(elements, key, value, backing_store_owner) { 2315 temps_[0] = temp; 2316 } 2317 2318 LOperand* temp() { return temps_[0]; } 2319 2320 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedExternal, "store-keyed-external") 2321 }; 2322 2323 2324 class LStoreKeyedFixed final : public LStoreKeyed<1> { 2325 public: 2326 LStoreKeyedFixed(LOperand* elements, LOperand* key, LOperand* value, 2327 LOperand* temp) 2328 : LStoreKeyed<1>(elements, key, value, nullptr) { 2329 temps_[0] = temp; 2330 } 2331 2332 LOperand* temp() { return temps_[0]; } 2333 2334 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixed, "store-keyed-fixed") 2335 }; 2336 2337 2338 class LStoreKeyedFixedDouble final : public LStoreKeyed<1> { 2339 public: 2340 LStoreKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* value, 2341 LOperand* temp) 2342 : LStoreKeyed<1>(elements, key, value, nullptr) { 2343 temps_[0] = temp; 2344 } 2345 2346 LOperand* temp() { return temps_[0]; } 2347 2348 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixedDouble, 2349 "store-keyed-fixed-double") 2350 }; 2351 2352 2353 class LStoreKeyedGeneric final : public LTemplateInstruction<0, 4, 2> { 2354 public: 2355 LStoreKeyedGeneric(LOperand* context, LOperand* object, LOperand* key, 2356 LOperand* value, LOperand* slot, LOperand* vector) { 2357 inputs_[0] = context; 2358 inputs_[1] = object; 2359 inputs_[2] = key; 2360 inputs_[3] = value; 2361 temps_[0] = slot; 2362 temps_[1] = vector; 2363 } 2364 2365 LOperand* context() { return inputs_[0]; } 2366 LOperand* object() { return inputs_[1]; } 2367 LOperand* key() { return inputs_[2]; } 2368 LOperand* value() { return inputs_[3]; } 2369 LOperand* temp_slot() { return temps_[0]; } 2370 LOperand* temp_vector() { return temps_[1]; } 2371 2372 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic") 2373 DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric) 2374 2375 void PrintDataTo(StringStream* stream) override; 2376 2377 LanguageMode language_mode() { return hydrogen()->language_mode(); } 2378 }; 2379 2380 2381 class LStoreNamedField final : public LTemplateInstruction<0, 2, 2> { 2382 public: 2383 LStoreNamedField(LOperand* object, LOperand* value, 2384 LOperand* temp0, LOperand* temp1) { 2385 inputs_[0] = object; 2386 inputs_[1] = value; 2387 temps_[0] = temp0; 2388 temps_[1] = temp1; 2389 } 2390 2391 LOperand* object() { return inputs_[0]; } 2392 LOperand* value() { return inputs_[1]; } 2393 LOperand* temp0() { return temps_[0]; } 2394 LOperand* temp1() { return temps_[1]; } 2395 2396 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field") 2397 DECLARE_HYDROGEN_ACCESSOR(StoreNamedField) 2398 2399 void PrintDataTo(StringStream* stream) override; 2400 2401 Representation representation() const { 2402 return hydrogen()->field_representation(); 2403 } 2404 }; 2405 2406 2407 class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> { 2408 public: 2409 LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value, 2410 LOperand* slot, LOperand* vector) { 2411 inputs_[0] = context; 2412 inputs_[1] = object; 2413 inputs_[2] = value; 2414 temps_[0] = slot; 2415 temps_[1] = vector; 2416 } 2417 2418 LOperand* context() { return inputs_[0]; } 2419 LOperand* object() { return inputs_[1]; } 2420 LOperand* value() { return inputs_[2]; } 2421 LOperand* temp_slot() { return temps_[0]; } 2422 LOperand* temp_vector() { return temps_[1]; } 2423 2424 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic") 2425 DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric) 2426 2427 void PrintDataTo(StringStream* stream) override; 2428 2429 Handle<Object> name() const { return hydrogen()->name(); } 2430 LanguageMode language_mode() { return hydrogen()->language_mode(); } 2431 }; 2432 2433 2434 class LMaybeGrowElements final : public LTemplateInstruction<1, 5, 0> { 2435 public: 2436 LMaybeGrowElements(LOperand* context, LOperand* object, LOperand* elements, 2437 LOperand* key, LOperand* current_capacity) { 2438 inputs_[0] = context; 2439 inputs_[1] = object; 2440 inputs_[2] = elements; 2441 inputs_[3] = key; 2442 inputs_[4] = current_capacity; 2443 } 2444 2445 LOperand* context() { return inputs_[0]; } 2446 LOperand* object() { return inputs_[1]; } 2447 LOperand* elements() { return inputs_[2]; } 2448 LOperand* key() { return inputs_[3]; } 2449 LOperand* current_capacity() { return inputs_[4]; } 2450 2451 DECLARE_HYDROGEN_ACCESSOR(MaybeGrowElements) 2452 DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements, "maybe-grow-elements") 2453 }; 2454 2455 2456 class LStringAdd final : public LTemplateInstruction<1, 3, 0> { 2457 public: 2458 LStringAdd(LOperand* context, LOperand* left, LOperand* right) { 2459 inputs_[0] = context; 2460 inputs_[1] = left; 2461 inputs_[2] = right; 2462 } 2463 2464 LOperand* context() { return inputs_[0]; } 2465 LOperand* left() { return inputs_[1]; } 2466 LOperand* right() { return inputs_[2]; } 2467 2468 DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add") 2469 DECLARE_HYDROGEN_ACCESSOR(StringAdd) 2470 }; 2471 2472 2473 class LStringCharCodeAt final : public LTemplateInstruction<1, 3, 0> { 2474 public: 2475 LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) { 2476 inputs_[0] = context; 2477 inputs_[1] = string; 2478 inputs_[2] = index; 2479 } 2480 2481 LOperand* context() { return inputs_[0]; } 2482 LOperand* string() { return inputs_[1]; } 2483 LOperand* index() { return inputs_[2]; } 2484 2485 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at") 2486 DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt) 2487 }; 2488 2489 2490 class LStringCharFromCode final : public LTemplateInstruction<1, 2, 0> { 2491 public: 2492 LStringCharFromCode(LOperand* context, LOperand* char_code) { 2493 inputs_[0] = context; 2494 inputs_[1] = char_code; 2495 } 2496 2497 LOperand* context() { return inputs_[0]; } 2498 LOperand* char_code() { return inputs_[1]; } 2499 2500 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code") 2501 DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode) 2502 }; 2503 2504 2505 class LStringCompareAndBranch final : public LControlInstruction<3, 0> { 2506 public: 2507 LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) { 2508 inputs_[0] = context; 2509 inputs_[1] = left; 2510 inputs_[2] = right; 2511 } 2512 2513 LOperand* context() { return inputs_[0]; } 2514 LOperand* left() { return inputs_[1]; } 2515 LOperand* right() { return inputs_[2]; } 2516 2517 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch, 2518 "string-compare-and-branch") 2519 DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch) 2520 2521 Token::Value op() const { return hydrogen()->token(); } 2522 2523 void PrintDataTo(StringStream* stream) override; 2524 }; 2525 2526 2527 // Truncating conversion from a tagged value to an int32. 2528 class LTaggedToI final : public LTemplateInstruction<1, 1, 2> { 2529 public: 2530 explicit LTaggedToI(LOperand* value, LOperand* temp1, LOperand* temp2) { 2531 inputs_[0] = value; 2532 temps_[0] = temp1; 2533 temps_[1] = temp2; 2534 } 2535 2536 LOperand* value() { return inputs_[0]; } 2537 LOperand* temp1() { return temps_[0]; } 2538 LOperand* temp2() { return temps_[1]; } 2539 2540 DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i") 2541 DECLARE_HYDROGEN_ACCESSOR(Change) 2542 2543 bool truncating() { return hydrogen()->CanTruncateToInt32(); } 2544 }; 2545 2546 2547 class LShiftI final : public LTemplateInstruction<1, 2, 0> { 2548 public: 2549 LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt) 2550 : op_(op), can_deopt_(can_deopt) { 2551 inputs_[0] = left; 2552 inputs_[1] = right; 2553 } 2554 2555 Token::Value op() const { return op_; } 2556 LOperand* left() { return inputs_[0]; } 2557 LOperand* right() { return inputs_[1]; } 2558 bool can_deopt() const { return can_deopt_; } 2559 2560 DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i") 2561 2562 private: 2563 Token::Value op_; 2564 bool can_deopt_; 2565 }; 2566 2567 2568 class LShiftS final : public LTemplateInstruction<1, 2, 0> { 2569 public: 2570 LShiftS(Token::Value op, LOperand* left, LOperand* right, bool can_deopt) 2571 : op_(op), can_deopt_(can_deopt) { 2572 inputs_[0] = left; 2573 inputs_[1] = right; 2574 } 2575 2576 Token::Value op() const { return op_; } 2577 LOperand* left() { return inputs_[0]; } 2578 LOperand* right() { return inputs_[1]; } 2579 bool can_deopt() const { return can_deopt_; } 2580 2581 DECLARE_CONCRETE_INSTRUCTION(ShiftS, "shift-s") 2582 2583 private: 2584 Token::Value op_; 2585 bool can_deopt_; 2586 }; 2587 2588 2589 class LStoreCodeEntry final : public LTemplateInstruction<0, 2, 1> { 2590 public: 2591 LStoreCodeEntry(LOperand* function, LOperand* code_object, 2592 LOperand* temp) { 2593 inputs_[0] = function; 2594 inputs_[1] = code_object; 2595 temps_[0] = temp; 2596 } 2597 2598 LOperand* function() { return inputs_[0]; } 2599 LOperand* code_object() { return inputs_[1]; } 2600 LOperand* temp() { return temps_[0]; } 2601 2602 void PrintDataTo(StringStream* stream) override; 2603 2604 DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry") 2605 DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry) 2606 }; 2607 2608 2609 class LStoreContextSlot final : public LTemplateInstruction<0, 2, 1> { 2610 public: 2611 LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) { 2612 inputs_[0] = context; 2613 inputs_[1] = value; 2614 temps_[0] = temp; 2615 } 2616 2617 LOperand* context() { return inputs_[0]; } 2618 LOperand* value() { return inputs_[1]; } 2619 LOperand* temp() { return temps_[0]; } 2620 2621 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot") 2622 DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot) 2623 2624 int slot_index() { return hydrogen()->slot_index(); } 2625 2626 void PrintDataTo(StringStream* stream) override; 2627 }; 2628 2629 2630 class LSubI final : public LTemplateInstruction<1, 2, 0> { 2631 public: 2632 LSubI(LOperand* left, LOperand* right) 2633 : shift_(NO_SHIFT), shift_amount_(0) { 2634 inputs_[0] = left; 2635 inputs_[1] = right; 2636 } 2637 2638 LSubI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount) 2639 : shift_(shift), shift_amount_(shift_amount) { 2640 inputs_[0] = left; 2641 inputs_[1] = right; 2642 } 2643 2644 LOperand* left() { return inputs_[0]; } 2645 LOperand* right() { return inputs_[1]; } 2646 2647 Shift shift() const { return shift_; } 2648 LOperand* shift_amount() const { return shift_amount_; } 2649 2650 DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i") 2651 DECLARE_HYDROGEN_ACCESSOR(Sub) 2652 2653 protected: 2654 Shift shift_; 2655 LOperand* shift_amount_; 2656 }; 2657 2658 2659 class LSubS: public LTemplateInstruction<1, 2, 0> { 2660 public: 2661 LSubS(LOperand* left, LOperand* right) { 2662 inputs_[0] = left; 2663 inputs_[1] = right; 2664 } 2665 2666 LOperand* left() { return inputs_[0]; } 2667 LOperand* right() { return inputs_[1]; } 2668 2669 DECLARE_CONCRETE_INSTRUCTION(SubS, "sub-s") 2670 DECLARE_HYDROGEN_ACCESSOR(Sub) 2671 }; 2672 2673 2674 class LThisFunction final : public LTemplateInstruction<1, 0, 0> { 2675 public: 2676 DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function") 2677 DECLARE_HYDROGEN_ACCESSOR(ThisFunction) 2678 }; 2679 2680 2681 class LTransitionElementsKind final : public LTemplateInstruction<0, 2, 2> { 2682 public: 2683 LTransitionElementsKind(LOperand* object, 2684 LOperand* context, 2685 LOperand* temp1, 2686 LOperand* temp2) { 2687 inputs_[0] = object; 2688 inputs_[1] = context; 2689 temps_[0] = temp1; 2690 temps_[1] = temp2; 2691 } 2692 2693 LOperand* object() { return inputs_[0]; } 2694 LOperand* context() { return inputs_[1]; } 2695 LOperand* temp1() { return temps_[0]; } 2696 LOperand* temp2() { return temps_[1]; } 2697 2698 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind, 2699 "transition-elements-kind") 2700 DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind) 2701 2702 void PrintDataTo(StringStream* stream) override; 2703 2704 Handle<Map> original_map() { return hydrogen()->original_map().handle(); } 2705 Handle<Map> transitioned_map() { 2706 return hydrogen()->transitioned_map().handle(); 2707 } 2708 ElementsKind from_kind() const { return hydrogen()->from_kind(); } 2709 ElementsKind to_kind() const { return hydrogen()->to_kind(); } 2710 }; 2711 2712 2713 class LTrapAllocationMemento final : public LTemplateInstruction<0, 1, 2> { 2714 public: 2715 LTrapAllocationMemento(LOperand* object, LOperand* temp1, LOperand* temp2) { 2716 inputs_[0] = object; 2717 temps_[0] = temp1; 2718 temps_[1] = temp2; 2719 } 2720 2721 LOperand* object() { return inputs_[0]; } 2722 LOperand* temp1() { return temps_[0]; } 2723 LOperand* temp2() { return temps_[1]; } 2724 2725 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento, "trap-allocation-memento") 2726 }; 2727 2728 2729 class LTruncateDoubleToIntOrSmi final : public LTemplateInstruction<1, 1, 0> { 2730 public: 2731 explicit LTruncateDoubleToIntOrSmi(LOperand* value) { 2732 inputs_[0] = value; 2733 } 2734 2735 LOperand* value() { return inputs_[0]; } 2736 2737 DECLARE_CONCRETE_INSTRUCTION(TruncateDoubleToIntOrSmi, 2738 "truncate-double-to-int-or-smi") 2739 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) 2740 2741 bool tag_result() { return hydrogen()->representation().IsSmi(); } 2742 }; 2743 2744 2745 class LTypeof final : public LTemplateInstruction<1, 2, 0> { 2746 public: 2747 LTypeof(LOperand* context, LOperand* value) { 2748 inputs_[0] = context; 2749 inputs_[1] = value; 2750 } 2751 2752 LOperand* context() { return inputs_[0]; } 2753 LOperand* value() { return inputs_[1]; } 2754 2755 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof") 2756 }; 2757 2758 2759 class LTypeofIsAndBranch final : public LControlInstruction<1, 2> { 2760 public: 2761 LTypeofIsAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) { 2762 inputs_[0] = value; 2763 temps_[0] = temp1; 2764 temps_[1] = temp2; 2765 } 2766 2767 LOperand* value() { return inputs_[0]; } 2768 LOperand* temp1() { return temps_[0]; } 2769 LOperand* temp2() { return temps_[1]; } 2770 2771 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch") 2772 DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch) 2773 2774 Handle<String> type_literal() const { return hydrogen()->type_literal(); } 2775 2776 void PrintDataTo(StringStream* stream) override; 2777 }; 2778 2779 2780 class LUint32ToDouble final : public LTemplateInstruction<1, 1, 0> { 2781 public: 2782 explicit LUint32ToDouble(LOperand* value) { 2783 inputs_[0] = value; 2784 } 2785 2786 LOperand* value() { return inputs_[0]; } 2787 2788 DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double") 2789 }; 2790 2791 2792 class LCheckMapValue final : public LTemplateInstruction<0, 2, 1> { 2793 public: 2794 LCheckMapValue(LOperand* value, LOperand* map, LOperand* temp) { 2795 inputs_[0] = value; 2796 inputs_[1] = map; 2797 temps_[0] = temp; 2798 } 2799 2800 LOperand* value() { return inputs_[0]; } 2801 LOperand* map() { return inputs_[1]; } 2802 LOperand* temp() { return temps_[0]; } 2803 2804 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value") 2805 }; 2806 2807 2808 class LLoadFieldByIndex final : public LTemplateInstruction<1, 2, 0> { 2809 public: 2810 LLoadFieldByIndex(LOperand* object, LOperand* index) { 2811 inputs_[0] = object; 2812 inputs_[1] = index; 2813 } 2814 2815 LOperand* object() { return inputs_[0]; } 2816 LOperand* index() { return inputs_[1]; } 2817 2818 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index") 2819 }; 2820 2821 2822 class LWrapReceiver final : public LTemplateInstruction<1, 2, 0> { 2823 public: 2824 LWrapReceiver(LOperand* receiver, LOperand* function) { 2825 inputs_[0] = receiver; 2826 inputs_[1] = function; 2827 } 2828 2829 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver") 2830 DECLARE_HYDROGEN_ACCESSOR(WrapReceiver) 2831 2832 LOperand* receiver() { return inputs_[0]; } 2833 LOperand* function() { return inputs_[1]; } 2834 }; 2835 2836 2837 class LChunkBuilder; 2838 class LPlatformChunk final : public LChunk { 2839 public: 2840 LPlatformChunk(CompilationInfo* info, HGraph* graph) 2841 : LChunk(info, graph) { } 2842 2843 int GetNextSpillIndex(); 2844 LOperand* GetNextSpillSlot(RegisterKind kind); 2845 }; 2846 2847 2848 class LChunkBuilder final : public LChunkBuilderBase { 2849 public: 2850 LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator) 2851 : LChunkBuilderBase(info, graph), 2852 current_instruction_(NULL), 2853 current_block_(NULL), 2854 allocator_(allocator) {} 2855 2856 // Build the sequence for the graph. 2857 LPlatformChunk* Build(); 2858 2859 // Declare methods that deal with the individual node types. 2860 #define DECLARE_DO(type) LInstruction* Do##type(H##type* node); 2861 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) 2862 #undef DECLARE_DO 2863 2864 LInstruction* DoDivByPowerOf2I(HDiv* instr); 2865 LInstruction* DoDivByConstI(HDiv* instr); 2866 LInstruction* DoDivI(HBinaryOperation* instr); 2867 LInstruction* DoModByPowerOf2I(HMod* instr); 2868 LInstruction* DoModByConstI(HMod* instr); 2869 LInstruction* DoModI(HMod* instr); 2870 LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr); 2871 LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr); 2872 LInstruction* DoFlooringDivI(HMathFloorOfDiv* instr); 2873 2874 static bool HasMagicNumberForDivision(int32_t divisor); 2875 2876 private: 2877 // Methods for getting operands for Use / Define / Temp. 2878 LUnallocated* ToUnallocated(Register reg); 2879 LUnallocated* ToUnallocated(DoubleRegister reg); 2880 2881 // Methods for setting up define-use relationships. 2882 MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand); 2883 MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register); 2884 MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value, 2885 DoubleRegister fixed_register); 2886 2887 // A value that is guaranteed to be allocated to a register. 2888 // The operand created by UseRegister is guaranteed to be live until the end 2889 // of the instruction. This means that register allocator will not reuse its 2890 // register for any other operand inside instruction. 2891 MUST_USE_RESULT LOperand* UseRegister(HValue* value); 2892 2893 // The operand created by UseRegisterAndClobber is guaranteed to be live until 2894 // the end of the end of the instruction, and it may also be used as a scratch 2895 // register by the instruction implementation. 2896 // 2897 // This behaves identically to ARM's UseTempRegister. However, it is renamed 2898 // to discourage its use in ARM64, since in most cases it is better to 2899 // allocate a temporary register for the Lithium instruction. 2900 MUST_USE_RESULT LOperand* UseRegisterAndClobber(HValue* value); 2901 2902 // The operand created by UseRegisterAtStart is guaranteed to be live only at 2903 // instruction start. The register allocator is free to assign the same 2904 // register to some other operand used inside instruction (i.e. temporary or 2905 // output). 2906 MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value); 2907 2908 // An input operand in a register or a constant operand. 2909 MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value); 2910 MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value); 2911 2912 // A constant operand. 2913 MUST_USE_RESULT LConstantOperand* UseConstant(HValue* value); 2914 2915 // An input operand in register, stack slot or a constant operand. 2916 // Will not be moved to a register even if one is freely available. 2917 virtual MUST_USE_RESULT LOperand* UseAny(HValue* value); 2918 2919 // Temporary operand that must be in a register. 2920 MUST_USE_RESULT LUnallocated* TempRegister(); 2921 2922 // Temporary operand that must be in a double register. 2923 MUST_USE_RESULT LUnallocated* TempDoubleRegister(); 2924 2925 MUST_USE_RESULT LOperand* FixedTemp(Register reg); 2926 2927 // Temporary operand that must be in a fixed double register. 2928 MUST_USE_RESULT LOperand* FixedTemp(DoubleRegister reg); 2929 2930 // Methods for setting up define-use relationships. 2931 // Return the same instruction that they are passed. 2932 LInstruction* Define(LTemplateResultInstruction<1>* instr, 2933 LUnallocated* result); 2934 LInstruction* DefineAsRegister(LTemplateResultInstruction<1>* instr); 2935 LInstruction* DefineAsSpilled(LTemplateResultInstruction<1>* instr, 2936 int index); 2937 2938 LInstruction* DefineSameAsFirst(LTemplateResultInstruction<1>* instr); 2939 LInstruction* DefineFixed(LTemplateResultInstruction<1>* instr, 2940 Register reg); 2941 LInstruction* DefineFixedDouble(LTemplateResultInstruction<1>* instr, 2942 DoubleRegister reg); 2943 2944 enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY }; 2945 2946 // By default we assume that instruction sequences generated for calls 2947 // cannot deoptimize eagerly and we do not attach environment to this 2948 // instruction. 2949 LInstruction* MarkAsCall( 2950 LInstruction* instr, 2951 HInstruction* hinstr, 2952 CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY); 2953 2954 LInstruction* AssignPointerMap(LInstruction* instr); 2955 LInstruction* AssignEnvironment(LInstruction* instr); 2956 2957 void VisitInstruction(HInstruction* current); 2958 void AddInstruction(LInstruction* instr, HInstruction* current); 2959 void DoBasicBlock(HBasicBlock* block); 2960 2961 int JSShiftAmountFromHConstant(HValue* constant) { 2962 return HConstant::cast(constant)->Integer32Value() & 0x1f; 2963 } 2964 bool LikelyFitsImmField(HInstruction* instr, int imm) { 2965 if (instr->IsAdd() || instr->IsSub()) { 2966 return Assembler::IsImmAddSub(imm) || Assembler::IsImmAddSub(-imm); 2967 } else { 2968 DCHECK(instr->IsBitwise()); 2969 unsigned unused_n, unused_imm_s, unused_imm_r; 2970 return Assembler::IsImmLogical(imm, kWRegSizeInBits, 2971 &unused_n, &unused_imm_s, &unused_imm_r); 2972 } 2973 } 2974 2975 // Indicates if a sequence of the form 2976 // lsl x8, x9, #imm 2977 // add x0, x1, x8 2978 // can be replaced with: 2979 // add x0, x1, x9 LSL #imm 2980 // If this is not possible, the function returns NULL. Otherwise it returns a 2981 // pointer to the shift instruction that would be optimized away. 2982 HBitwiseBinaryOperation* CanTransformToShiftedOp(HValue* val, 2983 HValue** left = NULL); 2984 // Checks if all uses of the shift operation can optimize it away. 2985 bool ShiftCanBeOptimizedAway(HBitwiseBinaryOperation* shift); 2986 // Attempts to merge the binary operation and an eventual previous shift 2987 // operation into a single operation. Returns the merged instruction on 2988 // success, and NULL otherwise. 2989 LInstruction* TryDoOpWithShiftedRightOperand(HBinaryOperation* op); 2990 LInstruction* DoShiftedBinaryOp(HBinaryOperation* instr, 2991 HValue* left, 2992 HBitwiseBinaryOperation* shift); 2993 2994 LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr); 2995 LInstruction* DoArithmeticD(Token::Value op, 2996 HArithmeticBinaryOperation* instr); 2997 LInstruction* DoArithmeticT(Token::Value op, 2998 HBinaryOperation* instr); 2999 3000 HInstruction* current_instruction_; 3001 HBasicBlock* current_block_; 3002 LAllocator* allocator_; 3003 3004 DISALLOW_COPY_AND_ASSIGN(LChunkBuilder); 3005 }; 3006 3007 #undef DECLARE_HYDROGEN_ACCESSOR 3008 #undef DECLARE_CONCRETE_INSTRUCTION 3009 3010 } // namespace internal 3011 } // namespace v8 3012 3013 #endif // V8_CRANKSHAFT_ARM64_LITHIUM_ARM64_H_ 3014