lithium-x64.h 74.5 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5 6
#ifndef V8_CRANKSHAFT_X64_LITHIUM_X64_H_
#define V8_CRANKSHAFT_X64_LITHIUM_X64_H_
7

8 9 10
#include "src/crankshaft/hydrogen.h"
#include "src/crankshaft/lithium.h"
#include "src/crankshaft/lithium-allocator.h"
11 12
#include "src/safepoint-table.h"
#include "src/utils.h"
13 14 15 16 17 18 19

namespace v8 {
namespace internal {

// Forward declarations.
class LCodeGen;

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
  V(AccessArgumentsAt)                       \
  V(AddI)                                    \
  V(Allocate)                                \
  V(ApplyArguments)                          \
  V(ArgumentsElements)                       \
  V(ArgumentsLength)                         \
  V(ArithmeticD)                             \
  V(ArithmeticT)                             \
  V(BitI)                                    \
  V(BoundsCheck)                             \
  V(Branch)                                  \
  V(CallWithDescriptor)                      \
  V(CallNewArray)                            \
  V(CallRuntime)                             \
35
  V(CheckArrayBufferNotNeutered)             \
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
  V(CheckInstanceType)                       \
  V(CheckMaps)                               \
  V(CheckMapValue)                           \
  V(CheckNonSmi)                             \
  V(CheckSmi)                                \
  V(CheckValue)                              \
  V(ClampDToUint8)                           \
  V(ClampIToUint8)                           \
  V(ClampTToUint8)                           \
  V(ClassOfTestAndBranch)                    \
  V(CompareNumericAndBranch)                 \
  V(CmpObjectEqAndBranch)                    \
  V(CmpHoleAndBranch)                        \
  V(CmpMapAndBranch)                         \
  V(CmpT)                                    \
  V(ConstantD)                               \
  V(ConstantE)                               \
  V(ConstantI)                               \
  V(ConstantS)                               \
  V(ConstantT)                               \
  V(Context)                                 \
  V(DebugBreak)                              \
  V(DeclareGlobals)                          \
  V(Deoptimize)                              \
  V(DivByConstI)                             \
  V(DivByPowerOf2I)                          \
  V(DivI)                                    \
  V(DoubleToI)                               \
  V(DoubleToSmi)                             \
  V(Drop)                                    \
  V(DummyUse)                                \
  V(Dummy)                                   \
68
  V(FastAllocate)                            \
69 70 71 72 73 74 75 76
  V(FlooringDivByConstI)                     \
  V(FlooringDivByPowerOf2I)                  \
  V(FlooringDivI)                            \
  V(ForInCacheArray)                         \
  V(ForInPrepareMap)                         \
  V(GetCachedArrayIndex)                     \
  V(Goto)                                    \
  V(HasCachedArrayIndexAndBranch)            \
77
  V(HasInPrototypeChainAndBranch)            \
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
  V(HasInstanceTypeAndBranch)                \
  V(InnerAllocatedObject)                    \
  V(InstructionGap)                          \
  V(Integer32ToDouble)                       \
  V(InvokeFunction)                          \
  V(IsStringAndBranch)                       \
  V(IsSmiAndBranch)                          \
  V(IsUndetectableAndBranch)                 \
  V(Label)                                   \
  V(LazyBailout)                             \
  V(LoadContextSlot)                         \
  V(LoadRoot)                                \
  V(LoadFieldByIndex)                        \
  V(LoadFunctionPrototype)                   \
  V(LoadGlobalGeneric)                       \
  V(LoadKeyed)                               \
  V(LoadKeyedGeneric)                        \
  V(LoadNamedField)                          \
  V(LoadNamedGeneric)                        \
  V(MathAbs)                                 \
  V(MathClz32)                               \
99
  V(MathCos)                                 \
100
  V(MathExp)                                 \
101 102
  V(MathFloorD)                              \
  V(MathFloorI)                              \
103 104 105 106
  V(MathFround)                              \
  V(MathLog)                                 \
  V(MathMinMax)                              \
  V(MathPowHalf)                             \
107 108
  V(MathRoundD)                              \
  V(MathRoundI)                              \
109
  V(MathSin)                                 \
110
  V(MathSqrt)                                \
111
  V(MaybeGrowElements)                       \
112 113 114 115 116 117 118 119 120 121 122
  V(ModByConstI)                             \
  V(ModByPowerOf2I)                          \
  V(ModI)                                    \
  V(MulI)                                    \
  V(NumberTagD)                              \
  V(NumberTagI)                              \
  V(NumberTagU)                              \
  V(NumberUntagD)                            \
  V(OsrEntry)                                \
  V(Parameter)                               \
  V(Power)                                   \
123
  V(Prologue)                                \
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
  V(PushArgument)                            \
  V(Return)                                  \
  V(SeqStringGetChar)                        \
  V(SeqStringSetChar)                        \
  V(ShiftI)                                  \
  V(SmiTag)                                  \
  V(SmiUntag)                                \
  V(StackCheck)                              \
  V(StoreCodeEntry)                          \
  V(StoreContextSlot)                        \
  V(StoreKeyed)                              \
  V(StoreKeyedGeneric)                       \
  V(StoreNamedField)                         \
  V(StoreNamedGeneric)                       \
  V(StringAdd)                               \
  V(StringCharCodeAt)                        \
  V(StringCharFromCode)                      \
  V(StringCompareAndBranch)                  \
  V(SubI)                                    \
  V(TaggedToI)                               \
  V(ThisFunction)                            \
  V(TransitionElementsKind)                  \
  V(TrapAllocationMemento)                   \
  V(Typeof)                                  \
  V(TypeofIsAndBranch)                       \
  V(Uint32ToDouble)                          \
  V(UnknownOSRValue)                         \
yangguo@chromium.org's avatar
yangguo@chromium.org committed
151
  V(WrapReceiver)
152

153
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)            \
154 155 156
  Opcode opcode() const final { return LInstruction::k##type; } \
  void CompileToNative(LCodeGen* generator) final;              \
  const char* Mnemonic() const final { return mnemonic; }       \
157 158 159
  static L##type* cast(LInstruction* instr) {                   \
    DCHECK(instr->Is##type());                                  \
    return reinterpret_cast<L##type*>(instr);                   \
160 161 162 163 164 165 166 167 168
  }


#define DECLARE_HYDROGEN_ACCESSOR(type)     \
  H##type* hydrogen() const {               \
    return H##type::cast(hydrogen_value()); \
  }


169
class LInstruction : public ZoneObject {
170
 public:
171
  LInstruction()
172 173 174 175
      : environment_(NULL),
        hydrogen_value_(NULL),
        bit_field_(IsCallBits::encode(false)) {
  }
176

177
  virtual ~LInstruction() {}
178

179 180
  virtual void CompileToNative(LCodeGen* generator) = 0;
  virtual const char* Mnemonic() const = 0;
181
  virtual void PrintTo(StringStream* stream);
182 183
  virtual void PrintDataTo(StringStream* stream);
  virtual void PrintOutputOperandTo(StringStream* stream);
184

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
  enum Opcode {
    // Declare a unique enum value for each instruction.
#define DECLARE_OPCODE(type) k##type,
    LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
    kNumberOfInstructions
#undef DECLARE_OPCODE
  };

  virtual Opcode opcode() const = 0;

  // Declare non-virtual type testers for all leaf IR classes.
#define DECLARE_PREDICATE(type) \
  bool Is##type() const { return opcode() == k##type; }
  LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
#undef DECLARE_PREDICATE

  // Declare virtual predicates for instructions that don't have
  // an opcode.
  virtual bool IsGap() const { return false; }
204

205 206
  virtual bool IsControl() const { return false; }

207 208 209
  // Try deleting this instruction if possible.
  virtual bool TryDelete() { return false; }

210 211 212
  void set_environment(LEnvironment* env) { environment_ = env; }
  LEnvironment* environment() const { return environment_; }
  bool HasEnvironment() const { return environment_ != NULL; }
213

214 215 216
  void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
  LPointerMap* pointer_map() const { return pointer_map_.get(); }
  bool HasPointerMap() const { return pointer_map_.is_set(); }
217

218 219 220
  void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
  HValue* hydrogen_value() const { return hydrogen_value_; }

221 222
  void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
  bool IsCall() const { return IsCallBits::decode(bit_field_); }
223

224 225 226 227 228 229 230
  void MarkAsSyntacticTailCall() {
    bit_field_ = IsSyntacticTailCallBits::update(bit_field_, true);
  }
  bool IsSyntacticTailCall() const {
    return IsSyntacticTailCallBits::decode(bit_field_);
  }

231
  // Interface to the register allocator and iterators.
232 233
  bool ClobbersTemps() const { return IsCall(); }
  bool ClobbersRegisters() const { return IsCall(); }
234
  virtual bool ClobbersDoubleRegisters(Isolate* isolate) const {
235 236
    return IsCall();
  }
237

238
  // Interface to the register allocator and iterators.
239
  bool IsMarkedAsCall() const { return IsCall(); }
240 241

  virtual bool HasResult() const = 0;
242
  virtual LOperand* result() const = 0;
243 244 245 246

  LOperand* FirstInput() { return InputAt(0); }
  LOperand* Output() { return HasResult() ? result() : NULL; }

247 248
  virtual bool HasInterestingComment(LCodeGen* gen) const { return true; }

249 250 251 252
  virtual bool MustSignExtendResult(LPlatformChunk* chunk) const {
    return false;
  }

253 254 255 256
#ifdef DEBUG
  void VerifyCall();
#endif

257 258 259
  virtual int InputCount() = 0;
  virtual LOperand* InputAt(int i) = 0;

260
 private:
261 262 263
  // Iterator support.
  friend class InputIterator;

264 265 266 267
  friend class TempIterator;
  virtual int TempCount() = 0;
  virtual LOperand* TempAt(int i) = 0;

268
  class IsCallBits: public BitField<bool, 0, 1> {};
269 270
  class IsSyntacticTailCallBits : public BitField<bool, IsCallBits::kNext, 1> {
  };
271

272
  LEnvironment* environment_;
273 274
  SetOncePointer<LPointerMap> pointer_map_;
  HValue* hydrogen_value_;
275
  int bit_field_;
276 277 278
};


279
// R = number of result operands (0 or 1).
280 281
template<int R>
class LTemplateResultInstruction : public LInstruction {
282
 public:
283 284
  // Allow 0 or 1 output operands.
  STATIC_ASSERT(R == 0 || R == 1);
285
  bool HasResult() const final { return R != 0 && result() != NULL; }
286
  void set_result(LOperand* operand) { results_[0] = operand; }
287
  LOperand* result() const override { return results_[0]; }
288

289
  bool MustSignExtendResult(LPlatformChunk* chunk) const final;
290

291
 protected:
292
  EmbeddedContainer<LOperand*, R> results_;
293 294 295 296 297 298 299 300 301
};


// R = number of result operands (0 or 1).
// I = number of input operands.
// T = number of temporary operands.
template<int R, int I, int T>
class LTemplateInstruction : public LTemplateResultInstruction<R> {
 protected:
302 303
  EmbeddedContainer<LOperand*, I> inputs_;
  EmbeddedContainer<LOperand*, T> temps_;
304 305

