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