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