 private:
306
  // Iterator support.
307 308
  int InputCount() final { return I; }
  LOperand* InputAt(int i) final { return inputs_[i]; }
309

310 311
  int TempCount() final { return T; }
  LOperand* TempAt(int i) final { return temps_[i]; }
312 313 314
};


315
class LGap : public LTemplateInstruction<0, 0, 0> {
316
 public:
317 318 319 320 321 322
  explicit LGap(HBasicBlock* block)
      : block_(block) {
    parallel_moves_[BEFORE] = NULL;
    parallel_moves_[START] = NULL;
    parallel_moves_[END] = NULL;
    parallel_moves_[AFTER] = NULL;
323 324
  }

325
  // Can't use the DECLARE-macro here because of sub-classes.
326 327
  bool IsGap() const final { return true; }
  void PrintDataTo(StringStream* stream) override;
328
  static LGap* cast(LInstruction* instr) {
329
    DCHECK(instr->IsGap());
330 331
    return reinterpret_cast<LGap*>(instr);
  }
332

333
  bool IsRedundant() const;
334

335
  HBasicBlock* block() const { return block_; }
336 337 338 339 340 341 342 343 344 345

  enum InnerPosition {
    BEFORE,
    START,
    END,
    AFTER,
    FIRST_INNER_POSITION = BEFORE,
    LAST_INNER_POSITION = AFTER
  };

346 347 348 349 350
  LParallelMove* GetOrCreateParallelMove(InnerPosition pos,
                                         Zone* zone)  {
    if (parallel_moves_[pos] == NULL) {
      parallel_moves_[pos] = new(zone) LParallelMove(zone);
    }
351
    return parallel_moves_[pos];
352 353 354
  }

  LParallelMove* GetParallelMove(InnerPosition pos)  {
355
    return parallel_moves_[pos];
356
  }
357 358 359 360

 private:
  LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
  HBasicBlock* block_;
361 362 363
};


364
class LInstructionGap final : public LGap {
365 366 367
 public:
  explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }

368
  bool HasInterestingComment(LCodeGen* gen) const override {
369 370 371
    return !IsRedundant();
  }

372 373 374 375
  DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
};


376
class LGoto final : public LTemplateInstruction<0, 0, 0> {
377
 public:
378
  explicit LGoto(HBasicBlock* block) : block_(block) { }
379

380
  bool HasInterestingComment(LCodeGen* gen) const override;
381
  DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
382 383
  void PrintDataTo(StringStream* stream) override;
  bool IsControl() const override { return true; }
384

385
  int block_id() const { return block_->block_id(); }
386 387

 private:
388
  HBasicBlock* block_;
389 390 391
};


392 393 394 395 396 397
class LPrologue final : public LTemplateInstruction<0, 0, 0> {
 public:
  DECLARE_CONCRETE_INSTRUCTION(Prologue, "prologue")
};


398
class LLazyBailout final : public LTemplateInstruction<0, 0, 0> {
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
 public:
  LLazyBailout() : gap_instructions_size_(0) { }

  DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")

  void set_gap_instructions_size(int gap_instructions_size) {
    gap_instructions_size_ = gap_instructions_size;
  }
  int gap_instructions_size() { return gap_instructions_size_; }

 private:
  int gap_instructions_size_;
};


414
class LDummy final : public LTemplateInstruction<1, 0, 0> {
415
 public:
416
  LDummy() {}
417 418 419 420
  DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
};


421
class LDummyUse final : public LTemplateInstruction<1, 1, 0> {
422 423 424 425 426 427 428 429
 public:
  explicit LDummyUse(LOperand* value) {
    inputs_[0] = value;
  }
  DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
};


430
class LDeoptimize final : public LTemplateInstruction<0, 0, 0> {
431
 public:
432
  bool IsControl() const override { return true; }
433
  DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
434
  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
435 436 437
};


438
class LLabel final : public LGap {
439
 public:
440
  explicit LLabel(HBasicBlock* block)
fschneider@chromium.org's avatar
fschneider@chromium.org committed
441
      : LGap(block), replacement_(NULL) { }
442

443
  bool HasInterestingComment(LCodeGen* gen) const override { return false; }
444 445
  DECLARE_CONCRETE_INSTRUCTION(Label, "label")

446
  void PrintDataTo(StringStream* stream) override;
447

fschneider@chromium.org's avatar
fschneider@chromium.org committed
448 449
  int block_id() const { return block()->block_id(); }
  bool is_loop_header() const { return block()->IsLoopHeader(); }
450
  bool is_osr_entry() const { return block()->is_osr_entry(); }
451 452 453 454
  Label* label() { return &label_; }
  LLabel* replacement() const { return replacement_; }
  void set_replacement(LLabel* label) { replacement_ = label; }
  bool HasReplacement() const { return replacement_ != NULL; }
455 456 457 458

 private:
  Label label_;
  LLabel* replacement_;
459 460 461
};


462
class LParameter final : public LTemplateInstruction<1, 0, 0> {
463
 public:
464
  bool HasInterestingComment(LCodeGen* gen) const override { return false; }
465 466
  DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
};
467

468

469
class LUnknownOSRValue final : public LTemplateInstruction<1, 0, 0> {
470
 public:
471
  bool HasInterestingComment(LCodeGen* gen) const override { return false; }
472 473
  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
};
474

475

476
template<int I, int T>
477
class LControlInstruction : public LTemplateInstruction<0, I, T> {
478
 public:
479 480
  LControlInstruction() : false_label_(NULL), true_label_(NULL) { }

481
  bool IsControl() const final { return true; }
482

483 484
  int SuccessorCount() { return hydrogen()->SuccessorCount(); }
  HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508

  int TrueDestination(LChunk* chunk) {
    return chunk->LookupDestination(true_block_id());
  }
  int FalseDestination(LChunk* chunk) {
    return chunk->LookupDestination(false_block_id());
  }

  Label* TrueLabel(LChunk* chunk) {
    if (true_label_ == NULL) {
      true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk));
    }
    return true_label_;
  }
  Label* FalseLabel(LChunk* chunk) {
    if (false_label_ == NULL) {
      false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk));
    }
    return false_label_;
  }

 protected:
  int true_block_id() { return SuccessorAt(0)->block_id(); }
  int false_block_id() { return SuccessorAt(1)->block_id(); }
509

510
 private:
511 512 513
  HControlInstruction* hydrogen() {
    return HControlInstruction::cast(this->hydrogen_value());
  }
514 515 516

  Label* false_label_;
  Label* true_label_;
517 518 519
};


520
class LWrapReceiver final : public LTemplateInstruction<1, 2, 0> {
521 522 523 524 525 526 527 528
 public:
  LWrapReceiver(LOperand* receiver, LOperand* function) {
    inputs_[0] = receiver;
    inputs_[1] = function;
  }

  LOperand* receiver() { return inputs_[0]; }
  LOperand* function() { return inputs_[1]; }
529 530

  DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
531
  DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
532 533 534
};


535
class LApplyArguments final : public LTemplateInstruction<1, 4, 0> {
536 537 538 539 540
 public:
  LApplyArguments(LOperand* function,
                  LOperand* receiver,
                  LOperand* length,
                  LOperand* elements) {
541 542 543 544
    inputs_[0] = function;
    inputs_[1] = receiver;
    inputs_[2] = length;
    inputs_[3] = elements;
545 546
  }

547 548 549 550
  LOperand* function() { return inputs_[0]; }
  LOperand* receiver() { return inputs_[1]; }
  LOperand* length() { return inputs_[2]; }
  LOperand* elements() { return inputs_[3]; }
551 552

  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
553
  DECLARE_HYDROGEN_ACCESSOR(ApplyArguments)
554 555 556
};


557
class LAccessArgumentsAt final : public LTemplateInstruction<1, 3, 0> {
558 559
 public:
  LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index) {
560 561 562
    inputs_[0] = arguments;
    inputs_[1] = length;
    inputs_[2] = index;
563 564
  }

565 566 567
  LOperand* arguments() { return inputs_[0]; }
  LOperand* length() { return inputs_[1]; }
  LOperand* index() { return inputs_[2]; }
568

569 570
  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")

571
  void PrintDataTo(StringStream* stream) override;
572 573 574
};


575
class LArgumentsLength final : public LTemplateInstruction<1, 1, 0> {
576
 public:
577 578 579
  explicit LArgumentsLength(LOperand* elements) {
    inputs_[0] = elements;
  }
580

581 582
  LOperand* elements() { return inputs_[0]; }

583 584 585 586
  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
};


587
class LArgumentsElements final : public LTemplateInstruction<1, 0, 0> {
588 589
 public:
  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
590
  DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements)
591 592 593
};


594
class LModByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
 public:
  LModByPowerOf2I(LOperand* dividend, int32_t divisor) {
    inputs_[0] = dividend;
    divisor_ = divisor;
  }

  LOperand* dividend() { return inputs_[0]; }
  int32_t divisor() const { return divisor_; }

  DECLARE_CONCRETE_INSTRUCTION(ModByPowerOf2I, "mod-by-power-of-2-i")
  DECLARE_HYDROGEN_ACCESSOR(Mod)

 private:
  int32_t divisor_;
};


612
class LModByConstI final : public LTemplateInstruction<1, 1, 2> {
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
 public:
  LModByConstI(LOperand* dividend,
               int32_t divisor,
               LOperand* temp1,
               LOperand* temp2) {
    inputs_[0] = dividend;
    divisor_ = divisor;
    temps_[0] = temp1;
    temps_[1] = temp2;
  }

  LOperand* dividend() { return inputs_[0]; }
  int32_t divisor() const { return divisor_; }
  LOperand* temp1() { return temps_[0]; }
  LOperand* temp2() { return temps_[1]; }

  DECLARE_CONCRETE_INSTRUCTION(ModByConstI, "mod-by-const-i")
  DECLARE_HYDROGEN_ACCESSOR(Mod)

