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