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