 private:
  int32_t divisor_;
};


637
class LModI final : public LTemplateInstruction<1, 2, 1> {
638
 public:
639 640 641 642 643
  LModI(LOperand* left, LOperand* right, LOperand* temp) {
    inputs_[0] = left;
    inputs_[1] = right;
    temps_[0] = temp;
  }
644

645 646 647 648
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }
  LOperand* temp() { return temps_[0]; }

649 650 651 652 653
  DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
  DECLARE_HYDROGEN_ACCESSOR(Mod)
};


654
class LDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
 public:
  LDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
    inputs_[0] = dividend;
    divisor_ = divisor;
  }

  LOperand* dividend() { return inputs_[0]; }
  int32_t divisor() const { return divisor_; }

  DECLARE_CONCRETE_INSTRUCTION(DivByPowerOf2I, "div-by-power-of-2-i")
  DECLARE_HYDROGEN_ACCESSOR(Div)

 private:
  int32_t divisor_;
};


672
class LDivByConstI final : public LTemplateInstruction<1, 1, 2> {
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
 public:
  LDivByConstI(LOperand* dividend,
               int32_t divisor,
               LOperand* temp1,
               LOperand* temp2) {
    inputs_[0] = dividend;
    divisor_ = divisor;
    temps_[0] = temp1;
    temps_[1] = temp2;
  }

  LOperand* dividend() { return inputs_[0]; }
  int32_t divisor() const { return divisor_; }
  LOperand* temp1() { return temps_[0]; }
  LOperand* temp2() { return temps_[1]; }

  DECLARE_CONCRETE_INSTRUCTION(DivByConstI, "div-by-const-i")
  DECLARE_HYDROGEN_ACCESSOR(Div)

 private:
  int32_t divisor_;
};


697
class LDivI final : public LTemplateInstruction<1, 2, 1> {
698
 public:
699 700 701
  LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
    inputs_[0] = dividend;
    inputs_[1] = divisor;
702 703
    temps_[0] = temp;
  }
704

705 706
  LOperand* dividend() { return inputs_[0]; }
  LOperand* divisor() { return inputs_[1]; }
707 708
  LOperand* temp() { return temps_[0]; }

709
  DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
710
  DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
711 712 713
};


714
class LFlooringDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
715
 public:
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
  LFlooringDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
    inputs_[0] = dividend;
    divisor_ = divisor;
  }

  LOperand* dividend() { return inputs_[0]; }
  int32_t divisor() const { return divisor_; }

  DECLARE_CONCRETE_INSTRUCTION(FlooringDivByPowerOf2I,
                               "flooring-div-by-power-of-2-i")
  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)

 private:
  int32_t divisor_;
};


733
class LFlooringDivByConstI final : public LTemplateInstruction<1, 1, 3> {
734
 public:
735 736 737
  LFlooringDivByConstI(LOperand* dividend,
                       int32_t divisor,
                       LOperand* temp1,
738 739
                       LOperand* temp2,
                       LOperand* temp3) {
740 741
    inputs_[0] = dividend;
    divisor_ = divisor;
742 743
    temps_[0] = temp1;
    temps_[1] = temp2;
744
    temps_[2] = temp3;
745 746
  }

747 748
  LOperand* dividend() { return inputs_[0]; }
  int32_t divisor() const { return divisor_; }
749
  LOperand* temp1() { return temps_[0]; }
750 751
  LOperand* temp2() { return temps_[1]; }
  LOperand* temp3() { return temps_[2]; }
752

753
  DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
754
  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
755 756 757

 private:
  int32_t divisor_;
758 759 760
};


761
class LFlooringDivI final : public LTemplateInstruction<1, 2, 1> {
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
 public:
  LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
    inputs_[0] = dividend;
    inputs_[1] = divisor;
    temps_[0] = temp;
  }

  LOperand* dividend() { return inputs_[0]; }
  LOperand* divisor() { return inputs_[1]; }
  LOperand* temp() { return temps_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(FlooringDivI, "flooring-div-i")
  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
};


778
class LMulI final : public LTemplateInstruction<1, 2, 0> {
779
 public:
780
  LMulI(LOperand* left, LOperand* right) {
781 782 783
    inputs_[0] = left;
    inputs_[1] = right;
  }
784

785 786 787
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

788 789 790 791 792
  DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
  DECLARE_HYDROGEN_ACCESSOR(Mul)
};


793
class LCompareNumericAndBranch final : public LControlInstruction<2, 0> {
794
 public:
795
  LCompareNumericAndBranch(LOperand* left, LOperand* right) {
796 797 798
    inputs_[0] = left;
    inputs_[1] = right;
  }
799

800 801 802
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

803 804 805
  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
                               "compare-numeric-and-branch")
  DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
806

807 808
  Token::Value op() const { return hydrogen()->token(); }
  bool is_double() const {
809
    return hydrogen()->representation().IsDouble();
810
  }
811

812
  void PrintDataTo(StringStream* stream) override;
813 814
};

815 816 817 818 819 820 821 822 823 824
// Math.floor with a double result.
class LMathFloorD final : public LTemplateInstruction<1, 1, 0> {
 public:
  explicit LMathFloorD(LOperand* value) { inputs_[0] = value; }

  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(MathFloorD, "math-floor-d")
  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
};
825

826 827
// Math.floor with an integer result.
class LMathFloorI final : public LTemplateInstruction<1, 1, 0> {
828
 public:
829
  explicit LMathFloorI(LOperand* value) { inputs_[0] = value; }
830

831 832
  LOperand* value() { return inputs_[0]; }

833
  DECLARE_CONCRETE_INSTRUCTION(MathFloorI, "math-floor-i")
834
  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
835
};
836

837 838 839 840 841 842 843 844 845 846
// Math.round with a double result.
class LMathRoundD final : public LTemplateInstruction<1, 1, 0> {
 public:
  explicit LMathRoundD(LOperand* value) { inputs_[0] = value; }

  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(MathRoundD, "math-round-d")
  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
};
847

848 849
// Math.round with an integer result.
class LMathRoundI final : public LTemplateInstruction<1, 1, 1> {
850
 public:
851
  LMathRoundI(LOperand* value, LOperand* temp) {
852
    inputs_[0] = value;
853
    temps_[0] = temp;
854 855 856
  }

  LOperand* value() { return inputs_[0]; }
857
  LOperand* temp() { return temps_[0]; }
858

859
  DECLARE_CONCRETE_INSTRUCTION(MathRoundI, "math-round-i")
860 861 862 863
  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
};


864
class LMathFround final : public LTemplateInstruction<1, 1, 0> {
865 866 867 868 869
 public:
  explicit LMathFround(LOperand* value) { inputs_[0] = value; }

  LOperand* value() { return inputs_[0]; }

870
  DECLARE_CONCRETE_INSTRUCTION(MathFround, "math-fround")
871 872 873
};


874
class LMathAbs final : public LTemplateInstruction<1, 2, 0> {
875
 public:
876 877
  explicit LMathAbs(LOperand* context, LOperand* value) {
    inputs_[1] = context;
878 879 880
    inputs_[0] = value;
  }

881
  LOperand* context() { return inputs_[1]; }
882 883 884 885 886 887 888
  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs")
  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
};


889
class LMathLog final : public LTemplateInstruction<1, 1, 0> {
890 891 892 893 894 895 896 897 898 899 900
 public:
  explicit LMathLog(LOperand* value) {
    inputs_[0] = value;
  }

  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
};


901
class LMathClz32 final : public LTemplateInstruction<1, 1, 0> {
902 903 904 905 906 907 908 909 910 911
 public:
  explicit LMathClz32(LOperand* value) {
    inputs_[0] = value;
  }

  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
};

912 913 914 915 916 917 918 919 920
class LMathCos final : public LTemplateInstruction<1, 1, 0> {
 public:
  explicit LMathCos(LOperand* value) { inputs_[0] = value; }

  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
};

921
class LMathExp final : public LTemplateInstruction<1, 1, 0> {
922
 public:
923
  explicit LMathExp(LOperand* value) { inputs_[0] = value; }
924 925 926 927

  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
928
};
929

930 931 932 933 934 935 936 937
class LMathSin final : public LTemplateInstruction<1, 1, 0> {
 public:
  explicit LMathSin(LOperand* value) { inputs_[0] = value; }

  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
};
938

939
class LMathSqrt final : public LTemplateInstruction<1, 1, 0> {
940 941 942 943 944 945 946 947 948 949 950
 public:
  explicit LMathSqrt(LOperand* value) {
    inputs_[0] = value;
  }

  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt")
};


951
class LMathPowHalf final : public LTemplateInstruction<1, 1, 0> {
952 953 954 955 956 957 958 959
 public:
  explicit LMathPowHalf(LOperand* value) {
    inputs_[0] = value;
  }

  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half")
960 961 962
};


963
class LCmpObjectEqAndBranch final : public LControlInstruction<2, 0> {
964
 public:
965
  LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
966 967 968
    inputs_[0] = left;
    inputs_[1] = right;
  }
969

970 971 972
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

973 974 975 976
  DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
};


977
class LCmpHoleAndBranch final : public LControlInstruction<1, 0> {
978 979 980 981 982 983 984 985 986
 public:
  explicit LCmpHoleAndBranch(LOperand* object) {
    inputs_[0] = object;
  }

  LOperand* object() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranch, "cmp-hole-and-branch")
  DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
987 988 989
};


990
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
991 992 993 994 995 996
 public:
  explicit LIsStringAndBranch(LOperand* value, LOperand* temp) {
    inputs_[0] = value;
    temps_[0] = temp;
  }

997 998 999
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

1000 1001 1002
  DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
  DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)

1003
  void PrintDataTo(StringStream* stream) override;
1004 1005 1006
};


1007
class LIsSmiAndBranch final : public LControlInstruction<1, 0> {
1008
 public:
1009 1010 1011
  explicit LIsSmiAndBranch(LOperand* value) {
    inputs_[0] = value;
  }
1012

1013 1014
  LOperand* value() { return inputs_[0]; }

1015
  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
1016
  DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
1017

1018
  void PrintDataTo(StringStream* stream) override;
1019 1020 1021
};


1022
class LIsUndetectableAndBranch final : public LControlInstruction<1, 1> {
1023 1024 1025 1026 1027 1028
 public:
  explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
    inputs_[0] = value;
    temps_[0] = temp;
  }

1029 1030 1031
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

1032 1033
  DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
                               "is-undetectable-and-branch")
1034
  DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
