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