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