1035

1036
  void PrintDataTo(StringStream* stream) override;
1037 1038 1039
};


1040
class LStringCompareAndBranch final : public LControlInstruction<3, 0> {
1041
 public:
1042 1043 1044 1045 1046 1047
  explicit LStringCompareAndBranch(LOperand* context,
                                   LOperand* left,
                                   LOperand* right) {
    inputs_[0] = context;
    inputs_[1] = left;
    inputs_[2] = right;
1048 1049
  }

1050 1051 1052
  LOperand* context() { return inputs_[0]; }
  LOperand* left() { return inputs_[1]; }
  LOperand* right() { return inputs_[2]; }
1053

1054 1055 1056 1057
  DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
                               "string-compare-and-branch")
  DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)

1058
  void PrintDataTo(StringStream* stream) override;
1059 1060 1061 1062 1063

  Token::Value op() const { return hydrogen()->token(); }
};


1064
class LHasInstanceTypeAndBranch final : public LControlInstruction<1, 0> {
1065
 public:
1066
  explicit LHasInstanceTypeAndBranch(LOperand* value) {
1067 1068
    inputs_[0] = value;
  }
1069

1070 1071
  LOperand* value() { return inputs_[0]; }

1072 1073
  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
                               "has-instance-type-and-branch")
1074
  DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
1075

1076
  void PrintDataTo(StringStream* stream) override;
1077 1078 1079
};


1080
class LGetCachedArrayIndex final : public LTemplateInstruction<1, 1, 0> {
1081 1082 1083 1084 1085
 public:
  explicit LGetCachedArrayIndex(LOperand* value) {
    inputs_[0] = value;
  }

1086 1087
  LOperand* value() { return inputs_[0]; }

1088 1089 1090 1091 1092
  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
  DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
};


1093
class LHasCachedArrayIndexAndBranch final : public LControlInstruction<1, 0> {
1094
 public:
1095 1096 1097
  explicit LHasCachedArrayIndexAndBranch(LOperand* value) {
    inputs_[0] = value;
  }
1098

1099 1100
  LOperand* value() { return inputs_[0]; }

1101 1102
  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
                               "has-cached-array-index-and-branch")
1103
  DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndexAndBranch)
1104

1105
  void PrintDataTo(StringStream* stream) override;
1106 1107 1108
};


1109
class LClassOfTestAndBranch final : public LControlInstruction<1, 2> {
1110
 public:
1111
  LClassOfTestAndBranch(LOperand* value, LOperand* temp, LOperand* temp2) {
1112 1113
    inputs_[0] = value;
    temps_[0] = temp;
1114
    temps_[1] = temp2;
1115
  }
1116

1117 1118 1119 1120
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }
  LOperand* temp2() { return temps_[1]; }

1121 1122
  DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
                               "class-of-test-and-branch")
1123
  DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
1124

1125
  void PrintDataTo(StringStream* stream) override;
1126 1127 1128
};


1129
class LCmpT final : public LTemplateInstruction<1, 3, 0> {
1130
 public:
1131 1132 1133 1134
  LCmpT(LOperand* context, LOperand* left, LOperand* right) {
    inputs_[0] = context;
    inputs_[1] = left;
    inputs_[2] = right;
1135
  }
1136

1137 1138 1139
  LOperand* context() { return inputs_[0]; }
  LOperand* left() { return inputs_[1]; }
  LOperand* right() { return inputs_[2]; }
1140

1141 1142
  DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
  DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
1143 1144 1145 1146 1147

  Token::Value op() const { return hydrogen()->token(); }
};


1148
class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 0> {
1149
 public:
1150 1151 1152
  LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype) {
    inputs_[0] = object;
    inputs_[1] = prototype;
1153
  }
1154

1155 1156
  LOperand* object() const { return inputs_[0]; }
  LOperand* prototype() const { return inputs_[1]; }
1157

1158 1159 1160
  DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch,
                               "has-in-prototype-chain-and-branch")
  DECLARE_HYDROGEN_ACCESSOR(HasInPrototypeChainAndBranch)
1161 1162 1163
};


1164
class LBoundsCheck final : public LTemplateInstruction<0, 2, 0> {
1165
 public:
1166 1167 1168 1169
  LBoundsCheck(LOperand* index, LOperand* length) {
    inputs_[0] = index;
    inputs_[1] = length;
  }
1170

1171 1172
  LOperand* index() { return inputs_[0]; }
  LOperand* length() { return inputs_[1]; }
1173 1174

  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
1175
  DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
1176 1177 1178
};


1179
class LBitI final : public LTemplateInstruction<1, 2, 0> {
1180
 public:
1181
  LBitI(LOperand* left, LOperand* right) {
1182 1183 1184
    inputs_[0] = left;
    inputs_[1] = right;
  }
1185

1186 1187 1188
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

1189
  Token::Value op() const { return hydrogen()->op(); }
1190 1191 1192
  bool IsInteger32() const {
    return hydrogen()->representation().IsInteger32();
  }
1193 1194

  DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
1195
  DECLARE_HYDROGEN_ACCESSOR(Bitwise)
1196 1197 1198
};


1199
class LShiftI final : public LTemplateInstruction<1, 2, 0> {
1200 1201
 public:
  LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
1202 1203 1204 1205
      : op_(op), can_deopt_(can_deopt) {
    inputs_[0] = left;
    inputs_[1] = right;
  }
1206 1207

  Token::Value op() const { return op_; }
1208 1209
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
  bool can_deopt() const { return can_deopt_; }

  DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")

 private:
  Token::Value op_;
  bool can_deopt_;
};


1220
class LSubI final : public LTemplateInstruction<1, 2, 0> {
1221
 public:
1222 1223 1224 1225
  LSubI(LOperand* left, LOperand* right) {
    inputs_[0] = left;
    inputs_[1] = right;
  }
1226

1227 1228 1229
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

1230 1231 1232 1233 1234
  DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
  DECLARE_HYDROGEN_ACCESSOR(Sub)
};


1235
class LConstantI final : public LTemplateInstruction<1, 0, 0> {
1236 1237
 public:
  DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
1238
  DECLARE_HYDROGEN_ACCESSOR(Constant)
1239

1240
  int32_t value() const { return hydrogen()->Integer32Value(); }
1241 1242 1243
};


1244
class LConstantS final : public LTemplateInstruction<1, 0, 0> {
1245 1246 1247 1248 1249 1250 1251 1252
 public:
  DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
  DECLARE_HYDROGEN_ACCESSOR(Constant)

  Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
};


1253
class LConstantD final : public LTemplateInstruction<1, 0, 0> {
1254 1255
 public:
  DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
1256
  DECLARE_HYDROGEN_ACCESSOR(Constant)
1257

1258
  uint64_t bits() const { return hydrogen()->DoubleValueAsBits(); }
1259 1260 1261
};


1262
class LConstantE final : public LTemplateInstruction<1, 0, 0> {
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
 public:
  DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
  DECLARE_HYDROGEN_ACCESSOR(Constant)

  ExternalReference value() const {
    return hydrogen()->ExternalReferenceValue();
  }
};


1273
class LConstantT final : public LTemplateInstruction<1, 0, 0> {
1274 1275
 public:
  DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
1276
  DECLARE_HYDROGEN_ACCESSOR(Constant)
1277

1278 1279 1280
  Handle<Object> value(Isolate* isolate) const {
    return hydrogen()->handle(isolate);
  }
1281 1282 1283
};


1284
class LBranch final : public LControlInstruction<1, 0> {
1285
 public:
1286 1287 1288
  explicit LBranch(LOperand* value) {
    inputs_[0] = value;
  }
1289

1290 1291
  LOperand* value() { return inputs_[0]; }

1292
  DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
1293
  DECLARE_HYDROGEN_ACCESSOR(Branch)
1294

1295
  void PrintDataTo(StringStream* stream) override;
1296 1297 1298
};


1299
class LDebugBreak final : public LTemplateInstruction<0, 0, 0> {
1300 1301 1302 1303 1304
 public:
  DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break")
};


1305
class LCmpMapAndBranch final : public LControlInstruction<1, 0> {
1306
 public:
1307 1308 1309
  explicit LCmpMapAndBranch(LOperand* value) {
    inputs_[0] = value;
  }
1310

1311 1312
  LOperand* value() { return inputs_[0]; }

1313
  DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
1314
  DECLARE_HYDROGEN_ACCESSOR(CompareMap)
1315

1316
  Handle<Map> map() const { return hydrogen()->map().handle(); }
1317 1318 1319
};


1320
class LSeqStringGetChar final : public LTemplateInstruction<1, 2, 0> {
1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334
 public:
  LSeqStringGetChar(LOperand* string, LOperand* index) {
    inputs_[0] = string;
    inputs_[1] = index;
  }

  LOperand* string() const { return inputs_[0]; }
  LOperand* index() const { return inputs_[1]; }

  DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char")
  DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar)
};


1335
class LSeqStringSetChar final : public LTemplateInstruction<1, 4, 0> {
1336
 public:
1337 1338
  LSeqStringSetChar(LOperand* context,
                    LOperand* string,
1339
                    LOperand* index,
1340
                    LOperand* value) {
1341 1342 1343 1344
    inputs_[0] = context;
    inputs_[1] = string;
    inputs_[2] = index;
    inputs_[3] = value;
1345 1346
  }

1347 1348 1349
  LOperand* string() { return inputs_[1]; }
  LOperand* index() { return inputs_[2]; }
  LOperand* value() { return inputs_[3]; }
1350 1351 1352 1353 1354 1355

  DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
  DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
};


1356
class LAddI final : public LTemplateInstruction<1, 2, 0> {
1357
 public:
1358 1359 1360 1361
  LAddI(LOperand* left, LOperand* right) {
    inputs_[0] = left;
    inputs_[1] = right;
  }
1362

1363 1364 1365
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

1366 1367 1368 1369 1370
  static bool UseLea(HAdd* add) {
    return !add->CheckFlag(HValue::kCanOverflow) &&
        add->BetterLeftOperand()->UseCount() > 1;
  }

1371 1372 1373 1374 1375
  DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
  DECLARE_HYDROGEN_ACCESSOR(Add)
};


1376
class LMathMinMax final : public LTemplateInstruction<1, 2, 0> {
1377 1378 1379 1380 1381 1382
 public:
  LMathMinMax(LOperand* left, LOperand* right) {
    inputs_[0] = left;
    inputs_[1] = right;
  }

1383 1384 1385
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

1386
  DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max")
1387 1388 1389 1390
  DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
};


