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