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