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