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