1391
class LPower final : public LTemplateInstruction<1, 2, 0> {
1392
 public:
1393 1394 1395 1396
  LPower(LOperand* left, LOperand* right) {
    inputs_[0] = left;
    inputs_[1] = right;
  }
1397

1398 1399 1400
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

1401 1402 1403 1404 1405
  DECLARE_CONCRETE_INSTRUCTION(Power, "power")
  DECLARE_HYDROGEN_ACCESSOR(Power)
};


1406
class LArithmeticD final : public LTemplateInstruction<1, 2, 0> {
1407 1408
 public:
  LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
1409 1410 1411 1412
      : op_(op) {
    inputs_[0] = left;
    inputs_[1] = right;
  }
1413 1414

  Token::Value op() const { return op_; }
1415 1416
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }
1417

1418 1419 1420
  Opcode opcode() const override { return LInstruction::kArithmeticD; }
  void CompileToNative(LCodeGen* generator) override;
  const char* Mnemonic() const override;
1421 1422 1423 1424 1425 1426

 private:
  Token::Value op_;
};


1427
class LArithmeticT final : public LTemplateInstruction<1, 3, 0> {
1428
 public:
1429 1430 1431 1432
  LArithmeticT(Token::Value op,
               LOperand* context,
               LOperand* left,
               LOperand* right)
1433
      : op_(op) {
1434 1435 1436
    inputs_[0] = context;
    inputs_[1] = left;
    inputs_[2] = right;
1437
  }
1438

1439
  Token::Value op() const { return op_; }
1440 1441 1442
  LOperand* context() { return inputs_[0]; }
  LOperand* left() { return inputs_[1]; }
  LOperand* right() { return inputs_[2]; }
1443

1444 1445 1446
  Opcode opcode() const override { return LInstruction::kArithmeticT; }
  void CompileToNative(LCodeGen* generator) override;
  const char* Mnemonic() const override;
1447

conradw's avatar
conradw committed
1448 1449
  DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)

1450 1451 1452 1453 1454
 private:
  Token::Value op_;
};


1455
class LReturn final : public LTemplateInstruction<0, 3, 0> {
1456
 public:
1457 1458 1459
  explicit LReturn(LOperand* value,
                   LOperand* context,
                   LOperand* parameter_count) {
1460
    inputs_[0] = value;
1461 1462
    inputs_[1] = context;
    inputs_[2] = parameter_count;
1463
  }
1464

1465
  LOperand* value() { return inputs_[0]; }
1466
  LOperand* context() { return inputs_[1]; }
1467

1468 1469 1470 1471
  bool has_constant_parameter_count() {
    return parameter_count()->IsConstantOperand();
  }
  LConstantOperand* constant_parameter_count() {
1472
    DCHECK(has_constant_parameter_count());
1473 1474
    return LConstantOperand::cast(parameter_count());
  }
1475
  LOperand* parameter_count() { return inputs_[2]; }
1476

1477
  DECLARE_CONCRETE_INSTRUCTION(Return, "return")
1478
  DECLARE_HYDROGEN_ACCESSOR(Return)
1479 1480 1481
};


1482
class LLoadNamedField final : public LTemplateInstruction<1, 1, 0> {
1483
 public:
1484
  explicit LLoadNamedField(LOperand* object) {
1485 1486
    inputs_[0] = object;
  }
1487

1488 1489
  LOperand* object() { return inputs_[0]; }

1490 1491 1492 1493 1494
  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
  DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
};


1495
class LLoadNamedGeneric final : public LTemplateInstruction<1, 2, 1> {
1496
 public:
1497 1498
  explicit LLoadNamedGeneric(LOperand* context, LOperand* object,
                             LOperand* vector) {
1499 1500
    inputs_[0] = context;
    inputs_[1] = object;
1501
    temps_[0] = vector;
1502
  }
1503 1504 1505 1506

  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
  DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)

1507 1508
  LOperand* context() { return inputs_[0]; }
  LOperand* object() { return inputs_[1]; }
1509 1510
  LOperand* temp_vector() { return temps_[0]; }

1511 1512 1513 1514
  Handle<Object> name() const { return hydrogen()->name(); }
};


1515
class LLoadFunctionPrototype final : public LTemplateInstruction<1, 1, 0> {
1516
 public:
1517
  explicit LLoadFunctionPrototype(LOperand* function) {
1518 1519
    inputs_[0] = function;
  }
1520 1521 1522 1523

  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
  DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)

1524
  LOperand* function() { return inputs_[0]; }
1525 1526 1527
};


1528
class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
1529 1530 1531 1532 1533 1534 1535 1536
 public:
  DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root")
  DECLARE_HYDROGEN_ACCESSOR(LoadRoot)

  Heap::RootListIndex index() const { return hydrogen()->index(); }
};


1537 1538 1539 1540 1541 1542 1543
inline static bool ExternalArrayOpRequiresTemp(
    Representation key_representation,
    ElementsKind elements_kind) {
  // Operations that require the key to be divided by two to be converted into
  // an index cannot fold the scale operation into a load and need an extra
  // temp register to do the work.
  return SmiValuesAre31Bits() && key_representation.IsSmi() &&
1544 1545
         (elements_kind == UINT8_ELEMENTS || elements_kind == INT8_ELEMENTS ||
          elements_kind == UINT8_CLAMPED_ELEMENTS);
1546 1547 1548
}


1549
class LLoadKeyed final : public LTemplateInstruction<1, 3, 0> {
1550
 public:
1551
  LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) {
1552 1553
    inputs_[0] = elements;
    inputs_[1] = key;
1554
    inputs_[2] = backing_store_owner;
1555
  }
1556

1557 1558
  DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
  DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
1559

1560 1561 1562
  bool is_fixed_typed_array() const {
    return hydrogen()->is_fixed_typed_array();
  }
1563 1564
  LOperand* elements() { return inputs_[0]; }
  LOperand* key() { return inputs_[1]; }
1565
  LOperand* backing_store_owner() { return inputs_[2]; }
1566
  void PrintDataTo(StringStream* stream) override;
1567
  uint32_t base_offset() const { return hydrogen()->base_offset(); }
1568
  ElementsKind elements_kind() const {
1569
    return hydrogen()->elements_kind();
1570
  }
1571 1572 1573
};


1574
class LLoadKeyedGeneric final : public LTemplateInstruction<1, 3, 1> {
1575
 public:
1576 1577
  LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key,
                    LOperand* vector) {
1578 1579 1580
    inputs_[0] = context;
    inputs_[1] = obj;
    inputs_[2] = key;
1581
    temps_[0] = vector;
1582
  }
1583 1584

  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
1585
  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
1586

1587 1588 1589
  LOperand* context() { return inputs_[0]; }
  LOperand* object() { return inputs_[1]; }
  LOperand* key() { return inputs_[2]; }
1590
  LOperand* temp_vector() { return temps_[0]; }
1591 1592
};

1593
class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> {
1594
 public:
1595
  explicit LLoadGlobalGeneric(LOperand* context, LOperand* vector) {
1596
    inputs_[0] = context;
1597
    temps_[0] = vector;
1598 1599 1600 1601 1602
  }

  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)

1603
  LOperand* context() { return inputs_[0]; }
1604 1605
  LOperand* temp_vector() { return temps_[0]; }

1606
  Handle<Object> name() const { return hydrogen()->name(); }
1607
  TypeofMode typeof_mode() const { return hydrogen()->typeof_mode(); }
1608 1609 1610
};


1611
class LLoadContextSlot final : public LTemplateInstruction<1, 1, 0> {
1612
 public:
whesse@chromium.org's avatar
whesse@chromium.org committed
1613 1614
  explicit LLoadContextSlot(LOperand* context) {
    inputs_[0] = context;
1615 1616
  }

1617 1618
  LOperand* context() { return inputs_[0]; }

1619 1620 1621
  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
  DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)

1622
  int slot_index() { return hydrogen()->slot_index(); }
1623

1624
  void PrintDataTo(StringStream* stream) override;
1625 1626 1627
};


1628
class LStoreContextSlot final : public LTemplateInstruction<0, 2, 1> {
1629
 public:
1630
  LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
whesse@chromium.org's avatar
whesse@chromium.org committed
1631 1632
    inputs_[0] = context;
    inputs_[1] = value;
1633
    temps_[0] = temp;
1634 1635
  }

1636 1637 1638 1639
  LOperand* context() { return inputs_[0]; }
  LOperand* value() { return inputs_[1]; }
  LOperand* temp() { return temps_[0]; }

1640 1641 1642 1643 1644
  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
  DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)

  int slot_index() { return hydrogen()->slot_index(); }

1645
  void PrintDataTo(StringStream* stream) override;
1646 1647 1648
};


1649
class LPushArgument final : public LTemplateInstruction<0, 1, 0> {
1650
 public:
1651 1652 1653
  explicit LPushArgument(LOperand* value) {
    inputs_[0] = value;
  }
1654

1655 1656
  LOperand* value() { return inputs_[0]; }

1657 1658 1659 1660
  DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument")
};


1661
class LDrop final : public LTemplateInstruction<0, 0, 0> {
1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
 public:
  explicit LDrop(int count) : count_(count) { }

  int count() const { return count_; }

  DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")

 private:
  int count_;
};


1674
class LStoreCodeEntry final : public LTemplateInstruction<0, 2, 0> {
1675 1676 1677
 public:
  LStoreCodeEntry(LOperand* function, LOperand* code_object) {
    inputs_[0] = function;
1678
    inputs_[1] = code_object;
1679 1680 1681
  }

  LOperand* function() { return inputs_[0]; }
1682
  LOperand* code_object() { return inputs_[1]; }
1683

1684
  void PrintDataTo(StringStream* stream) override;
1685 1686 1687 1688 1689 1690

  DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
  DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
};


1691
class LInnerAllocatedObject final : public LTemplateInstruction<1, 2, 0> {
1692
 public:
1693
  LInnerAllocatedObject(LOperand* base_object, LOperand* offset) {
1694
    inputs_[0] = base_object;
1695
    inputs_[1] = offset;
1696 1697
  }

1698 1699
  LOperand* base_object() const { return inputs_[0]; }
  LOperand* offset() const { return inputs_[1]; }
1700

1701
  void PrintDataTo(StringStream* stream) override;
1702

1703
  DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object")
1704 1705 1706
};


1707
class LThisFunction final : public LTemplateInstruction<1, 0, 0> {
1708
 public:
1709
  DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
1710
  DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
1711 1712 1713
};


