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