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