1714
class LContext final : public LTemplateInstruction<1, 0, 0> {
1715 1716
 public:
  DECLARE_CONCRETE_INSTRUCTION(Context, "context")
1717
  DECLARE_HYDROGEN_ACCESSOR(Context)
1718 1719 1720
};


1721
class LDeclareGlobals final : public LTemplateInstruction<0, 1, 0> {
1722
 public:
1723 1724 1725 1726 1727 1728
  explicit LDeclareGlobals(LOperand* context) {
    inputs_[0] = context;
  }

  LOperand* context() { return inputs_[0]; }

1729 1730 1731 1732 1733
  DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
  DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
};


1734
class LCallWithDescriptor final : public LTemplateResultInstruction<1> {
1735
 public:
1736
  LCallWithDescriptor(CallInterfaceDescriptor descriptor,
1737
                      const ZoneList<LOperand*>& operands, Zone* zone)
1738 1739 1740 1741 1742 1743
      : inputs_(descriptor.GetRegisterParameterCount() +
                    kImplicitRegisterParameterCount,
                zone) {
    DCHECK(descriptor.GetRegisterParameterCount() +
               kImplicitRegisterParameterCount ==
           operands.length());
1744
    inputs_.AddAll(operands, zone);
1745 1746
  }

1747
  LOperand* target() const { return inputs_[0]; }
1748

1749 1750
  DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)

1751 1752 1753 1754
  // The target and context are passed as implicit parameters that are not
  // explicitly listed in the descriptor.
  static const int kImplicitRegisterParameterCount = 2;

1755 1756
 private:
  DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
1757

1758
  void PrintDataTo(StringStream* stream) override;
1759 1760 1761

  int arity() const { return hydrogen()->argument_count() - 1; }

1762
  ZoneList<LOperand*> inputs_;
1763

1764
  // Iterator support.
1765 1766
  int InputCount() final { return inputs_.length(); }
  LOperand* InputAt(int i) final { return inputs_[i]; }
1767

1768 1769
  int TempCount() final { return 0; }
  LOperand* TempAt(int i) final { return NULL; }
1770 1771 1772
};


1773
class LInvokeFunction final : public LTemplateInstruction<1, 2, 0> {
1774
 public:
1775
  LInvokeFunction(LOperand* context, LOperand* function) {
1776
    inputs_[0] = context;
1777
    inputs_[1] = function;
1778 1779 1780
  }

  LOperand* context() { return inputs_[0]; }
1781
  LOperand* function() { return inputs_[1]; }
1782

1783 1784
  DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
  DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
1785

1786
  void PrintDataTo(StringStream* stream) override;
1787 1788 1789 1790 1791

  int arity() const { return hydrogen()->argument_count() - 1; }
};


1792
class LCallNewArray final : public LTemplateInstruction<1, 2, 0> {
1793
 public:
1794 1795 1796
  LCallNewArray(LOperand* context, LOperand* constructor) {
    inputs_[0] = context;
    inputs_[1] = constructor;
1797 1798
  }

1799 1800
  LOperand* context() { return inputs_[0]; }
  LOperand* constructor() { return inputs_[1]; }
1801 1802 1803 1804

  DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
  DECLARE_HYDROGEN_ACCESSOR(CallNewArray)

1805
  void PrintDataTo(StringStream* stream) override;
1806 1807 1808 1809 1810

  int arity() const { return hydrogen()->argument_count() - 1; }
};


1811
class LCallRuntime final : public LTemplateInstruction<1, 1, 0> {
1812
 public:
1813 1814 1815 1816 1817 1818
  explicit LCallRuntime(LOperand* context) {
    inputs_[0] = context;
  }

  LOperand* context() { return inputs_[0]; }

1819 1820 1821
  DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
  DECLARE_HYDROGEN_ACCESSOR(CallRuntime)

1822
  bool ClobbersDoubleRegisters(Isolate* isolate) const override {
1823 1824 1825
    return save_doubles() == kDontSaveFPRegs;
  }

1826
  const Runtime::Function* function() const { return hydrogen()->function(); }
1827
  int arity() const { return hydrogen()->argument_count(); }
1828
  SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); }
1829 1830 1831
};


1832
class LInteger32ToDouble final : public LTemplateInstruction<1, 1, 0> {
1833
 public:
1834 1835 1836
  explicit LInteger32ToDouble(LOperand* value) {
    inputs_[0] = value;
  }
1837

1838 1839
  LOperand* value() { return inputs_[0]; }

1840 1841 1842 1843
  DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
};


1844
class LUint32ToDouble final : public LTemplateInstruction<1, 1, 0> {
1845
 public:
1846
  explicit LUint32ToDouble(LOperand* value) {
1847 1848 1849
    inputs_[0] = value;
  }

1850 1851
  LOperand* value() { return inputs_[0]; }

1852 1853 1854 1855
  DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
};


1856
class LNumberTagI final : public LTemplateInstruction<1, 1, 2> {
1857
 public:
1858
  LNumberTagI(LOperand* value, LOperand* temp1, LOperand* temp2) {
1859
    inputs_[0] = value;
1860 1861
    temps_[0] = temp1;
    temps_[1] = temp2;
1862
  }
1863

1864
  LOperand* value() { return inputs_[0]; }
1865 1866
  LOperand* temp1() { return temps_[0]; }
  LOperand* temp2() { return temps_[1]; }
1867

1868 1869 1870 1871
  DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i")
};


1872
class LNumberTagU final : public LTemplateInstruction<1, 1, 2> {
1873
 public:
1874
  LNumberTagU(LOperand* value, LOperand* temp1, LOperand* temp2) {
1875
    inputs_[0] = value;
1876 1877
    temps_[0] = temp1;
    temps_[1] = temp2;
1878 1879
  }

1880
  LOperand* value() { return inputs_[0]; }
1881 1882
  LOperand* temp1() { return temps_[0]; }
  LOperand* temp2() { return temps_[1]; }
1883

1884 1885 1886 1887
  DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
};


1888
class LNumberTagD final : public LTemplateInstruction<1, 1, 1> {
1889
 public:
1890 1891 1892 1893
  explicit LNumberTagD(LOperand* value, LOperand* temp) {
    inputs_[0] = value;
    temps_[0] = temp;
  }
1894

1895 1896 1897
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

1898
  DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
1899
  DECLARE_HYDROGEN_ACCESSOR(Change)
1900 1901 1902 1903
};


// Sometimes truncating conversion from a tagged value to an int32.
1904
class LDoubleToI final : public LTemplateInstruction<1, 1, 0> {
1905
 public:
1906
  explicit LDoubleToI(LOperand* value) {
1907 1908
    inputs_[0] = value;
  }
1909

1910 1911
  LOperand* value() { return inputs_[0]; }

1912
  DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
1913
  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
1914 1915 1916 1917 1918

  bool truncating() { return hydrogen()->CanTruncateToInt32(); }
};


1919
class LDoubleToSmi final : public LTemplateInstruction<1, 1, 0> {
1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931
 public:
  explicit LDoubleToSmi(LOperand* value) {
    inputs_[0] = value;
  }

  LOperand* value() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
};


1932
// Truncating conversion from a tagged value to an int32.
1933
class LTaggedToI final : public LTemplateInstruction<1, 1, 1> {
1934
 public:
1935 1936 1937 1938
  LTaggedToI(LOperand* value, LOperand* temp) {
    inputs_[0] = value;
    temps_[0] = temp;
  }
1939

1940 1941 1942
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

1943
  DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
1944
  DECLARE_HYDROGEN_ACCESSOR(Change)
1945 1946 1947 1948 1949

  bool truncating() { return hydrogen()->CanTruncateToInt32(); }
};


1950
class LSmiTag final : public LTemplateInstruction<1, 1, 0> {
1951
 public:
1952 1953 1954
  explicit LSmiTag(LOperand* value) {
    inputs_[0] = value;
  }
1955

1956 1957
  LOperand* value() { return inputs_[0]; }

1958
  DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
1959
  DECLARE_HYDROGEN_ACCESSOR(Change)
1960 1961 1962
};


1963
class LNumberUntagD final : public LTemplateInstruction<1, 1, 0> {
1964
 public:
1965 1966 1967
  explicit LNumberUntagD(LOperand* value) {
    inputs_[0] = value;
  }
1968

1969 1970
  LOperand* value() { return inputs_[0]; }

1971
  DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
1972
  DECLARE_HYDROGEN_ACCESSOR(Change);
1973 1974 1975
};


1976
class LSmiUntag final : public LTemplateInstruction<1, 1, 0> {
1977
 public:
1978 1979 1980 1981
  LSmiUntag(LOperand* value, bool needs_check)
      : needs_check_(needs_check) {
    inputs_[0] = value;
  }
1982

1983
  LOperand* value() { return inputs_[0]; }
1984 1985
  bool needs_check() const { return needs_check_; }

1986 1987
  DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")

1988 1989 1990 1991 1992
 private:
  bool needs_check_;
};


1993
class LStoreNamedField final : public LTemplateInstruction<0, 2, 1> {
1994
 public:
1995
  LStoreNamedField(LOperand* object, LOperand* value, LOperand* temp) {
1996 1997
    inputs_[0] = object;
    inputs_[1] = value;
1998
    temps_[0] = temp;
1999 2000
  }

2001 2002 2003 2004
  LOperand* object() { return inputs_[0]; }
  LOperand* value() { return inputs_[1]; }
  LOperand* temp() { return temps_[0]; }

2005 2006
  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
  DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
2007

2008
  void PrintDataTo(StringStream* stream) override;
2009

2010 2011 2012
  Representation representation() const {
    return hydrogen()->field_representation();
  }
2013 2014 2015
};


2016
class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
2017
 public:
2018 2019
  LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value,
                     LOperand* slot, LOperand* vector) {
2020 2021 2022
    inputs_[0] = context;
    inputs_[1] = object;
    inputs_[2] = value;
2023 2024
    temps_[0] = slot;
    temps_[1] = vector;
2025
  }
2026

2027 2028 2029
  LOperand* context() { return inputs_[0]; }
  LOperand* object() { return inputs_[1]; }
  LOperand* value() { return inputs_[2]; }
2030 2031
  LOperand* temp_slot() { return temps_[0]; }
  LOperand* temp_vector() { return temps_[1]; }
2032

2033 2034
  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
  DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
2035

2036
  void PrintDataTo(StringStream* stream) override;
2037 2038

  Handle<Object> name() const { return hydrogen()->name(); }
2039
  LanguageMode language_mode() { return hydrogen()->language_mode(); }
2040 2041 2042
};


