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