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