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