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