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