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