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