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