2043
class LStoreKeyed final : public LTemplateInstruction<0, 4, 0> {
2044
 public:
2045 2046
  LStoreKeyed(LOperand* object, LOperand* key, LOperand* value,
              LOperand* backing_store_owner) {
2047
    inputs_[0] = object;
2048
    inputs_[1] = key;
2049
    inputs_[2] = value;
2050
    inputs_[3] = backing_store_owner;
2051 2052
  }

2053 2054 2055
  bool is_fixed_typed_array() const {
    return hydrogen()->is_fixed_typed_array();
  }
2056 2057 2058
  LOperand* elements() { return inputs_[0]; }
  LOperand* key() { return inputs_[1]; }
  LOperand* value() { return inputs_[2]; }
2059
  LOperand* backing_store_owner() { return inputs_[3]; }
2060
  ElementsKind elements_kind() const { return hydrogen()->elements_kind(); }
2061

2062 2063
  DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
  DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
2064

2065
  void PrintDataTo(StringStream* stream) override;
2066
  bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
2067
  uint32_t base_offset() const { return hydrogen()->base_offset(); }
2068 2069 2070
};


2071
class LStoreKeyedGeneric final : public LTemplateInstruction<0, 4, 2> {
2072
 public:
2073 2074
  LStoreKeyedGeneric(LOperand* context, LOperand* object, LOperand* key,
                     LOperand* value, LOperand* slot, LOperand* vector) {
2075 2076 2077 2078
    inputs_[0] = context;
    inputs_[1] = object;
    inputs_[2] = key;
    inputs_[3] = value;
2079 2080
    temps_[0] = slot;
    temps_[1] = vector;
2081
  }
2082

2083 2084 2085 2086
  LOperand* context() { return inputs_[0]; }
  LOperand* object() { return inputs_[1]; }
  LOperand* key() { return inputs_[2]; }
  LOperand* value() { return inputs_[3]; }
2087 2088
  LOperand* temp_slot() { return temps_[0]; }
  LOperand* temp_vector() { return temps_[1]; }
2089

2090
  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
mmaly@chromium.org's avatar
mmaly@chromium.org committed
2091
  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
2092

2093
  void PrintDataTo(StringStream* stream) override;
2094

2095
  LanguageMode language_mode() { return hydrogen()->language_mode(); }
2096 2097 2098
};


2099
class LTransitionElementsKind final : public LTemplateInstruction<0, 2, 2> {
2100 2101
 public:
  LTransitionElementsKind(LOperand* object,
2102
                          LOperand* context,
2103
                          LOperand* new_map_temp,
2104
                          LOperand* temp) {
2105
    inputs_[0] = object;
2106
    inputs_[1] = context;
2107
    temps_[0] = new_map_temp;
2108
    temps_[1] = temp;
2109 2110
  }

2111
  LOperand* object() { return inputs_[0]; }
2112
  LOperand* context() { return inputs_[1]; }
2113 2114 2115
  LOperand* new_map_temp() { return temps_[0]; }
  LOperand* temp() { return temps_[1]; }

2116 2117 2118 2119
  DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
                               "transition-elements-kind")
  DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)

2120
  void PrintDataTo(StringStream* stream) override;
2121

2122 2123 2124 2125
  Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
  Handle<Map> transitioned_map() {
    return hydrogen()->transitioned_map().handle();
  }
2126 2127
  ElementsKind from_kind() { return hydrogen()->from_kind(); }
  ElementsKind to_kind() { return hydrogen()->to_kind(); }
2128 2129 2130
};


2131
class LTrapAllocationMemento final : public LTemplateInstruction<0, 1, 1> {
2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146
 public:
  LTrapAllocationMemento(LOperand* object,
                         LOperand* temp) {
    inputs_[0] = object;
    temps_[0] = temp;
  }

  LOperand* object() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento,
                               "trap-allocation-memento")
};


2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168
class LMaybeGrowElements final : public LTemplateInstruction<1, 5, 0> {
 public:
  LMaybeGrowElements(LOperand* context, LOperand* object, LOperand* elements,
                     LOperand* key, LOperand* current_capacity) {
    inputs_[0] = context;
    inputs_[1] = object;
    inputs_[2] = elements;
    inputs_[3] = key;
    inputs_[4] = current_capacity;
  }

  LOperand* context() { return inputs_[0]; }
  LOperand* object() { return inputs_[1]; }
  LOperand* elements() { return inputs_[2]; }
  LOperand* key() { return inputs_[3]; }
  LOperand* current_capacity() { return inputs_[4]; }

  DECLARE_HYDROGEN_ACCESSOR(MaybeGrowElements)
  DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements, "maybe-grow-elements")
};


2169
class LStringAdd final : public LTemplateInstruction<1, 3, 0> {
2170
 public:
2171 2172 2173 2174
  LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
    inputs_[0] = context;
    inputs_[1] = left;
    inputs_[2] = right;
2175 2176
  }

2177 2178 2179
  LOperand* context() { return inputs_[0]; }
  LOperand* left() { return inputs_[1]; }
  LOperand* right() { return inputs_[2]; }
2180 2181 2182

  DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
  DECLARE_HYDROGEN_ACCESSOR(StringAdd)
2183 2184 2185
};


2186
class LStringCharCodeAt final : public LTemplateInstruction<1, 3, 0> {
2187
 public:
2188 2189 2190 2191
  LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
    inputs_[0] = context;
    inputs_[1] = string;
    inputs_[2] = index;
2192 2193
  }

2194 2195 2196
  LOperand* context() { return inputs_[0]; }
  LOperand* string() { return inputs_[1]; }
  LOperand* index() { return inputs_[2]; }
2197 2198 2199

  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
  DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
2200 2201 2202
};


2203
class LStringCharFromCode final : public LTemplateInstruction<1, 2, 0> {
2204
 public:
2205 2206 2207
  explicit LStringCharFromCode(LOperand* context, LOperand* char_code) {
    inputs_[0] = context;
    inputs_[1] = char_code;
2208 2209
  }

2210 2211
  LOperand* context() { return inputs_[0]; }
  LOperand* char_code() { return inputs_[1]; }
2212

2213 2214 2215 2216 2217
  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
  DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
};


2218
class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
2219
 public:
2220
  explicit LCheckValue(LOperand* value) {
2221 2222
    inputs_[0] = value;
  }
2223

2224
  LOperand* value() { return inputs_[0]; }
2225

2226 2227
  DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value")
  DECLARE_HYDROGEN_ACCESSOR(CheckValue)
2228 2229 2230
};


2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243
class LCheckArrayBufferNotNeutered final
    : public LTemplateInstruction<0, 1, 0> {
 public:
  explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; }

  LOperand* view() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
                               "check-array-buffer-not-neutered")
  DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
};


2244
class LCheckInstanceType final : public LTemplateInstruction<0, 1, 0> {
2245
 public:
2246
  explicit LCheckInstanceType(LOperand* value) {
2247 2248
    inputs_[0] = value;
  }
2249

2250 2251
  LOperand* value() { return inputs_[0]; }

2252 2253 2254 2255 2256
  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
  DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
};


2257
class LCheckMaps final : public LTemplateInstruction<0, 1, 0> {
2258
 public:
2259
  explicit LCheckMaps(LOperand* value = NULL) {
2260 2261
    inputs_[0] = value;
  }
2262

2263 2264
  LOperand* value() { return inputs_[0]; }

2265 2266
  DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
  DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
2267 2268 2269
};


2270
class LCheckSmi final : public LTemplateInstruction<1, 1, 0> {
2271
 public:
2272
  explicit LCheckSmi(LOperand* value) {
2273 2274
    inputs_[0] = value;
  }
2275

2276 2277
  LOperand* value() { return inputs_[0]; }

2278 2279
  DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
};
2280

2281

2282
class LClampDToUint8 final : public LTemplateInstruction<1, 1, 0> {
2283
 public:
2284
  explicit LClampDToUint8(LOperand* unclamped) {
2285
    inputs_[0] = unclamped;
2286 2287 2288 2289
  }

  LOperand* unclamped() { return inputs_[0]; }

2290
  DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
2291 2292 2293
};


2294
class LClampIToUint8 final : public LTemplateInstruction<1, 1, 0> {
2295
 public:
2296 2297
  explicit LClampIToUint8(LOperand* unclamped) {
    inputs_[0] = unclamped;
2298 2299 2300 2301 2302 2303 2304 2305
  }

  LOperand* unclamped() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
};


2306
class LClampTToUint8 final : public LTemplateInstruction<1, 1, 1> {
2307
 public:
2308
  LClampTToUint8(LOperand* unclamped,
2309
                 LOperand* temp_xmm) {
2310
    inputs_[0] = unclamped;
2311
    temps_[0] = temp_xmm;
2312 2313 2314
  }

  LOperand* unclamped() { return inputs_[0]; }
2315
  LOperand* temp_xmm() { return temps_[0]; }
2316

2317
  DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
2318 2319 2320
};


2321
class LCheckNonSmi final : public LTemplateInstruction<0, 1, 0> {
2322 2323 2324
 public:
  explicit LCheckNonSmi(LOperand* value) {
    inputs_[0] = value;
2325 2326
  }

2327 2328
  LOperand* value() { return inputs_[0]; }

2329
  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
2330
  DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject)
2331 2332 2333
};


2334
class LAllocate final : public LTemplateInstruction<1, 2, 1> {
2335
 public:
2336 2337 2338
  LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
    inputs_[0] = context;
    inputs_[1] = size;
2339 2340 2341
    temps_[0] = temp;
  }

2342 2343
  LOperand* context() { return inputs_[0]; }
  LOperand* size() { return inputs_[1]; }
2344 2345 2346 2347 2348 2349
  LOperand* temp() { return temps_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
  DECLARE_HYDROGEN_ACCESSOR(Allocate)
};

2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362
class LFastAllocate final : public LTemplateInstruction<1, 1, 1> {
 public:
  LFastAllocate(LOperand* size, LOperand* temp) {
    inputs_[0] = size;
    temps_[0] = temp;
  }

