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