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