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 3// found in the LICENSE file. 4 5#ifndef V8_CRANKSHAFT_MIPS_LITHIUM_MIPS_H_ 6#define V8_CRANKSHAFT_MIPS_LITHIUM_MIPS_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 14namespace v8 { 15namespace internal { 16 17// Forward declarations. 18class LCodeGen; 19 20#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \ 21 V(AccessArgumentsAt) \ 22 V(AddI) \ 23 V(Allocate) \ 24 V(ApplyArguments) \ 25 V(ArgumentsElements) \ 26 V(ArgumentsLength) \ 27 V(ArithmeticD) \ 28 V(ArithmeticT) \ 29 V(BitI) \ 30 V(BoundsCheck) \ 31 V(Branch) \ 32 V(CallWithDescriptor) \ 33 V(CallNewArray) \ 34 V(CallRuntime) \ 35 V(CheckArrayBufferNotNeutered) \ 36 V(CheckInstanceType) \ 37 V(CheckMaps) \ 38 V(CheckMapValue) \ 39 V(CheckNonSmi) \ 40 V(CheckSmi) \ 41 V(CheckValue) \ 42 V(ClampDToUint8) \ 43 V(ClampIToUint8) \ 44 V(ClampTToUint8) \ 45 V(ClassOfTestAndBranch) \ 46 V(CompareNumericAndBranch) \ 47 V(CmpObjectEqAndBranch) \ 48 V(CmpHoleAndBranch) \ 49 V(CmpMapAndBranch) \ 50 V(CmpT) \ 51 V(ConstantD) \ 52 V(ConstantE) \ 53 V(ConstantI) \ 54 V(ConstantS) \ 55 V(ConstantT) \ 56 V(Context) \ 57 V(DebugBreak) \ 58 V(DeclareGlobals) \ 59 V(Deoptimize) \ 60 V(DivByConstI) \ 61 V(DivByPowerOf2I) \ 62 V(DivI) \ 63 V(DoubleToI) \ 64 V(DoubleToSmi) \ 65 V(Drop) \ 66 V(Dummy) \ 67 V(DummyUse) \ 68 V(FastAllocate) \ 69 V(FlooringDivByConstI) \ 70 V(FlooringDivByPowerOf2I) \ 71 V(FlooringDivI) \ 72 V(ForInCacheArray) \ 73 V(ForInPrepareMap) \ 74 V(Goto) \ 75 V(HasInPrototypeChainAndBranch) \ 76 V(HasInstanceTypeAndBranch) \ 77 V(InnerAllocatedObject) \ 78 V(InstructionGap) \ 79 V(Integer32ToDouble) \ 80 V(InvokeFunction) \ 81 V(IsStringAndBranch) \ 82 V(IsSmiAndBranch) \ 83 V(IsUndetectableAndBranch) \ 84 V(Label) \ 85 V(LazyBailout) \ 86 V(LoadContextSlot) \ 87 V(LoadRoot) \ 88 V(LoadFieldByIndex) \ 89 V(LoadFunctionPrototype) \ 90 V(LoadKeyed) \ 91 V(LoadNamedField) \ 92 V(MathAbs) \ 93 V(MathCos) \ 94 V(MathSin) \ 95 V(MathExp) \ 96 V(MathClz32) \ 97 V(MathFloor) \ 98 V(MathFround) \ 99 V(MathLog) \ 100 V(MathMinMax) \ 101 V(MathPowHalf) \ 102 V(MathRound) \ 103 V(MathSqrt) \ 104 V(MaybeGrowElements) \ 105 V(ModByConstI) \ 106 V(ModByPowerOf2I) \ 107 V(ModI) \ 108 V(MulI) \ 109 V(MultiplyAddD) \ 110 V(NumberTagD) \ 111 V(NumberTagI) \ 112 V(NumberTagU) \ 113 V(NumberUntagD) \ 114 V(OsrEntry) \ 115 V(Parameter) \ 116 V(Power) \ 117 V(Prologue) \ 118 V(PushArgument) \ 119 V(Return) \ 120 V(SeqStringGetChar) \ 121 V(SeqStringSetChar) \ 122 V(ShiftI) \ 123 V(SmiTag) \ 124 V(SmiUntag) \ 125 V(StackCheck) \ 126 V(StoreCodeEntry) \ 127 V(StoreContextSlot) \ 128 V(StoreKeyed) \ 129 V(StoreNamedField) \ 130 V(StringAdd) \ 131 V(StringCharCodeAt) \ 132 V(StringCharFromCode) \ 133 V(StringCompareAndBranch) \ 134 V(SubI) \ 135 V(TaggedToI) \ 136 V(ThisFunction) \ 137 V(TransitionElementsKind) \ 138 V(TrapAllocationMemento) \ 139 V(Typeof) \ 140 V(TypeofIsAndBranch) \ 141 V(Uint32ToDouble) \ 142 V(UnknownOSRValue) \ 143 V(WrapReceiver) 144 145#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \ 146 Opcode opcode() const final { return LInstruction::k##type; } \ 147 void CompileToNative(LCodeGen* generator) final; \ 148 const char* Mnemonic() const final { return mnemonic; } \ 149 static L##type* cast(LInstruction* instr) { \ 150 DCHECK(instr->Is##type()); \ 151 return reinterpret_cast<L##type*>(instr); \ 152 } 153 154 155#define DECLARE_HYDROGEN_ACCESSOR(type) \ 156 H##type* hydrogen() const { \ 157 return H##type::cast(hydrogen_value()); \ 158 } 159 160 161class LInstruction : public ZoneObject { 162 public: 163 LInstruction() 164 : environment_(NULL), 165 hydrogen_value_(NULL), 166 bit_field_(IsCallBits::encode(false)) { 167 } 168 169 virtual ~LInstruction() {} 170 171 virtual void CompileToNative(LCodeGen* generator) = 0; 172 virtual const char* Mnemonic() const = 0; 173 virtual void PrintTo(StringStream* stream); 174 virtual void PrintDataTo(StringStream* stream); 175 virtual void PrintOutputOperandTo(StringStream* stream); 176 177 enum Opcode { 178 // Declare a unique enum value for each instruction. 179#define DECLARE_OPCODE(type) k##type, 180 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE) 181 kNumberOfInstructions 182#undef DECLARE_OPCODE 183 }; 184 185 virtual Opcode opcode() const = 0; 186 187 // Declare non-virtual type testers for all leaf IR classes. 188#define DECLARE_PREDICATE(type) \ 189 bool Is##type() const { return opcode() == k##type; } 190 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE) 191#undef DECLARE_PREDICATE 192 193 // Declare virtual predicates for instructions that don't have 194 // an opcode. 195 virtual bool IsGap() const { return false; } 196 197 virtual bool IsControl() const { return false; } 198 199 // Try deleting this instruction if possible. 200 virtual bool TryDelete() { return false; } 201 202 void set_environment(LEnvironment* env) { environment_ = env; } 203 LEnvironment* environment() const { return environment_; } 204 bool HasEnvironment() const { return environment_ != NULL; } 205 206 void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); } 207 LPointerMap* pointer_map() const { return pointer_map_.get(); } 208 bool HasPointerMap() const { return pointer_map_.is_set(); } 209 210 void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; } 211 HValue* hydrogen_value() const { return hydrogen_value_; } 212 213 void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); } 214 bool IsCall() const { return IsCallBits::decode(bit_field_); } 215 216 void MarkAsSyntacticTailCall() { 217 bit_field_ = IsSyntacticTailCallBits::update(bit_field_, true); 218 } 219 bool IsSyntacticTailCall() const { 220 return IsSyntacticTailCallBits::decode(bit_field_); 221 } 222 223 // Interface to the register allocator and iterators. 224 bool ClobbersTemps() const { return IsCall(); } 225 bool ClobbersRegisters() const { return IsCall(); } 226 virtual bool ClobbersDoubleRegisters(Isolate* isolate) const { 227 return IsCall(); 228 } 229 230 // Interface to the register allocator and iterators. 231 bool IsMarkedAsCall() const { return IsCall(); } 232 233 virtual bool HasResult() const = 0; 234 virtual LOperand* result() const = 0; 235 236 LOperand* FirstInput() { return InputAt(0); } 237 LOperand* Output() { return HasResult() ? result() : NULL; } 238 239 virtual bool HasInterestingComment(LCodeGen* gen) const { return true; } 240 241#ifdef DEBUG 242 void VerifyCall(); 243#endif 244 245 virtual int InputCount() = 0; 246 virtual LOperand* InputAt(int i) = 0; 247 248 private: 249 // Iterator interface. 250 friend class InputIterator; 251 252 friend class TempIterator; 253 virtual int TempCount() = 0; 254 virtual LOperand* TempAt(int i) = 0; 255 256 class IsCallBits: public BitField<bool, 0, 1> {}; 257 class IsSyntacticTailCallBits : public BitField<bool, IsCallBits::kNext, 1> { 258 }; 259 260 LEnvironment* environment_; 261 SetOncePointer<LPointerMap> pointer_map_; 262 HValue* hydrogen_value_; 263 int bit_field_; 264}; 265 266 267// R = number of result operands (0 or 1). 268template<int R> 269class LTemplateResultInstruction : public LInstruction { 270 public: 271 // Allow 0 or 1 output operands. 272 STATIC_ASSERT(R == 0 || R == 1); 273 bool HasResult() const final { return R != 0 && result() != NULL; } 274 void set_result(LOperand* operand) { results_[0] = operand; } 275 LOperand* result() const override { return results_[0]; } 276 277 protected: 278 EmbeddedContainer<LOperand*, R> results_; 279}; 280 281 282// R = number of result operands (0 or 1). 283// I = number of input operands. 284// T = number of temporary operands. 285template<int R, int I, int T> 286class LTemplateInstruction : public LTemplateResultInstruction<R> { 287 protected: 288 EmbeddedContainer<LOperand*, I> inputs_; 289 EmbeddedContainer<LOperand*, T> temps_; 290 291 private: 292 // Iterator support. 293 int InputCount() final { return I; } 294 LOperand* InputAt(int i) final { return inputs_[i]; } 295 296 int TempCount() final { return T; } 297 LOperand* TempAt(int i) final { return temps_[i]; } 298}; 299 300 301class LGap : public LTemplateInstruction<0, 0, 0> { 302 public: 303 explicit LGap(HBasicBlock* block) 304 : block_(block) { 305 parallel_moves_[BEFORE] = NULL; 306 parallel_moves_[START] = NULL; 307 parallel_moves_[END] = NULL; 308 parallel_moves_[AFTER] = NULL; 309 } 310 311 // Can't use the DECLARE-macro here because of sub-classes. 312 bool IsGap() const final { return true; } 313 void PrintDataTo(StringStream* stream) override; 314 static LGap* cast(LInstruction* instr) { 315 DCHECK(instr->IsGap()); 316 return reinterpret_cast<LGap*>(instr); 317 } 318 319 bool IsRedundant() const; 320 321 HBasicBlock* block() const { return block_; } 322 323 enum InnerPosition { 324 BEFORE, 325 START, 326 END, 327 AFTER, 328 FIRST_INNER_POSITION = BEFORE, 329 LAST_INNER_POSITION = AFTER 330 }; 331 332 LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) { 333 if (parallel_moves_[pos] == NULL) { 334 parallel_moves_[pos] = new(zone) LParallelMove(zone); 335 } 336 return parallel_moves_[pos]; 337 } 338 339 LParallelMove* GetParallelMove(InnerPosition pos) { 340 return parallel_moves_[pos]; 341 } 342 343 private: 344 LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1]; 345 HBasicBlock* block_; 346}; 347 348 349class LInstructionGap final : public LGap { 350 public: 351 explicit LInstructionGap(HBasicBlock* block) : LGap(block) { } 352 353 bool HasInterestingComment(LCodeGen* gen) const override { 354 return !IsRedundant(); 355 } 356 357 DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap") 358}; 359 360 361class LGoto final : public LTemplateInstruction<0, 0, 0> { 362 public: 363 explicit LGoto(HBasicBlock* block) : block_(block) { } 364 365 bool HasInterestingComment(LCodeGen* gen) const override; 366 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto") 367 void PrintDataTo(StringStream* stream) override; 368 bool IsControl() const override { return true; } 369 370 int block_id() const { return block_->block_id(); } 371 372 private: 373 HBasicBlock* block_; 374}; 375 376 377class LPrologue final : public LTemplateInstruction<0, 0, 0> { 378 public: 379 DECLARE_CONCRETE_INSTRUCTION(Prologue, "prologue") 380}; 381 382 383class LLazyBailout final : public LTemplateInstruction<0, 0, 0> { 384 public: 385 LLazyBailout() : gap_instructions_size_(0) { } 386 387 DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout") 388 389 void set_gap_instructions_size(int gap_instructions_size) { 390 gap_instructions_size_ = gap_instructions_size; 391 } 392 int gap_instructions_size() { return gap_instructions_size_; } 393 394 private: 395 int gap_instructions_size_; 396}; 397 398 399class LDummy final : public LTemplateInstruction<1, 0, 0> { 400 public: 401 LDummy() {} 402 DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy") 403}; 404 405 406class LDummyUse final : public LTemplateInstruction<1, 1, 0> { 407 public: 408 explicit LDummyUse(LOperand* value) { 409 inputs_[0] = value; 410 } 411 DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use") 412}; 413 414 415class LDeoptimize final : public LTemplateInstruction<0, 0, 0> { 416 public: 417 bool IsControl() const override { return true; } 418 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize") 419 DECLARE_HYDROGEN_ACCESSOR(Deoptimize) 420}; 421 422 423class LLabel final : public LGap { 424 public: 425 explicit LLabel(HBasicBlock* block) 426 : LGap(block), replacement_(NULL) { } 427 428 bool HasInterestingComment(LCodeGen* gen) const override { return false; } 429 DECLARE_CONCRETE_INSTRUCTION(Label, "label") 430 431 void PrintDataTo(StringStream* stream) override; 432 433 int block_id() const { return block()->block_id(); } 434 bool is_loop_header() const { return block()->IsLoopHeader(); } 435 bool is_osr_entry() const { return block()->is_osr_entry(); } 436 Label* label() { return &label_; } 437 LLabel* replacement() const { return replacement_; } 438 void set_replacement(LLabel* label) { replacement_ = label; } 439 bool HasReplacement() const { return replacement_ != NULL; } 440 441 private: 442 Label label_; 443 LLabel* replacement_; 444}; 445 446 447class LParameter final : public LTemplateInstruction<1, 0, 0> { 448 public: 449 bool HasInterestingComment(LCodeGen* gen) const override { return false; } 450 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter") 451}; 452 453 454class LUnknownOSRValue final : public LTemplateInstruction<1, 0, 0> { 455 public: 456 bool HasInterestingComment(LCodeGen* gen) const override { return false; } 457 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value") 458}; 459 460 461template<int I, int T> 462class LControlInstruction : public LTemplateInstruction<0, I, T> { 463 public: 464 LControlInstruction() : false_label_(NULL), true_label_(NULL) { } 465 466 bool IsControl() const final { return true; } 467 468 int SuccessorCount() { return hydrogen()->SuccessorCount(); } 469 HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); } 470 471 int TrueDestination(LChunk* chunk) { 472 return chunk->LookupDestination(true_block_id()); 473 } 474 int FalseDestination(LChunk* chunk) { 475 return chunk->LookupDestination(false_block_id()); 476 } 477 478 Label* TrueLabel(LChunk* chunk) { 479 if (true_label_ == NULL) { 480 true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk)); 481 } 482 return true_label_; 483 } 484 Label* FalseLabel(LChunk* chunk) { 485 if (false_label_ == NULL) { 486 false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk)); 487 } 488 return false_label_; 489 } 490 491 protected: 492 int true_block_id() { return SuccessorAt(0)->block_id(); } 493 int false_block_id() { return SuccessorAt(1)->block_id(); } 494 495 private: 496 HControlInstruction* hydrogen() { 497 return HControlInstruction::cast(this->hydrogen_value()); 498 } 499 500 Label* false_label_; 501 Label* true_label_; 502}; 503 504 505class LWrapReceiver final : public LTemplateInstruction<1, 2, 0> { 506 public: 507 LWrapReceiver(LOperand* receiver, LOperand* function) { 508 inputs_[0] = receiver; 509 inputs_[1] = function; 510 } 511 512 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver") 513 DECLARE_HYDROGEN_ACCESSOR(WrapReceiver) 514 515 LOperand* receiver() { return inputs_[0]; } 516 LOperand* function() { return inputs_[1]; } 517}; 518 519 520class LApplyArguments final : public LTemplateInstruction<1, 4, 0> { 521 public: 522 LApplyArguments(LOperand* function, 523 LOperand* receiver, 524 LOperand* length, 525 LOperand* elements) { 526 inputs_[0] = function; 527 inputs_[1] = receiver; 528 inputs_[2] = length; 529 inputs_[3] = elements; 530 } 531 532 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments") 533 DECLARE_HYDROGEN_ACCESSOR(ApplyArguments) 534 535 LOperand* function() { return inputs_[0]; } 536 LOperand* receiver() { return inputs_[1]; } 537 LOperand* length() { return inputs_[2]; } 538 LOperand* elements() { return inputs_[3]; } 539}; 540 541 542class LAccessArgumentsAt final : public LTemplateInstruction<1, 3, 0> { 543 public: 544 LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index) { 545 inputs_[0] = arguments; 546 inputs_[1] = length; 547 inputs_[2] = index; 548 } 549 550 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at") 551 552 LOperand* arguments() { return inputs_[0]; } 553 LOperand* length() { return inputs_[1]; } 554 LOperand* index() { return inputs_[2]; } 555 556 void PrintDataTo(StringStream* stream) override; 557}; 558 559 560class LArgumentsLength final : public LTemplateInstruction<1, 1, 0> { 561 public: 562 explicit LArgumentsLength(LOperand* elements) { 563 inputs_[0] = elements; 564 } 565 566 LOperand* elements() { return inputs_[0]; } 567 568 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length") 569}; 570 571 572class LArgumentsElements final : public LTemplateInstruction<1, 0, 0> { 573 public: 574 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements") 575 DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements) 576}; 577 578 579class LModByPowerOf2I final : public LTemplateInstruction<1, 1, 0> { 580 public: 581 LModByPowerOf2I(LOperand* dividend, int32_t divisor) { 582 inputs_[0] = dividend; 583 divisor_ = divisor; 584 } 585 586 LOperand* dividend() { return inputs_[0]; } 587 int32_t divisor() const { return divisor_; } 588 589 DECLARE_CONCRETE_INSTRUCTION(ModByPowerOf2I, "mod-by-power-of-2-i") 590 DECLARE_HYDROGEN_ACCESSOR(Mod) 591 592 private: 593 int32_t divisor_; 594}; 595 596 597class LModByConstI final : public LTemplateInstruction<1, 1, 0> { 598 public: 599 LModByConstI(LOperand* dividend, int32_t divisor) { 600 inputs_[0] = dividend; 601 divisor_ = divisor; 602 } 603 604 LOperand* dividend() { return inputs_[0]; } 605 int32_t divisor() const { return divisor_; } 606 607 DECLARE_CONCRETE_INSTRUCTION(ModByConstI, "mod-by-const-i") 608 DECLARE_HYDROGEN_ACCESSOR(Mod) 609 610 private: 611 int32_t divisor_; 612}; 613 614 615class LModI final : public LTemplateInstruction<1, 2, 3> { 616 public: 617 LModI(LOperand* left, 618 LOperand* right) { 619 inputs_[0] = left; 620 inputs_[1] = right; 621 } 622 623 LOperand* left() { return inputs_[0]; } 624 LOperand* right() { return inputs_[1]; } 625 626 DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i") 627 DECLARE_HYDROGEN_ACCESSOR(Mod) 628}; 629 630 631class LDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> { 632 public: 633 LDivByPowerOf2I(LOperand* dividend, int32_t divisor) { 634 inputs_[0] = dividend; 635 divisor_ = divisor; 636 } 637 638 LOperand* dividend() { return inputs_[0]; } 639 int32_t divisor() const { return divisor_; } 640 641 DECLARE_CONCRETE_INSTRUCTION(DivByPowerOf2I, "div-by-power-of-2-i") 642 DECLARE_HYDROGEN_ACCESSOR(Div) 643 644 private: 645 int32_t divisor_; 646}; 647 648 649class LDivByConstI final : public LTemplateInstruction<1, 1, 0> { 650 public: 651 LDivByConstI(LOperand* dividend, int32_t divisor) { 652 inputs_[0] = dividend; 653 divisor_ = divisor; 654 } 655 656 LOperand* dividend() { return inputs_[0]; } 657 int32_t divisor() const { return divisor_; } 658 659 DECLARE_CONCRETE_INSTRUCTION(DivByConstI, "div-by-const-i") 660 DECLARE_HYDROGEN_ACCESSOR(Div) 661 662 private: 663 int32_t divisor_; 664}; 665 666 667class LDivI final : public LTemplateInstruction<1, 2, 1> { 668 public: 669 LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) { 670 inputs_[0] = dividend; 671 inputs_[1] = divisor; 672 temps_[0] = temp; 673 } 674 675 LOperand* dividend() { return inputs_[0]; } 676 LOperand* divisor() { return inputs_[1]; } 677 LOperand* temp() { return temps_[0]; } 678 679 DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i") 680 DECLARE_HYDROGEN_ACCESSOR(BinaryOperation) 681}; 682 683 684class LFlooringDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> { 685 public: 686 LFlooringDivByPowerOf2I(LOperand* dividend, int32_t divisor) { 687 inputs_[0] = dividend; 688 divisor_ = divisor; 689 } 690 691 LOperand* dividend() { return inputs_[0]; } 692 int32_t divisor() { return divisor_; } 693 694 DECLARE_CONCRETE_INSTRUCTION(FlooringDivByPowerOf2I, 695 "flooring-div-by-power-of-2-i") 696 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv) 697 698 private: 699 int32_t divisor_; 700}; 701 702 703class LFlooringDivByConstI final : public LTemplateInstruction<1, 1, 2> { 704 public: 705 LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) { 706 inputs_[0] = dividend; 707 divisor_ = divisor; 708 temps_[0] = temp; 709 } 710 711 LOperand* dividend() { return inputs_[0]; } 712 int32_t divisor() const { return divisor_; } 713 LOperand* temp() { return temps_[0]; } 714 715 DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i") 716 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv) 717 718 private: 719 int32_t divisor_; 720}; 721 722 723class LFlooringDivI final : public LTemplateInstruction<1, 2, 0> { 724 public: 725 LFlooringDivI(LOperand* dividend, LOperand* divisor) { 726 inputs_[0] = dividend; 727 inputs_[1] = divisor; 728 } 729 730 LOperand* dividend() { return inputs_[0]; } 731 LOperand* divisor() { return inputs_[1]; } 732 733 DECLARE_CONCRETE_INSTRUCTION(FlooringDivI, "flooring-div-i") 734 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv) 735}; 736 737 738class LMulI final : public LTemplateInstruction<1, 2, 0> { 739 public: 740 LMulI(LOperand* left, LOperand* right) { 741 inputs_[0] = left; 742 inputs_[1] = right; 743 } 744 745 LOperand* left() { return inputs_[0]; } 746 LOperand* right() { return inputs_[1]; } 747 748 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i") 749 DECLARE_HYDROGEN_ACCESSOR(Mul) 750}; 751 752 753// Instruction for computing multiplier * multiplicand + addend. 754class LMultiplyAddD final : public LTemplateInstruction<1, 3, 0> { 755 public: 756 LMultiplyAddD(LOperand* addend, LOperand* multiplier, 757 LOperand* multiplicand) { 758 inputs_[0] = addend; 759 inputs_[1] = multiplier; 760 inputs_[2] = multiplicand; 761 } 762 763 LOperand* addend() { return inputs_[0]; } 764 LOperand* multiplier() { return inputs_[1]; } 765 LOperand* multiplicand() { return inputs_[2]; } 766 767 DECLARE_CONCRETE_INSTRUCTION(MultiplyAddD, "multiply-add-d") 768}; 769 770 771class LDebugBreak final : public LTemplateInstruction<0, 0, 0> { 772 public: 773 DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break") 774}; 775 776 777class LCompareNumericAndBranch final : public LControlInstruction<2, 0> { 778 public: 779 LCompareNumericAndBranch(LOperand* left, LOperand* right) { 780 inputs_[0] = left; 781 inputs_[1] = right; 782 } 783 784 LOperand* left() { return inputs_[0]; } 785 LOperand* right() { return inputs_[1]; } 786 787 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch, 788 "compare-numeric-and-branch") 789 DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch) 790 791 Token::Value op() const { return hydrogen()->token(); } 792 bool is_double() const { 793 return hydrogen()->representation().IsDouble(); 794 } 795 796 void PrintDataTo(StringStream* stream) override; 797}; 798 799 800class LMathFloor final : public LTemplateInstruction<1, 1, 1> { 801 public: 802 LMathFloor(LOperand* value, LOperand* temp) { 803 inputs_[0] = value; 804 temps_[0] = temp; 805 } 806 807 LOperand* value() { return inputs_[0]; } 808 LOperand* temp() { return temps_[0]; } 809 810 DECLARE_CONCRETE_INSTRUCTION(MathFloor, "math-floor") 811 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation) 812}; 813 814 815class LMathRound final : public LTemplateInstruction<1, 1, 1> { 816 public: 817 LMathRound(LOperand* value, LOperand* temp) { 818 inputs_[0] = value; 819 temps_[0] = temp; 820 } 821 822 LOperand* value() { return inputs_[0]; } 823 LOperand* temp() { return temps_[0]; } 824 825 DECLARE_CONCRETE_INSTRUCTION(MathRound, "math-round") 826 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation) 827}; 828 829 830class LMathFround final : public LTemplateInstruction<1, 1, 0> { 831 public: 832 explicit LMathFround(LOperand* value) { inputs_[0] = value; } 833 834 LOperand* value() { return inputs_[0]; } 835 836 DECLARE_CONCRETE_INSTRUCTION(MathFround, "math-fround") 837}; 838 839 840class LMathAbs final : public LTemplateInstruction<1, 2, 0> { 841 public: 842 LMathAbs(LOperand* context, LOperand* value) { 843 inputs_[1] = context; 844 inputs_[0] = value; 845 } 846 847 LOperand* context() { return inputs_[1]; } 848 LOperand* value() { return inputs_[0]; } 849 850 DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs") 851 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation) 852}; 853 854 855class LMathLog final : public LTemplateInstruction<1, 1, 0> { 856 public: 857 explicit LMathLog(LOperand* value) { 858 inputs_[0] = value; 859 } 860 861 LOperand* value() { return inputs_[0]; } 862 863 DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log") 864}; 865 866 867class LMathClz32 final : public LTemplateInstruction<1, 1, 0> { 868 public: 869 explicit LMathClz32(LOperand* value) { 870 inputs_[0] = value; 871 } 872 873 LOperand* value() { return inputs_[0]; } 874 875 DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32") 876}; 877 878class LMathCos final : public LTemplateInstruction<1, 1, 0> { 879 public: 880 explicit LMathCos(LOperand* value) { inputs_[0] = value; } 881 882 LOperand* value() { return inputs_[0]; } 883 884 DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos") 885}; 886 887class LMathSin final : public LTemplateInstruction<1, 1, 0> { 888 public: 889 explicit LMathSin(LOperand* value) { inputs_[0] = value; } 890 891 LOperand* value() { return inputs_[0]; } 892 893 DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin") 894}; 895 896class LMathExp final : public LTemplateInstruction<1, 1, 0> { 897 public: 898 explicit LMathExp(LOperand* value) { inputs_[0] = value; } 899 900 LOperand* value() { return inputs_[0]; } 901 902 DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp") 903}; 904 905 906class LMathSqrt final : public LTemplateInstruction<1, 1, 0> { 907 public: 908 explicit LMathSqrt(LOperand* value) { 909 inputs_[0] = value; 910 } 911 912 LOperand* value() { return inputs_[0]; } 913 914 DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt") 915}; 916 917 918class LMathPowHalf final : public LTemplateInstruction<1, 1, 1> { 919 public: 920 LMathPowHalf(LOperand* value, LOperand* temp) { 921 inputs_[0] = value; 922 temps_[0] = temp; 923 } 924 925 LOperand* value() { return inputs_[0]; } 926 LOperand* temp() { return temps_[0]; } 927 928 DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half") 929}; 930 931 932class LCmpObjectEqAndBranch final : public LControlInstruction<2, 0> { 933 public: 934 LCmpObjectEqAndBranch(LOperand* left, LOperand* right) { 935 inputs_[0] = left; 936 inputs_[1] = right; 937 } 938 939 LOperand* left() { return inputs_[0]; } 940 LOperand* right() { return inputs_[1]; } 941 942 DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch") 943 DECLARE_HYDROGEN_ACCESSOR(CompareObjectEqAndBranch) 944}; 945 946 947class LCmpHoleAndBranch final : public LControlInstruction<1, 0> { 948 public: 949 explicit LCmpHoleAndBranch(LOperand* object) { 950 inputs_[0] = object; 951 } 952 953 LOperand* object() { return inputs_[0]; } 954 955 DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranch, "cmp-hole-and-branch") 956 DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch) 957}; 958 959 960class LIsStringAndBranch final : public LControlInstruction<1, 1> { 961 public: 962 LIsStringAndBranch(LOperand* value, LOperand* temp) { 963 inputs_[0] = value; 964 temps_[0] = temp; 965 } 966 967 LOperand* value() { return inputs_[0]; } 968 LOperand* temp() { return temps_[0]; } 969 970 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch") 971 DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch) 972 973 void PrintDataTo(StringStream* stream) override; 974}; 975 976 977class LIsSmiAndBranch final : public LControlInstruction<1, 0> { 978 public: 979 explicit LIsSmiAndBranch(LOperand* value) { 980 inputs_[0] = value; 981 } 982 983 LOperand* value() { return inputs_[0]; } 984 985 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch") 986 DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch) 987 988 void PrintDataTo(StringStream* stream) override; 989}; 990 991 992class LIsUndetectableAndBranch final : public LControlInstruction<1, 1> { 993 public: 994 explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) { 995 inputs_[0] = value; 996 temps_[0] = temp; 997 } 998 999 LOperand* value() { return inputs_[0]; } 1000 LOperand* temp() { return temps_[0]; } 1001 1002 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch, 1003 "is-undetectable-and-branch") 1004 DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch) 1005 1006 void PrintDataTo(StringStream* stream) override; 1007}; 1008 1009 1010class LStringCompareAndBranch final : public LControlInstruction<3, 0> { 1011 public: 1012 LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) { 1013 inputs_[0] = context; 1014 inputs_[1] = left; 1015 inputs_[2] = right; 1016 } 1017 1018 LOperand* context() { return inputs_[0]; } 1019 LOperand* left() { return inputs_[1]; } 1020 LOperand* right() { return inputs_[2]; } 1021 1022 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch, 1023 "string-compare-and-branch") 1024 DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch) 1025 1026 Token::Value op() const { return hydrogen()->token(); } 1027 1028 void PrintDataTo(StringStream* stream) override; 1029}; 1030 1031 1032class LHasInstanceTypeAndBranch final : public LControlInstruction<1, 0> { 1033 public: 1034 explicit LHasInstanceTypeAndBranch(LOperand* value) { 1035 inputs_[0] = value; 1036 } 1037 1038 LOperand* value() { return inputs_[0]; } 1039 1040 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch, 1041 "has-instance-type-and-branch") 1042 DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch) 1043 1044 void PrintDataTo(StringStream* stream) override; 1045}; 1046 1047class LClassOfTestAndBranch final : public LControlInstruction<1, 1> { 1048 public: 1049 LClassOfTestAndBranch(LOperand* value, LOperand* temp) { 1050 inputs_[0] = value; 1051 temps_[0] = temp; 1052 } 1053 1054 LOperand* value() { return inputs_[0]; } 1055 LOperand* temp() { return temps_[0]; } 1056 1057 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch, 1058 "class-of-test-and-branch") 1059 DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch) 1060 1061 void PrintDataTo(StringStream* stream) override; 1062}; 1063 1064 1065class LCmpT final : public LTemplateInstruction<1, 3, 0> { 1066 public: 1067 LCmpT(LOperand* context, LOperand* left, LOperand* right) { 1068 inputs_[0] = context; 1069 inputs_[1] = left; 1070 inputs_[2] = right; 1071 } 1072 1073 LOperand* context() { return inputs_[0]; } 1074 LOperand* left() { return inputs_[1]; } 1075 LOperand* right() { return inputs_[2]; } 1076 1077 DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t") 1078 DECLARE_HYDROGEN_ACCESSOR(CompareGeneric) 1079 1080 Token::Value op() const { return hydrogen()->token(); } 1081}; 1082 1083 1084class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 0> { 1085 public: 1086 LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype) { 1087 inputs_[0] = object; 1088 inputs_[1] = prototype; 1089 } 1090 1091 LOperand* object() const { return inputs_[0]; } 1092 LOperand* prototype() const { return inputs_[1]; } 1093 1094 DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch, 1095 "has-in-prototype-chain-and-branch") 1096 DECLARE_HYDROGEN_ACCESSOR(HasInPrototypeChainAndBranch) 1097}; 1098 1099 1100class LBoundsCheck final : public LTemplateInstruction<0, 2, 0> { 1101 public: 1102 LBoundsCheck(LOperand* index, LOperand* length) { 1103 inputs_[0] = index; 1104 inputs_[1] = length; 1105 } 1106 1107 LOperand* index() { return inputs_[0]; } 1108 LOperand* length() { return inputs_[1]; } 1109 1110 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check") 1111 DECLARE_HYDROGEN_ACCESSOR(BoundsCheck) 1112}; 1113 1114 1115class LBitI final : public LTemplateInstruction<1, 2, 0> { 1116 public: 1117 LBitI(LOperand* left, LOperand* right) { 1118 inputs_[0] = left; 1119 inputs_[1] = right; 1120 } 1121 1122 LOperand* left() { return inputs_[0]; } 1123 LOperand* right() { return inputs_[1]; } 1124 1125 Token::Value op() const { return hydrogen()->op(); } 1126 1127 DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i") 1128 DECLARE_HYDROGEN_ACCESSOR(Bitwise) 1129}; 1130 1131 1132class LShiftI final : public LTemplateInstruction<1, 2, 0> { 1133 public: 1134 LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt) 1135 : op_(op), can_deopt_(can_deopt) { 1136 inputs_[0] = left; 1137 inputs_[1] = right; 1138 } 1139 1140 Token::Value op() const { return op_; } 1141 LOperand* left() { return inputs_[0]; } 1142 LOperand* right() { return inputs_[1]; } 1143 bool can_deopt() const { return can_deopt_; } 1144 1145 DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i") 1146 1147 private: 1148 Token::Value op_; 1149 bool can_deopt_; 1150}; 1151 1152 1153class LSubI final : public LTemplateInstruction<1, 2, 0> { 1154 public: 1155 LSubI(LOperand* left, LOperand* right) { 1156 inputs_[0] = left; 1157 inputs_[1] = right; 1158 } 1159 1160 LOperand* left() { return inputs_[0]; } 1161 LOperand* right() { return inputs_[1]; } 1162 1163 DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i") 1164 DECLARE_HYDROGEN_ACCESSOR(Sub) 1165}; 1166 1167 1168class LConstantI final : public LTemplateInstruction<1, 0, 0> { 1169 public: 1170 DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i") 1171 DECLARE_HYDROGEN_ACCESSOR(Constant) 1172 1173 int32_t value() const { return hydrogen()->Integer32Value(); } 1174}; 1175 1176 1177class LConstantS final : public LTemplateInstruction<1, 0, 0> { 1178 public: 1179 DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s") 1180 DECLARE_HYDROGEN_ACCESSOR(Constant) 1181 1182 Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); } 1183}; 1184 1185 1186class LConstantD final : public LTemplateInstruction<1, 0, 0> { 1187 public: 1188 DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d") 1189 DECLARE_HYDROGEN_ACCESSOR(Constant) 1190 1191 double value() const { return hydrogen()->DoubleValue(); } 1192 uint64_t bits() const { return hydrogen()->DoubleValueAsBits(); } 1193}; 1194 1195 1196class LConstantE final : public LTemplateInstruction<1, 0, 0> { 1197 public: 1198 DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e") 1199 DECLARE_HYDROGEN_ACCESSOR(Constant) 1200 1201 ExternalReference value() const { 1202 return hydrogen()->ExternalReferenceValue(); 1203 } 1204}; 1205 1206 1207class LConstantT final : public LTemplateInstruction<1, 0, 0> { 1208 public: 1209 DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t") 1210 DECLARE_HYDROGEN_ACCESSOR(Constant) 1211 1212 Handle<Object> value(Isolate* isolate) const { 1213 return hydrogen()->handle(isolate); 1214 } 1215}; 1216 1217 1218class LBranch final : public LControlInstruction<1, 0> { 1219 public: 1220 explicit LBranch(LOperand* value) { 1221 inputs_[0] = value; 1222 } 1223 1224 LOperand* value() { return inputs_[0]; } 1225 1226 DECLARE_CONCRETE_INSTRUCTION(Branch, "branch") 1227 DECLARE_HYDROGEN_ACCESSOR(Branch) 1228 1229 void PrintDataTo(StringStream* stream) override; 1230}; 1231 1232 1233class LCmpMapAndBranch final : public LControlInstruction<1, 1> { 1234 public: 1235 LCmpMapAndBranch(LOperand* value, LOperand* temp) { 1236 inputs_[0] = value; 1237 temps_[0] = temp; 1238 } 1239 1240 LOperand* value() { return inputs_[0]; } 1241 LOperand* temp() { return temps_[0]; } 1242 1243 DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch") 1244 DECLARE_HYDROGEN_ACCESSOR(CompareMap) 1245 1246 Handle<Map> map() const { return hydrogen()->map().handle(); } 1247}; 1248 1249 1250class LSeqStringGetChar final : public LTemplateInstruction<1, 2, 0> { 1251 public: 1252 LSeqStringGetChar(LOperand* string, LOperand* index) { 1253 inputs_[0] = string; 1254 inputs_[1] = index; 1255 } 1256 1257 LOperand* string() const { return inputs_[0]; } 1258 LOperand* index() const { return inputs_[1]; } 1259 1260 DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char") 1261 DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar) 1262}; 1263 1264 1265class LSeqStringSetChar final : public LTemplateInstruction<1, 4, 0> { 1266 public: 1267 LSeqStringSetChar(LOperand* context, 1268 LOperand* string, 1269 LOperand* index, 1270 LOperand* value) { 1271 inputs_[0] = context; 1272 inputs_[1] = string; 1273 inputs_[2] = index; 1274 inputs_[3] = value; 1275 } 1276 1277 LOperand* string() { return inputs_[1]; } 1278 LOperand* index() { return inputs_[2]; } 1279 LOperand* value() { return inputs_[3]; } 1280 1281 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char") 1282 DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar) 1283}; 1284 1285 1286class LAddI final : public LTemplateInstruction<1, 2, 0> { 1287 public: 1288 LAddI(LOperand* left, LOperand* right) { 1289 inputs_[0] = left; 1290 inputs_[1] = right; 1291 } 1292 1293 LOperand* left() { return inputs_[0]; } 1294 LOperand* right() { return inputs_[1]; } 1295 1296 DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i") 1297 DECLARE_HYDROGEN_ACCESSOR(Add) 1298}; 1299 1300 1301class LMathMinMax final : public LTemplateInstruction<1, 2, 0> { 1302 public: 1303 LMathMinMax(LOperand* left, LOperand* right) { 1304 inputs_[0] = left; 1305 inputs_[1] = right; 1306 } 1307 1308 LOperand* left() { return inputs_[0]; } 1309 LOperand* right() { return inputs_[1]; } 1310 1311 DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max") 1312 DECLARE_HYDROGEN_ACCESSOR(MathMinMax) 1313}; 1314 1315 1316class LPower final : public LTemplateInstruction<1, 2, 0> { 1317 public: 1318 LPower(LOperand* left, LOperand* right) { 1319 inputs_[0] = left; 1320 inputs_[1] = right; 1321 } 1322 1323 LOperand* left() { return inputs_[0]; } 1324 LOperand* right() { return inputs_[1]; } 1325 1326 DECLARE_CONCRETE_INSTRUCTION(Power, "power") 1327 DECLARE_HYDROGEN_ACCESSOR(Power) 1328}; 1329 1330 1331class LArithmeticD final : public LTemplateInstruction<1, 2, 0> { 1332 public: 1333 LArithmeticD(Token::Value op, LOperand* left, LOperand* right) 1334 : op_(op) { 1335 inputs_[0] = left; 1336 inputs_[1] = right; 1337 } 1338 1339 Token::Value op() const { return op_; } 1340 LOperand* left() { return inputs_[0]; } 1341 LOperand* right() { return inputs_[1]; } 1342 1343 Opcode opcode() const override { return LInstruction::kArithmeticD; } 1344 void CompileToNative(LCodeGen* generator) override; 1345 const char* Mnemonic() const override; 1346 1347 private: 1348 Token::Value op_; 1349}; 1350 1351 1352class LArithmeticT final : public LTemplateInstruction<1, 3, 0> { 1353 public: 1354 LArithmeticT(Token::Value op, 1355 LOperand* context, 1356 LOperand* left, 1357 LOperand* right) 1358 : op_(op) { 1359 inputs_[0] = context; 1360 inputs_[1] = left; 1361 inputs_[2] = right; 1362 } 1363 1364 LOperand* context() { return inputs_[0]; } 1365 LOperand* left() { return inputs_[1]; } 1366 LOperand* right() { return inputs_[2]; } 1367 Token::Value op() const { return op_; } 1368 1369 Opcode opcode() const final { return LInstruction::kArithmeticT; } 1370 void CompileToNative(LCodeGen* generator) override; 1371 const char* Mnemonic() const override; 1372 1373 DECLARE_HYDROGEN_ACCESSOR(BinaryOperation) 1374 1375 private: 1376 Token::Value op_; 1377}; 1378 1379 1380class LReturn final : public LTemplateInstruction<0, 3, 0> { 1381 public: 1382 LReturn(LOperand* value, LOperand* context, LOperand* parameter_count) { 1383 inputs_[0] = value; 1384 inputs_[1] = context; 1385 inputs_[2] = parameter_count; 1386 } 1387 1388 LOperand* value() { return inputs_[0]; } 1389 1390 bool has_constant_parameter_count() { 1391 return parameter_count()->IsConstantOperand(); 1392 } 1393 LConstantOperand* constant_parameter_count() { 1394 DCHECK(has_constant_parameter_count()); 1395 return LConstantOperand::cast(parameter_count()); 1396 } 1397 LOperand* parameter_count() { return inputs_[2]; } 1398 1399 DECLARE_CONCRETE_INSTRUCTION(Return, "return") 1400}; 1401 1402 1403class LLoadNamedField final : public LTemplateInstruction<1, 1, 0> { 1404 public: 1405 explicit LLoadNamedField(LOperand* object) { 1406 inputs_[0] = object; 1407 } 1408 1409 LOperand* object() { return inputs_[0]; } 1410 1411 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field") 1412 DECLARE_HYDROGEN_ACCESSOR(LoadNamedField) 1413}; 1414 1415 1416class LLoadFunctionPrototype final : public LTemplateInstruction<1, 1, 0> { 1417 public: 1418 explicit LLoadFunctionPrototype(LOperand* function) { 1419 inputs_[0] = function; 1420 } 1421 1422 LOperand* function() { return inputs_[0]; } 1423 1424 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype") 1425 DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype) 1426}; 1427 1428 1429class LLoadRoot final : public LTemplateInstruction<1, 0, 0> { 1430 public: 1431 DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root") 1432 DECLARE_HYDROGEN_ACCESSOR(LoadRoot) 1433 1434 Heap::RootListIndex index() const { return hydrogen()->index(); } 1435}; 1436 1437 1438class LLoadKeyed final : public LTemplateInstruction<1, 3, 0> { 1439 public: 1440 LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) { 1441 inputs_[0] = elements; 1442 inputs_[1] = key; 1443 inputs_[2] = backing_store_owner; 1444 } 1445 1446 LOperand* elements() { return inputs_[0]; } 1447 LOperand* key() { return inputs_[1]; } 1448 LOperand* backing_store_owner() { return inputs_[2]; } 1449 ElementsKind elements_kind() const { 1450 return hydrogen()->elements_kind(); 1451 } 1452 bool is_fixed_typed_array() const { 1453 return hydrogen()->is_fixed_typed_array(); 1454 } 1455 1456 DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed") 1457 DECLARE_HYDROGEN_ACCESSOR(LoadKeyed) 1458 1459 void PrintDataTo(StringStream* stream) override; 1460 uint32_t base_offset() const { return hydrogen()->base_offset(); } 1461}; 1462 1463 1464class LLoadContextSlot final : public LTemplateInstruction<1, 1, 0> { 1465 public: 1466 explicit LLoadContextSlot(LOperand* context) { 1467 inputs_[0] = context; 1468 } 1469 1470 LOperand* context() { return inputs_[0]; } 1471 1472 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot") 1473 DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot) 1474 1475 int slot_index() { return hydrogen()->slot_index(); } 1476 1477 void PrintDataTo(StringStream* stream) override; 1478}; 1479 1480 1481class LStoreContextSlot final : public LTemplateInstruction<0, 2, 0> { 1482 public: 1483 LStoreContextSlot(LOperand* context, LOperand* value) { 1484 inputs_[0] = context; 1485 inputs_[1] = value; 1486 } 1487 1488 LOperand* context() { return inputs_[0]; } 1489 LOperand* value() { return inputs_[1]; } 1490 1491 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot") 1492 DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot) 1493 1494 int slot_index() { return hydrogen()->slot_index(); } 1495 1496 void PrintDataTo(StringStream* stream) override; 1497}; 1498 1499 1500class LPushArgument final : public LTemplateInstruction<0, 1, 0> { 1501 public: 1502 explicit LPushArgument(LOperand* value) { 1503 inputs_[0] = value; 1504 } 1505 1506 LOperand* value() { return inputs_[0]; } 1507 1508 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument") 1509}; 1510 1511 1512class LDrop final : public LTemplateInstruction<0, 0, 0> { 1513 public: 1514 explicit LDrop(int count) : count_(count) { } 1515 1516 int count() const { return count_; } 1517 1518 DECLARE_CONCRETE_INSTRUCTION(Drop, "drop") 1519 1520 private: 1521 int count_; 1522}; 1523 1524 1525class LStoreCodeEntry final : public LTemplateInstruction<0, 2, 0> { 1526 public: 1527 LStoreCodeEntry(LOperand* function, LOperand* code_object) { 1528 inputs_[0] = function; 1529 inputs_[1] = code_object; 1530 } 1531 1532 LOperand* function() { return inputs_[0]; } 1533 LOperand* code_object() { return inputs_[1]; } 1534 1535 void PrintDataTo(StringStream* stream) override; 1536 1537 DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry") 1538 DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry) 1539}; 1540 1541 1542class LInnerAllocatedObject final : public LTemplateInstruction<1, 2, 0> { 1543 public: 1544 LInnerAllocatedObject(LOperand* base_object, LOperand* offset) { 1545 inputs_[0] = base_object; 1546 inputs_[1] = offset; 1547 } 1548 1549 LOperand* base_object() const { return inputs_[0]; } 1550 LOperand* offset() const { return inputs_[1]; } 1551 1552 void PrintDataTo(StringStream* stream) override; 1553 1554 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object") 1555}; 1556 1557 1558class LThisFunction final : public LTemplateInstruction<1, 0, 0> { 1559 public: 1560 DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function") 1561 DECLARE_HYDROGEN_ACCESSOR(ThisFunction) 1562}; 1563 1564 1565class LContext final : public LTemplateInstruction<1, 0, 0> { 1566 public: 1567 DECLARE_CONCRETE_INSTRUCTION(Context, "context") 1568 DECLARE_HYDROGEN_ACCESSOR(Context) 1569}; 1570 1571 1572class LDeclareGlobals final : public LTemplateInstruction<0, 1, 0> { 1573 public: 1574 explicit LDeclareGlobals(LOperand* context) { 1575 inputs_[0] = context; 1576 } 1577 1578 LOperand* context() { return inputs_[0]; } 1579 1580 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals") 1581 DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals) 1582}; 1583 1584 1585class LCallWithDescriptor final : public LTemplateResultInstruction<1> { 1586 public: 1587 LCallWithDescriptor(CallInterfaceDescriptor descriptor, 1588 const ZoneList<LOperand*>& operands, Zone* zone) 1589 : descriptor_(descriptor), 1590 inputs_(descriptor.GetRegisterParameterCount() + 1591 kImplicitRegisterParameterCount, 1592 zone) { 1593 DCHECK(descriptor.GetRegisterParameterCount() + 1594 kImplicitRegisterParameterCount == 1595 operands.length()); 1596 inputs_.AddAll(operands, zone); 1597 } 1598 1599 LOperand* target() const { return inputs_[0]; } 1600 1601 const CallInterfaceDescriptor descriptor() { return descriptor_; } 1602 1603 DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor) 1604 1605 // The target and context are passed as implicit parameters that are not 1606 // explicitly listed in the descriptor. 1607 static const int kImplicitRegisterParameterCount = 2; 1608 1609 private: 1610 DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor") 1611 1612 void PrintDataTo(StringStream* stream) override; 1613 1614 int arity() const { return hydrogen()->argument_count() - 1; } 1615 1616 CallInterfaceDescriptor descriptor_; 1617 ZoneList<LOperand*> inputs_; 1618 1619 // Iterator support. 1620 int InputCount() final { return inputs_.length(); } 1621 LOperand* InputAt(int i) final { return inputs_[i]; } 1622 1623 int TempCount() final { return 0; } 1624 LOperand* TempAt(int i) final { return NULL; } 1625}; 1626 1627 1628class LInvokeFunction final : public LTemplateInstruction<1, 2, 0> { 1629 public: 1630 LInvokeFunction(LOperand* context, LOperand* function) { 1631 inputs_[0] = context; 1632 inputs_[1] = function; 1633 } 1634 1635 LOperand* context() { return inputs_[0]; } 1636 LOperand* function() { return inputs_[1]; } 1637 1638 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function") 1639 DECLARE_HYDROGEN_ACCESSOR(InvokeFunction) 1640 1641 void PrintDataTo(StringStream* stream) override; 1642 1643 int arity() const { return hydrogen()->argument_count() - 1; } 1644}; 1645 1646 1647class LCallNewArray final : public LTemplateInstruction<1, 2, 0> { 1648 public: 1649 LCallNewArray(LOperand* context, LOperand* constructor) { 1650 inputs_[0] = context; 1651 inputs_[1] = constructor; 1652 } 1653 1654 LOperand* context() { return inputs_[0]; } 1655 LOperand* constructor() { return inputs_[1]; } 1656 1657 DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array") 1658 DECLARE_HYDROGEN_ACCESSOR(CallNewArray) 1659 1660 void PrintDataTo(StringStream* stream) override; 1661 1662 int arity() const { return hydrogen()->argument_count() - 1; } 1663}; 1664 1665 1666class LCallRuntime final : public LTemplateInstruction<1, 1, 0> { 1667 public: 1668 explicit LCallRuntime(LOperand* context) { 1669 inputs_[0] = context; 1670 } 1671 1672 LOperand* context() { return inputs_[0]; } 1673 1674 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime") 1675 DECLARE_HYDROGEN_ACCESSOR(CallRuntime) 1676 1677 bool ClobbersDoubleRegisters(Isolate* isolate) const override { 1678 return save_doubles() == kDontSaveFPRegs; 1679 } 1680 1681 const Runtime::Function* function() const { return hydrogen()->function(); } 1682 int arity() const { return hydrogen()->argument_count(); } 1683 SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); } 1684}; 1685 1686 1687class LInteger32ToDouble final : public LTemplateInstruction<1, 1, 0> { 1688 public: 1689 explicit LInteger32ToDouble(LOperand* value) { 1690 inputs_[0] = value; 1691 } 1692 1693 LOperand* value() { return inputs_[0]; } 1694 1695 DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double") 1696}; 1697 1698 1699class LUint32ToDouble final : public LTemplateInstruction<1, 1, 0> { 1700 public: 1701 explicit LUint32ToDouble(LOperand* value) { 1702 inputs_[0] = value; 1703 } 1704 1705 LOperand* value() { return inputs_[0]; } 1706 1707 DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double") 1708}; 1709 1710 1711class LNumberTagI final : public LTemplateInstruction<1, 1, 2> { 1712 public: 1713 LNumberTagI(LOperand* value, LOperand* temp1, LOperand* temp2) { 1714 inputs_[0] = value; 1715 temps_[0] = temp1; 1716 temps_[1] = temp2; 1717 } 1718 1719 LOperand* value() { return inputs_[0]; } 1720 LOperand* temp1() { return temps_[0]; } 1721 LOperand* temp2() { return temps_[1]; } 1722 1723 DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i") 1724}; 1725 1726 1727class LNumberTagU final : public LTemplateInstruction<1, 1, 2> { 1728 public: 1729 LNumberTagU(LOperand* value, LOperand* temp1, LOperand* temp2) { 1730 inputs_[0] = value; 1731 temps_[0] = temp1; 1732 temps_[1] = temp2; 1733 } 1734 1735 LOperand* value() { return inputs_[0]; } 1736 LOperand* temp1() { return temps_[0]; } 1737 LOperand* temp2() { return temps_[1]; } 1738 1739 DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u") 1740}; 1741 1742 1743class LNumberTagD final : public LTemplateInstruction<1, 1, 2> { 1744 public: 1745 LNumberTagD(LOperand* value, LOperand* temp, LOperand* temp2) { 1746 inputs_[0] = value; 1747 temps_[0] = temp; 1748 temps_[1] = temp2; 1749 } 1750 1751 LOperand* value() { return inputs_[0]; } 1752 LOperand* temp() { return temps_[0]; } 1753 LOperand* temp2() { return temps_[1]; } 1754 1755 DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d") 1756 DECLARE_HYDROGEN_ACCESSOR(Change) 1757}; 1758 1759 1760class LDoubleToSmi final : public LTemplateInstruction<1, 1, 0> { 1761 public: 1762 explicit LDoubleToSmi(LOperand* value) { 1763 inputs_[0] = value; 1764 } 1765 1766 LOperand* value() { return inputs_[0]; } 1767 1768 DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi") 1769 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) 1770 1771 bool truncating() { return hydrogen()->CanTruncateToInt32(); } 1772}; 1773 1774 1775// Sometimes truncating conversion from a tagged value to an int32. 1776class LDoubleToI final : public LTemplateInstruction<1, 1, 0> { 1777 public: 1778 explicit LDoubleToI(LOperand* value) { 1779 inputs_[0] = value; 1780 } 1781 1782 LOperand* value() { return inputs_[0]; } 1783 1784 DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i") 1785 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) 1786 1787 bool truncating() { return hydrogen()->CanTruncateToInt32(); } 1788}; 1789 1790 1791// Truncating conversion from a tagged value to an int32. 1792class LTaggedToI final : public LTemplateInstruction<1, 1, 2> { 1793 public: 1794 LTaggedToI(LOperand* value, 1795 LOperand* temp, 1796 LOperand* temp2) { 1797 inputs_[0] = value; 1798 temps_[0] = temp; 1799 temps_[1] = temp2; 1800 } 1801 1802 LOperand* value() { return inputs_[0]; } 1803 LOperand* temp() { return temps_[0]; } 1804 LOperand* temp2() { return temps_[1]; } 1805 1806 DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i") 1807 DECLARE_HYDROGEN_ACCESSOR(Change) 1808 1809 bool truncating() { return hydrogen()->CanTruncateToInt32(); } 1810}; 1811 1812 1813class LSmiTag final : public LTemplateInstruction<1, 1, 0> { 1814 public: 1815 explicit LSmiTag(LOperand* value) { 1816 inputs_[0] = value; 1817 } 1818 1819 LOperand* value() { return inputs_[0]; } 1820 1821 DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag") 1822 DECLARE_HYDROGEN_ACCESSOR(Change) 1823}; 1824 1825 1826class LNumberUntagD final : public LTemplateInstruction<1, 1, 0> { 1827 public: 1828 explicit LNumberUntagD(LOperand* value) { 1829 inputs_[0] = value; 1830 } 1831 1832 LOperand* value() { return inputs_[0]; } 1833 1834 DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag") 1835 DECLARE_HYDROGEN_ACCESSOR(Change) 1836 1837 bool truncating() { return hydrogen()->CanTruncateToNumber(); } 1838}; 1839 1840 1841class LSmiUntag final : public LTemplateInstruction<1, 1, 0> { 1842 public: 1843 LSmiUntag(LOperand* value, bool needs_check) 1844 : needs_check_(needs_check) { 1845 inputs_[0] = value; 1846 } 1847 1848 LOperand* value() { return inputs_[0]; } 1849 bool needs_check() const { return needs_check_; } 1850 1851 DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag") 1852 1853 private: 1854 bool needs_check_; 1855}; 1856 1857 1858class LStoreNamedField final : public LTemplateInstruction<0, 2, 1> { 1859 public: 1860 LStoreNamedField(LOperand* object, LOperand* value, LOperand* temp) { 1861 inputs_[0] = object; 1862 inputs_[1] = value; 1863 temps_[0] = temp; 1864 } 1865 1866 LOperand* object() { return inputs_[0]; } 1867 LOperand* value() { return inputs_[1]; } 1868 LOperand* temp() { return temps_[0]; } 1869 1870 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field") 1871 DECLARE_HYDROGEN_ACCESSOR(StoreNamedField) 1872 1873 void PrintDataTo(StringStream* stream) override; 1874 1875 Representation representation() const { 1876 return hydrogen()->field_representation(); 1877 } 1878}; 1879 1880 1881class LStoreKeyed final : public LTemplateInstruction<0, 4, 0> { 1882 public: 1883 LStoreKeyed(LOperand* object, LOperand* key, LOperand* value, 1884 LOperand* backing_store_owner) { 1885 inputs_[0] = object; 1886 inputs_[1] = key; 1887 inputs_[2] = value; 1888 inputs_[3] = backing_store_owner; 1889 } 1890 1891 bool is_fixed_typed_array() const { 1892 return hydrogen()->is_fixed_typed_array(); 1893 } 1894 LOperand* elements() { return inputs_[0]; } 1895 LOperand* key() { return inputs_[1]; } 1896 LOperand* value() { return inputs_[2]; } 1897 LOperand* backing_store_owner() { return inputs_[3]; } 1898 ElementsKind elements_kind() const { 1899 return hydrogen()->elements_kind(); 1900 } 1901 1902 DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed") 1903 DECLARE_HYDROGEN_ACCESSOR(StoreKeyed) 1904 1905 void PrintDataTo(StringStream* stream) override; 1906 bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); } 1907 uint32_t base_offset() const { return hydrogen()->base_offset(); } 1908}; 1909 1910 1911class LTransitionElementsKind final : public LTemplateInstruction<0, 2, 1> { 1912 public: 1913 LTransitionElementsKind(LOperand* object, 1914 LOperand* context, 1915 LOperand* new_map_temp) { 1916 inputs_[0] = object; 1917 inputs_[1] = context; 1918 temps_[0] = new_map_temp; 1919 } 1920 1921 LOperand* context() { return inputs_[1]; } 1922 LOperand* object() { return inputs_[0]; } 1923 LOperand* new_map_temp() { return temps_[0]; } 1924 1925 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind, 1926 "transition-elements-kind") 1927 DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind) 1928 1929 void PrintDataTo(StringStream* stream) override; 1930 1931 Handle<Map> original_map() { return hydrogen()->original_map().handle(); } 1932 Handle<Map> transitioned_map() { 1933 return hydrogen()->transitioned_map().handle(); 1934 } 1935 ElementsKind from_kind() { return hydrogen()->from_kind(); } 1936 ElementsKind to_kind() { return hydrogen()->to_kind(); } 1937}; 1938 1939 1940class LTrapAllocationMemento final : public LTemplateInstruction<0, 1, 1> { 1941 public: 1942 LTrapAllocationMemento(LOperand* object, 1943 LOperand* temp) { 1944 inputs_[0] = object; 1945 temps_[0] = temp; 1946 } 1947 1948 LOperand* object() { return inputs_[0]; } 1949 LOperand* temp() { return temps_[0]; } 1950 1951 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento, 1952 "trap-allocation-memento") 1953}; 1954 1955 1956class LMaybeGrowElements final : public LTemplateInstruction<1, 5, 0> { 1957 public: 1958 LMaybeGrowElements(LOperand* context, LOperand* object, LOperand* elements, 1959 LOperand* key, LOperand* current_capacity) { 1960 inputs_[0] = context; 1961 inputs_[1] = object; 1962 inputs_[2] = elements; 1963 inputs_[3] = key; 1964 inputs_[4] = current_capacity; 1965 } 1966 1967 LOperand* context() { return inputs_[0]; } 1968 LOperand* object() { return inputs_[1]; } 1969 LOperand* elements() { return inputs_[2]; } 1970 LOperand* key() { return inputs_[3]; } 1971 LOperand* current_capacity() { return inputs_[4]; } 1972 1973 bool ClobbersDoubleRegisters(Isolate* isolate) const override { return true; } 1974 1975 DECLARE_HYDROGEN_ACCESSOR(MaybeGrowElements) 1976 DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements, "maybe-grow-elements") 1977}; 1978 1979 1980class LStringAdd final : public LTemplateInstruction<1, 3, 0> { 1981 public: 1982 LStringAdd(LOperand* context, LOperand* left, LOperand* right) { 1983 inputs_[0] = context; 1984 inputs_[1] = left; 1985 inputs_[2] = right; 1986 } 1987 1988 LOperand* context() { return inputs_[0]; } 1989 LOperand* left() { return inputs_[1]; } 1990 LOperand* right() { return inputs_[2]; } 1991 1992 DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add") 1993 DECLARE_HYDROGEN_ACCESSOR(StringAdd) 1994}; 1995 1996 1997class LStringCharCodeAt final : public LTemplateInstruction<1, 3, 0> { 1998 public: 1999 LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) { 2000 inputs_[0] = context; 2001 inputs_[1] = string; 2002 inputs_[2] = index; 2003 } 2004 2005 LOperand* context() { return inputs_[0]; } 2006 LOperand* string() { return inputs_[1]; } 2007 LOperand* index() { return inputs_[2]; } 2008 2009 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at") 2010 DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt) 2011}; 2012 2013 2014class LStringCharFromCode final : public LTemplateInstruction<1, 2, 0> { 2015 public: 2016 explicit LStringCharFromCode(LOperand* context, LOperand* char_code) { 2017 inputs_[0] = context; 2018 inputs_[1] = char_code; 2019 } 2020 2021 LOperand* context() { return inputs_[0]; } 2022 LOperand* char_code() { return inputs_[1]; } 2023 2024 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code") 2025 DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode) 2026}; 2027 2028 2029class LCheckValue final : public LTemplateInstruction<0, 1, 0> { 2030 public: 2031 explicit LCheckValue(LOperand* value) { 2032 inputs_[0] = value; 2033 } 2034 2035 LOperand* value() { return inputs_[0]; } 2036 2037 DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value") 2038 DECLARE_HYDROGEN_ACCESSOR(CheckValue) 2039}; 2040 2041 2042class LCheckArrayBufferNotNeutered final 2043 : public LTemplateInstruction<0, 1, 0> { 2044 public: 2045 explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; } 2046 2047 LOperand* view() { return inputs_[0]; } 2048 2049 DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered, 2050 "check-array-buffer-not-neutered") 2051 DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered) 2052}; 2053 2054 2055class LCheckInstanceType final : public LTemplateInstruction<0, 1, 0> { 2056 public: 2057 explicit LCheckInstanceType(LOperand* value) { 2058 inputs_[0] = value; 2059 } 2060 2061 LOperand* value() { return inputs_[0]; } 2062 2063 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type") 2064 DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType) 2065}; 2066 2067 2068class LCheckMaps final : public LTemplateInstruction<0, 1, 0> { 2069 public: 2070 explicit LCheckMaps(LOperand* value = NULL) { 2071 inputs_[0] = value; 2072 } 2073 2074 LOperand* value() { return inputs_[0]; } 2075 2076 DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps") 2077 DECLARE_HYDROGEN_ACCESSOR(CheckMaps) 2078}; 2079 2080 2081class LCheckSmi final : public LTemplateInstruction<1, 1, 0> { 2082 public: 2083 explicit LCheckSmi(LOperand* value) { 2084 inputs_[0] = value; 2085 } 2086 2087 LOperand* value() { return inputs_[0]; } 2088 2089 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi") 2090}; 2091 2092 2093class LCheckNonSmi final : public LTemplateInstruction<0, 1, 0> { 2094 public: 2095 explicit LCheckNonSmi(LOperand* value) { 2096 inputs_[0] = value; 2097 } 2098 2099 LOperand* value() { return inputs_[0]; } 2100 2101 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi") 2102 DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject) 2103}; 2104 2105 2106class LClampDToUint8 final : public LTemplateInstruction<1, 1, 1> { 2107 public: 2108 LClampDToUint8(LOperand* unclamped, LOperand* temp) { 2109 inputs_[0] = unclamped; 2110 temps_[0] = temp; 2111 } 2112 2113 LOperand* unclamped() { return inputs_[0]; } 2114 LOperand* temp() { return temps_[0]; } 2115 2116 DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8") 2117}; 2118 2119 2120class LClampIToUint8 final : public LTemplateInstruction<1, 1, 0> { 2121 public: 2122 explicit LClampIToUint8(LOperand* unclamped) { 2123 inputs_[0] = unclamped; 2124 } 2125 2126 LOperand* unclamped() { return inputs_[0]; } 2127 2128 DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8") 2129}; 2130 2131 2132class LClampTToUint8 final : public LTemplateInstruction<1, 1, 1> { 2133 public: 2134 LClampTToUint8(LOperand* unclamped, LOperand* temp) { 2135 inputs_[0] = unclamped; 2136 temps_[0] = temp; 2137 } 2138 2139 LOperand* unclamped() { return inputs_[0]; } 2140 LOperand* temp() { return temps_[0]; } 2141 2142 DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8") 2143}; 2144 2145 2146class LAllocate final : public LTemplateInstruction<1, 2, 2> { 2147 public: 2148 LAllocate(LOperand* context, 2149 LOperand* size, 2150 LOperand* temp1, 2151 LOperand* temp2) { 2152 inputs_[0] = context; 2153 inputs_[1] = size; 2154 temps_[0] = temp1; 2155 temps_[1] = temp2; 2156 } 2157 2158 LOperand* context() { return inputs_[0]; } 2159 LOperand* size() { return inputs_[1]; } 2160 LOperand* temp1() { return temps_[0]; } 2161 LOperand* temp2() { return temps_[1]; } 2162 2163 DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate") 2164 DECLARE_HYDROGEN_ACCESSOR(Allocate) 2165}; 2166 2167class LFastAllocate final : public LTemplateInstruction<1, 1, 2> { 2168 public: 2169 LFastAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) { 2170 inputs_[0] = size; 2171 temps_[0] = temp1; 2172 temps_[1] = temp2; 2173 } 2174 2175 LOperand* size() { return inputs_[0]; } 2176 LOperand* temp1() { return temps_[0]; } 2177 LOperand* temp2() { return temps_[1]; } 2178 2179 DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate") 2180 DECLARE_HYDROGEN_ACCESSOR(Allocate) 2181}; 2182 2183class LTypeof final : public LTemplateInstruction<1, 2, 0> { 2184 public: 2185 LTypeof(LOperand* context, LOperand* value) { 2186 inputs_[0] = context; 2187 inputs_[1] = value; 2188 } 2189 2190 LOperand* context() { return inputs_[0]; } 2191 LOperand* value() { return inputs_[1]; } 2192 2193 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof") 2194}; 2195 2196 2197class LTypeofIsAndBranch final : public LControlInstruction<1, 0> { 2198 public: 2199 explicit LTypeofIsAndBranch(LOperand* value) { 2200 inputs_[0] = value; 2201 } 2202 2203 LOperand* value() { return inputs_[0]; } 2204 2205 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch") 2206 DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch) 2207 2208 Handle<String> type_literal() { return hydrogen()->type_literal(); } 2209 2210 void PrintDataTo(StringStream* stream) override; 2211}; 2212 2213 2214class LOsrEntry final : public LTemplateInstruction<0, 0, 0> { 2215 public: 2216 LOsrEntry() {} 2217 2218 bool HasInterestingComment(LCodeGen* gen) const override { return false; } 2219 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry") 2220}; 2221 2222 2223class LStackCheck final : public LTemplateInstruction<0, 1, 0> { 2224 public: 2225 explicit LStackCheck(LOperand* context) { 2226 inputs_[0] = context; 2227 } 2228 2229 LOperand* context() { return inputs_[0]; } 2230 2231 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check") 2232 DECLARE_HYDROGEN_ACCESSOR(StackCheck) 2233 2234 Label* done_label() { return &done_label_; } 2235 2236 private: 2237 Label done_label_; 2238}; 2239 2240 2241class LForInPrepareMap final : public LTemplateInstruction<1, 2, 0> { 2242 public: 2243 LForInPrepareMap(LOperand* context, LOperand* object) { 2244 inputs_[0] = context; 2245 inputs_[1] = object; 2246 } 2247 2248 LOperand* context() { return inputs_[0]; } 2249 LOperand* object() { return inputs_[1]; } 2250 2251 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map") 2252}; 2253 2254 2255class LForInCacheArray final : public LTemplateInstruction<1, 1, 0> { 2256 public: 2257 explicit LForInCacheArray(LOperand* map) { 2258 inputs_[0] = map; 2259 } 2260 2261 LOperand* map() { return inputs_[0]; } 2262 2263 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array") 2264 2265 int idx() { 2266 return HForInCacheArray::cast(this->hydrogen_value())->idx(); 2267 } 2268}; 2269 2270 2271class LCheckMapValue final : public LTemplateInstruction<0, 2, 0> { 2272 public: 2273 LCheckMapValue(LOperand* value, LOperand* map) { 2274 inputs_[0] = value; 2275 inputs_[1] = map; 2276 } 2277 2278 LOperand* value() { return inputs_[0]; } 2279 LOperand* map() { return inputs_[1]; } 2280 2281 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value") 2282}; 2283 2284 2285class LLoadFieldByIndex final : public LTemplateInstruction<1, 2, 0> { 2286 public: 2287 LLoadFieldByIndex(LOperand* object, LOperand* index) { 2288 inputs_[0] = object; 2289 inputs_[1] = index; 2290 } 2291 2292 LOperand* object() { return inputs_[0]; } 2293 LOperand* index() { return inputs_[1]; } 2294 2295 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index") 2296}; 2297 2298 2299class LChunkBuilder; 2300class LPlatformChunk final : public LChunk { 2301 public: 2302 LPlatformChunk(CompilationInfo* info, HGraph* graph) 2303 : LChunk(info, graph) { } 2304 2305 int GetNextSpillIndex(RegisterKind kind); 2306 LOperand* GetNextSpillSlot(RegisterKind kind); 2307}; 2308 2309 2310class LChunkBuilder final : public LChunkBuilderBase { 2311 public: 2312 LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator) 2313 : LChunkBuilderBase(info, graph), 2314 current_instruction_(NULL), 2315 current_block_(NULL), 2316 next_block_(NULL), 2317 allocator_(allocator) {} 2318 2319 // Build the sequence for the graph. 2320 LPlatformChunk* Build(); 2321 2322 // Declare methods that deal with the individual node types. 2323#define DECLARE_DO(type) LInstruction* Do##type(H##type* node); 2324 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) 2325#undef DECLARE_DO 2326 2327 LInstruction* DoMultiplyAdd(HMul* mul, HValue* addend); 2328 2329 static bool HasMagicNumberForDivisor(int32_t divisor); 2330 2331 LInstruction* DoMathFloor(HUnaryMathOperation* instr); 2332 LInstruction* DoMathRound(HUnaryMathOperation* instr); 2333 LInstruction* DoMathFround(HUnaryMathOperation* instr); 2334 LInstruction* DoMathAbs(HUnaryMathOperation* instr); 2335 LInstruction* DoMathLog(HUnaryMathOperation* instr); 2336 LInstruction* DoMathCos(HUnaryMathOperation* instr); 2337 LInstruction* DoMathSin(HUnaryMathOperation* instr); 2338 LInstruction* DoMathExp(HUnaryMathOperation* instr); 2339 LInstruction* DoMathSqrt(HUnaryMathOperation* instr); 2340 LInstruction* DoMathPowHalf(HUnaryMathOperation* instr); 2341 LInstruction* DoMathClz32(HUnaryMathOperation* instr); 2342 LInstruction* DoDivByPowerOf2I(HDiv* instr); 2343 LInstruction* DoDivByConstI(HDiv* instr); 2344 LInstruction* DoDivI(HDiv* instr); 2345 LInstruction* DoModByPowerOf2I(HMod* instr); 2346 LInstruction* DoModByConstI(HMod* instr); 2347 LInstruction* DoModI(HMod* instr); 2348 LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr); 2349 LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr); 2350 LInstruction* DoFlooringDivI(HMathFloorOfDiv* instr); 2351 2352 private: 2353 // Methods for getting operands for Use / Define / Temp. 2354 LUnallocated* ToUnallocated(Register reg); 2355 LUnallocated* ToUnallocated(DoubleRegister reg); 2356 2357 // Methods for setting up define-use relationships. 2358 MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand); 2359 MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register); 2360 MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value, 2361 DoubleRegister fixed_register); 2362 2363 // A value that is guaranteed to be allocated to a register. 2364 // Operand created by UseRegister is guaranteed to be live until the end of 2365 // instruction. This means that register allocator will not reuse it's 2366 // register for any other operand inside instruction. 2367 // Operand created by UseRegisterAtStart is guaranteed to be live only at 2368 // instruction start. Register allocator is free to assign the same register 2369 // to some other operand used inside instruction (i.e. temporary or 2370 // output). 2371 MUST_USE_RESULT LOperand* UseRegister(HValue* value); 2372 MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value); 2373 2374 // An input operand in a register that may be trashed. 2375 MUST_USE_RESULT LOperand* UseTempRegister(HValue* value); 2376 2377 // An input operand in a register or stack slot. 2378 MUST_USE_RESULT LOperand* Use(HValue* value); 2379 MUST_USE_RESULT LOperand* UseAtStart(HValue* value); 2380 2381 // An input operand in a register, stack slot or a constant operand. 2382 MUST_USE_RESULT LOperand* UseOrConstant(HValue* value); 2383 MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value); 2384 2385 // An input operand in a register or a constant operand. 2386 MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value); 2387 MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value); 2388 2389 // An input operand in a constant operand. 2390 MUST_USE_RESULT LOperand* UseConstant(HValue* value); 2391 2392 // An input operand in register, stack slot or a constant operand. 2393 // Will not be moved to a register even if one is freely available. 2394 MUST_USE_RESULT LOperand* UseAny(HValue* value) override; 2395 2396 // Temporary operand that must be in a register. 2397 MUST_USE_RESULT LUnallocated* TempRegister(); 2398 MUST_USE_RESULT LUnallocated* TempDoubleRegister(); 2399 MUST_USE_RESULT LOperand* FixedTemp(Register reg); 2400 MUST_USE_RESULT LOperand* FixedTemp(DoubleRegister reg); 2401 2402 // Methods for setting up define-use relationships. 2403 // Return the same instruction that they are passed. 2404 LInstruction* Define(LTemplateResultInstruction<1>* instr, 2405 LUnallocated* result); 2406 LInstruction* DefineAsRegister(LTemplateResultInstruction<1>* instr); 2407 LInstruction* DefineAsSpilled(LTemplateResultInstruction<1>* instr, 2408 int index); 2409 LInstruction* DefineSameAsFirst(LTemplateResultInstruction<1>* instr); 2410 LInstruction* DefineFixed(LTemplateResultInstruction<1>* instr, 2411 Register reg); 2412 LInstruction* DefineFixedDouble(LTemplateResultInstruction<1>* instr, 2413 DoubleRegister reg); 2414 LInstruction* AssignEnvironment(LInstruction* instr); 2415 LInstruction* AssignPointerMap(LInstruction* instr); 2416 2417 enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY }; 2418 2419 // By default we assume that instruction sequences generated for calls 2420 // cannot deoptimize eagerly and we do not attach environment to this 2421 // instruction. 2422 LInstruction* MarkAsCall( 2423 LInstruction* instr, 2424 HInstruction* hinstr, 2425 CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY); 2426 2427 void VisitInstruction(HInstruction* current); 2428 void AddInstruction(LInstruction* instr, HInstruction* current); 2429 2430 void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block); 2431 LInstruction* DoBit(Token::Value op, HBitwiseBinaryOperation* instr); 2432 LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr); 2433 LInstruction* DoArithmeticD(Token::Value op, 2434 HArithmeticBinaryOperation* instr); 2435 LInstruction* DoArithmeticT(Token::Value op, 2436 HBinaryOperation* instr); 2437 2438 HInstruction* current_instruction_; 2439 HBasicBlock* current_block_; 2440 HBasicBlock* next_block_; 2441 LAllocator* allocator_; 2442 2443 DISALLOW_COPY_AND_ASSIGN(LChunkBuilder); 2444}; 2445 2446#undef DECLARE_HYDROGEN_ACCESSOR 2447#undef DECLARE_CONCRETE_INSTRUCTION 2448 2449} // namespace internal 2450} // namespace v8 2451 2452#endif // V8_CRANKSHAFT_MIPS_LITHIUM_MIPS_H_ 2453