  LOperand* size() const { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate")
  DECLARE_HYDROGEN_ACCESSOR(Allocate)
};
2363

2364
class LTypeof final : public LTemplateInstruction<1, 2, 0> {
2365
 public:
2366 2367 2368
  LTypeof(LOperand* context, LOperand* value) {
    inputs_[0] = context;
    inputs_[1] = value;
2369
  }
2370

2371 2372
  LOperand* context() { return inputs_[0]; }
  LOperand* value() { return inputs_[1]; }
2373

2374 2375 2376 2377
  DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
};


2378
class LTypeofIsAndBranch final : public LControlInstruction<1, 0> {
2379
 public:
2380 2381 2382
  explicit LTypeofIsAndBranch(LOperand* value) {
    inputs_[0] = value;
  }
2383

2384 2385
  LOperand* value() { return inputs_[0]; }

2386
  DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
2387
  DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
2388

2389
  Handle<String> type_literal() { return hydrogen()->type_literal(); }
2390

2391
  void PrintDataTo(StringStream* stream) override;
2392 2393 2394
};


2395
class LOsrEntry final : public LTemplateInstruction<0, 0, 0> {
2396
 public:
2397
  LOsrEntry() {}
2398

2399
  bool HasInterestingComment(LCodeGen* gen) const override { return false; }
2400 2401 2402 2403
  DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
};


2404
class LStackCheck final : public LTemplateInstruction<0, 1, 0> {
2405
 public:
2406 2407 2408 2409 2410 2411
  explicit LStackCheck(LOperand* context) {
    inputs_[0] = context;
  }

  LOperand* context() { return inputs_[0]; }

2412
  DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
2413 2414 2415 2416 2417 2418
  DECLARE_HYDROGEN_ACCESSOR(StackCheck)

  Label* done_label() { return &done_label_; }

 private:
  Label done_label_;
2419 2420 2421
};


2422
class LForInPrepareMap final : public LTemplateInstruction<1, 2, 0> {
2423
 public:
2424 2425 2426
  LForInPrepareMap(LOperand* context, LOperand* object) {
    inputs_[0] = context;
    inputs_[1] = object;
2427 2428
  }

2429 2430
  LOperand* context() { return inputs_[0]; }
  LOperand* object() { return inputs_[1]; }
2431 2432 2433 2434 2435

  DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
};


2436
class LForInCacheArray final : public LTemplateInstruction<1, 1, 0> {
2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451
 public:
  explicit LForInCacheArray(LOperand* map) {
    inputs_[0] = map;
  }

  LOperand* map() { return inputs_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")

  int idx() {
    return HForInCacheArray::cast(this->hydrogen_value())->idx();
  }
};


2452
class LCheckMapValue final : public LTemplateInstruction<0, 2, 0> {
2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465
 public:
  LCheckMapValue(LOperand* value, LOperand* map) {
    inputs_[0] = value;
    inputs_[1] = map;
  }

  LOperand* value() { return inputs_[0]; }
  LOperand* map() { return inputs_[1]; }

  DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
};


2466
class LLoadFieldByIndex final : public LTemplateInstruction<1, 2, 0> {
2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479
 public:
  LLoadFieldByIndex(LOperand* object, LOperand* index) {
    inputs_[0] = object;
    inputs_[1] = index;
  }

  LOperand* object() { return inputs_[0]; }
  LOperand* index() { return inputs_[1]; }

  DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
};


2480
class LChunkBuilder;
2481
class LPlatformChunk final : public LChunk {
2482
 public:
2483
  LPlatformChunk(CompilationInfo* info, HGraph* graph)
2484 2485
      : LChunk(info, graph),
        dehoisted_key_ids_(graph->GetMaximumValueID(), graph->zone()) { }
2486

2487 2488
  int GetNextSpillIndex(RegisterKind kind);
  LOperand* GetNextSpillSlot(RegisterKind kind);
2489 2490 2491 2492 2493 2494 2495
  BitVector* GetDehoistedKeyIds() { return &dehoisted_key_ids_; }
  bool IsDehoistedKey(HValue* value) {
    return dehoisted_key_ids_.Contains(value->id());
  }

 private:
  BitVector dehoisted_key_ids_;
2496 2497 2498
};


2499
class LChunkBuilder final : public LChunkBuilderBase {
2500
 public:
2501
  LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
2502
      : LChunkBuilderBase(info, graph),
2503 2504 2505
        current_instruction_(NULL),
        current_block_(NULL),
        next_block_(NULL),
2506
        allocator_(allocator) {}
2507

2508
  // Build the sequence for the graph.
2509
  LPlatformChunk* Build();
2510 2511 2512 2513 2514 2515

  // Declare methods that deal with the individual node types.
#define DECLARE_DO(type) LInstruction* Do##type(H##type* node);
  HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
#undef DECLARE_DO

2516 2517
  LInstruction* DoMathFloor(HUnaryMathOperation* instr);
  LInstruction* DoMathRound(HUnaryMathOperation* instr);
2518
  LInstruction* DoMathFround(HUnaryMathOperation* instr);
2519
  LInstruction* DoMathAbs(HUnaryMathOperation* instr);
2520
  LInstruction* DoMathCos(HUnaryMathOperation* instr);
2521 2522
  LInstruction* DoMathLog(HUnaryMathOperation* instr);
  LInstruction* DoMathExp(HUnaryMathOperation* instr);
2523
  LInstruction* DoMathSin(HUnaryMathOperation* instr);
2524 2525
  LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
  LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
2526
  LInstruction* DoMathClz32(HUnaryMathOperation* instr);
2527
  LInstruction* DoDivByPowerOf2I(HDiv* instr);
2528
  LInstruction* DoDivByConstI(HDiv* instr);
2529
  LInstruction* DoDivI(HDiv* instr);
2530
  LInstruction* DoModByPowerOf2I(HMod* instr);
2531
  LInstruction* DoModByConstI(HMod* instr);
2532 2533 2534
  LInstruction* DoModI(HMod* instr);
  LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr);
  LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr);
2535
  LInstruction* DoFlooringDivI(HMathFloorOfDiv* instr);
2536

2537 2538 2539 2540 2541 2542
 private:
  // Methods for getting operands for Use / Define / Temp.
  LUnallocated* ToUnallocated(Register reg);
  LUnallocated* ToUnallocated(XMMRegister reg);

  // Methods for setting up define-use relationships.
2543 2544 2545 2546
  MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
  MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
  MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
                                           XMMRegister fixed_register);
2547 2548 2549 2550 2551 2552 2553 2554 2555

  // A value that is guaranteed to be allocated to a register.
  // Operand created by UseRegister is guaranteed to be live until the end of
  // instruction. This means that register allocator will not reuse it's
  // register for any other operand inside instruction.
  // Operand created by UseRegisterAtStart is guaranteed to be live only at
  // instruction start. Register allocator is free to assign the same register
  // to some other operand used inside instruction (i.e. temporary or
  // output).
2556 2557
  MUST_USE_RESULT LOperand* UseRegister(HValue* value);
  MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
2558

2559
  // An input operand in a register that may be trashed.
2560
  MUST_USE_RESULT LOperand* UseTempRegister(HValue* value);
2561

2562 2563 2564
  // An input operand in a register that may be trashed or a constant operand.
  MUST_USE_RESULT LOperand* UseTempRegisterOrConstant(HValue* value);

2565
  // An input operand in a register or stack slot.
2566 2567
  MUST_USE_RESULT LOperand* Use(HValue* value);
  MUST_USE_RESULT LOperand* UseAtStart(HValue* value);
2568

2569
  // An input operand in a register, stack slot or a constant operand.
2570 2571
  MUST_USE_RESULT LOperand* UseOrConstant(HValue* value);
  MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value);
2572

2573
  // An input operand in a register or a constant operand.
2574 2575 2576
  MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
  MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);

2577 2578 2579
  // An input operand in a constant operand.
  MUST_USE_RESULT LOperand* UseConstant(HValue* value);

2580 2581
  // An input operand in register, stack slot or a constant operand.
  // Will not be moved to a register even if one is freely available.
2582
  MUST_USE_RESULT LOperand* UseAny(HValue* value) override;
2583

2584 2585 2586 2587
  // Temporary operand that must be in a register.
  MUST_USE_RESULT LUnallocated* TempRegister();
  MUST_USE_RESULT LOperand* FixedTemp(Register reg);
  MUST_USE_RESULT LOperand* FixedTemp(XMMRegister reg);
2588 2589 2590

  // Methods for setting up define-use relationships.
  // Return the same instruction that they are passed.
2591 2592 2593 2594 2595 2596 2597 2598 2599 2600
  LInstruction* Define(LTemplateResultInstruction<1>* instr,
                       LUnallocated* result);
  LInstruction* DefineAsRegister(LTemplateResultInstruction<1>* instr);
  LInstruction* DefineAsSpilled(LTemplateResultInstruction<1>* instr,
                                int index);
  LInstruction* DefineSameAsFirst(LTemplateResultInstruction<1>* instr);
  LInstruction* DefineFixed(LTemplateResultInstruction<1>* instr,
                            Register reg);
  LInstruction* DefineFixedDouble(LTemplateResultInstruction<1>* instr,
                                  XMMRegister reg);
2601 2602
  // Assigns an environment to an instruction.  An instruction which can
  // deoptimize must have an environment.
2603
  LInstruction* AssignEnvironment(LInstruction* instr);
2604 2605
  // Assigns a pointer map to an instruction.  An instruction which can
  // trigger a GC or a lazy deoptimization must have a pointer map.
2606 2607 2608 2609
  LInstruction* AssignPointerMap(LInstruction* instr);

  enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };

2610 2611 2612
  // Marks a call for the register allocator.  Assigns a pointer map to
  // support GC and lazy deoptimization.  Assigns an environment to support
  // eager deoptimization if CAN_DEOPTIMIZE_EAGERLY.
2613 2614 2615 2616 2617 2618
  LInstruction* MarkAsCall(
      LInstruction* instr,
      HInstruction* hinstr,
      CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);

  void VisitInstruction(HInstruction* current);
2619
  void AddInstruction(LInstruction* instr, HInstruction* current);
2620 2621

  void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block);
2622 2623 2624 2625
  LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr);
  LInstruction* DoArithmeticD(Token::Value op,
                              HArithmeticBinaryOperation* instr);
  LInstruction* DoArithmeticT(Token::Value op,
2626
                              HBinaryOperation* instr);
2627
  void FindDehoistedKeyDefinitions(HValue* candidate);
2628 2629 2630 2631 2632 2633

  HInstruction* current_instruction_;
  HBasicBlock* current_block_;
  HBasicBlock* next_block_;
  LAllocator* allocator_;

2634 2635 2636
  DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
};

2637 2638
#undef DECLARE_HYDROGEN_ACCESSOR
#undef DECLARE_CONCRETE_INSTRUCTION
2639

2640 2641
}  // namespace internal
}  // namespace v8
2642

2643
#endif  // V8_CRANKSHAFT_X64_LITHIUM_X64_H_