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