lithium-ia32.h 80.2 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 7

#ifndef V8_IA32_LITHIUM_IA32_H_
#define V8_IA32_LITHIUM_IA32_H_

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

namespace v8 {
namespace internal {

17 18 19 20
namespace compiler {
class RCodeVisualizer;
}

21 22 23
// Forward declarations.
class LCodeGen;

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


170
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)            \
171 172 173
  Opcode opcode() const final { return LInstruction::k##type; } \
  void CompileToNative(LCodeGen* generator) final;              \
  const char* Mnemonic() const final { return mnemonic; }       \
174 175 176
  static L##type* cast(LInstruction* instr) {                   \
    DCHECK(instr->Is##type());                                  \
    return reinterpret_cast<L##type*>(instr);                   \
177 178 179 180 181 182 183 184 185
  }


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


186
class LInstruction : public ZoneObject {
187 188
 public:
  LInstruction()
189 190
      : environment_(NULL),
        hydrogen_value_(NULL),
191 192 193
        bit_field_(IsCallBits::encode(false)) {
  }

194
  virtual ~LInstruction() {}
195 196 197

  virtual void CompileToNative(LCodeGen* generator) = 0;
  virtual const char* Mnemonic() const = 0;
198
  virtual void PrintTo(StringStream* stream);
199 200
  virtual void PrintDataTo(StringStream* stream);
  virtual void PrintOutputOperandTo(StringStream* stream);
201

202 203 204
  enum Opcode {
    // Declare a unique enum value for each instruction.
#define DECLARE_OPCODE(type) k##type,
205
    LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE) kAdapter,
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
    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; }
221

222 223
  virtual bool IsControl() const { return false; }

224 225 226
  // Try deleting this instruction if possible.
  virtual bool TryDelete() { return false; }

227 228 229
  void set_environment(LEnvironment* env) { environment_ = env; }
  LEnvironment* environment() const { return environment_; }
  bool HasEnvironment() const { return environment_ != NULL; }
230 231 232 233 234 235 236 237

  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(); }

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

238 239
  void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
  bool IsCall() const { return IsCallBits::decode(bit_field_); }
240 241

  // Interface to the register allocator and iterators.
242 243
  bool ClobbersTemps() const { return IsCall(); }
  bool ClobbersRegisters() const { return IsCall(); }
244
  virtual bool ClobbersDoubleRegisters(Isolate* isolate) const {
245
    return IsCall();
246
  }
247 248

  virtual bool HasResult() const = 0;
249
  virtual LOperand* result() const = 0;
250

251 252 253
  bool HasDoubleRegisterResult();
  bool HasDoubleRegisterInput();

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

257 258
  virtual bool HasInterestingComment(LCodeGen* gen) const { return true; }

259 260 261 262
#ifdef DEBUG
  void VerifyCall();
#endif

263 264 265
  virtual int InputCount() = 0;
  virtual LOperand* InputAt(int i) = 0;

266
 private:
267 268 269
  // Iterator support.
  friend class InputIterator;

270 271 272 273
  friend class TempIterator;
  virtual int TempCount() = 0;
  virtual LOperand* TempAt(int i) = 0;

274 275
  class IsCallBits: public BitField<bool, 0, 1> {};

276
  LEnvironment* environment_;
277 278
  SetOncePointer<LPointerMap> pointer_map_;
  HValue* hydrogen_value_;
279
  int bit_field_;
280 281 282
};


283
// R = number of result operands (0 or 1).
284 285
template<int R>
class LTemplateResultInstruction : public LInstruction {
286
 public:
287 288
  // Allow 0 or 1 output operands.
  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 299 300 301 302 303
};


// 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:
304 305
  EmbeddedContainer<LOperand*, I> inputs_;
  EmbeddedContainer<LOperand*, T> temps_;
306 307

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

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


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

326
  // Can't use the DECLARE-macro here because of sub-classes.
327 328
  bool IsGap() const final { return true; }
  void PrintDataTo(StringStream* stream) override;
329
  static LGap* cast(LInstruction* instr) {
330
    DCHECK(instr->IsGap());
331 332
    return reinterpret_cast<LGap*>(instr);
  }
333 334 335 336 337 338 339 340 341 342 343 344 345 346

  bool IsRedundant() const;

  HBasicBlock* block() const { return block_; }

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

347 348 349 350
  LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone)  {
    if (parallel_moves_[pos] == NULL) {
      parallel_moves_[pos] = new(zone) LParallelMove(zone);
    }
351 352 353 354 355 356 357 358 359 360 361 362 363
    return parallel_moves_[pos];
  }

  LParallelMove* GetParallelMove(InnerPosition pos)  {
    return parallel_moves_[pos];
  }

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


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
  bool ClobbersDoubleRegisters(Isolate* isolate) const override {
387 388
    return false;
  }
389 390

  bool jumps_to_join() const { return block_->predecessors()->length() > 1; }
391 392

 private:
393
  HBasicBlock* block_;
394 395 396
};


397 398 399 400 401 402
class LPrologue final : public LTemplateInstruction<0, 0, 0> {
 public:
  DECLARE_CONCRETE_INSTRUCTION(Prologue, "prologue")
};


403
class LLazyBailout final : public LTemplateInstruction<0, 0, 0> {
404 405 406 407 408
 public:
  DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
};


409
class LDummy final : public LTemplateInstruction<1, 0, 0> {
410
 public:
411
  LDummy() {}
412 413 414 415
  DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
};


416
class LDummyUse final : public LTemplateInstruction<1, 1, 0> {
417 418 419 420 421 422 423 424
 public:
  explicit LDummyUse(LOperand* value) {
    inputs_[0] = value;
  }
  DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
};


425
class LDeoptimize final : public LTemplateInstruction<0, 0, 0> {
426
 public:
427
  bool IsControl() const override { return true; }
428
  DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
429
  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
430 431 432
};


433
class LLabel final : public LGap {
434 435
 public:
  explicit LLabel(HBasicBlock* block)
fschneider@chromium.org's avatar
fschneider@chromium.org committed
436
      : LGap(block), replacement_(NULL) { }
437

438
  bool HasInterestingComment(LCodeGen* gen) const override { return false; }
439 440
  DECLARE_CONCRETE_INSTRUCTION(Label, "label")

441
  void PrintDataTo(StringStream* stream) override;
442

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

 private:
  Label label_;
  LLabel* replacement_;
};


457
class LParameter final : public LTemplateInstruction<1, 0, 0> {
458
 public:
459
  bool HasInterestingComment(LCodeGen* gen) const override { return false; }
460 461 462 463
  DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
};


464
class LCallStub final : public LTemplateInstruction<1, 1, 0> {
465
 public:
466 467 468 469
  explicit LCallStub(LOperand* context) {
    inputs_[0] = context;
  }

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

472 473 474 475 476
  DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
  DECLARE_HYDROGEN_ACCESSOR(CallStub)
};


477
class LUnknownOSRValue final : public LTemplateInstruction<1, 0, 0> {
478
 public:
479
  bool HasInterestingComment(LCodeGen* gen) const override { return false; }
480 481 482 483
  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
};


484
template<int I, int T>
485
class LControlInstruction: public LTemplateInstruction<0, I, T> {
486
 public:
487 488
  LControlInstruction() : false_label_(NULL), true_label_(NULL) { }

489
  bool IsControl() const final { return true; }
490

491 492
  int SuccessorCount() { return hydrogen()->SuccessorCount(); }
  HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516

  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(); }
517

518
 private:
519 520 521
  HControlInstruction* hydrogen() {
    return HControlInstruction::cast(this->hydrogen_value());
  }
522 523 524

  Label* false_label_;
  Label* true_label_;
525 526 527
};


528
class LWrapReceiver final : public LTemplateInstruction<1, 2, 1> {
529 530 531 532 533 534 535 536 537 538 539
 public:
  LWrapReceiver(LOperand* receiver,
                LOperand* function,
                LOperand* temp) {
    inputs_[0] = receiver;
    inputs_[1] = function;
    temps_[0] = temp;
  }

  LOperand* receiver() { return inputs_[0]; }
  LOperand* function() { return inputs_[1]; }
540 541 542
  LOperand* temp() { return temps_[0]; }

  DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
543
  DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
544 545 546
};


547
class LApplyArguments final : public LTemplateInstruction<1, 4, 0> {
548 549 550 551
 public:
  LApplyArguments(LOperand* function,
                  LOperand* receiver,
                  LOperand* length,
552
                  LOperand* elements) {
553 554 555 556
    inputs_[0] = function;
    inputs_[1] = receiver;
    inputs_[2] = length;
    inputs_[3] = elements;
557
  }
558

559 560 561 562
  LOperand* function() { return inputs_[0]; }
  LOperand* receiver() { return inputs_[1]; }
  LOperand* length() { return inputs_[2]; }
  LOperand* elements() { return inputs_[3]; }
563 564

  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
565 566 567
};


568
class LAccessArgumentsAt final : public LTemplateInstruction<1, 3, 0> {
569
 public:
570
  LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index) {
571 572 573
    inputs_[0] = arguments;
    inputs_[1] = length;
    inputs_[2] = index;
574
  }
575

576 577 578
  LOperand* arguments() { return inputs_[0]; }
  LOperand* length() { return inputs_[1]; }
  LOperand* index() { return inputs_[2]; }
579

580 581
  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")

582
  void PrintDataTo(StringStream* stream) override;
583 584 585
};


586
class LArgumentsLength final : public LTemplateInstruction<1, 1, 0> {
587
 public:
588 589 590
  explicit LArgumentsLength(LOperand* elements) {
    inputs_[0] = elements;
  }
591

592 593
  LOperand* elements() { return inputs_[0]; }

594 595 596 597
  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
};


598
class LArgumentsElements final : public LTemplateInstruction<1, 0, 0> {
599 600
 public:
  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
601
  DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements)
602 603 604
};


605
class LDebugBreak final : public LTemplateInstruction<0, 0, 0> {
606 607 608 609 610
 public:
  DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break")
};


611
class LModByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
 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_;
};


629
class LModByConstI final : public LTemplateInstruction<1, 1, 2> {
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653
 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_;
};


654
class LModI final : public LTemplateInstruction<1, 2, 1> {
655
 public:
656 657 658 659 660
  LModI(LOperand* left, LOperand* right, LOperand* temp) {
    inputs_[0] = left;
    inputs_[1] = right;
    temps_[0] = temp;
  }
661

662 663 664 665
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }
  LOperand* temp() { return temps_[0]; }

666 667 668 669 670
  DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
  DECLARE_HYDROGEN_ACCESSOR(Mod)
};


671
class LDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
 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_;
};


689
class LDivByConstI final : public LTemplateInstruction<1, 1, 2> {
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
 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_;
};


714
class LDivI final : public LTemplateInstruction<1, 2, 1> {
715
 public:
716 717 718
  LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
    inputs_[0] = dividend;
    inputs_[1] = divisor;
719 720
    temps_[0] = temp;
  }
721

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

726
  DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
727
  DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
728 729 730
};


731
class LFlooringDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
732
 public:
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
  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_;
};


750
class LFlooringDivByConstI final : public LTemplateInstruction<1, 1, 3> {
751
 public:
752 753 754
  LFlooringDivByConstI(LOperand* dividend,
                       int32_t divisor,
                       LOperand* temp1,
755 756
                       LOperand* temp2,
                       LOperand* temp3) {
757 758
    inputs_[0] = dividend;
    divisor_ = divisor;
759 760
    temps_[0] = temp1;
    temps_[1] = temp2;
761
    temps_[2] = temp3;
762 763
  }

764 765
  LOperand* dividend() { return inputs_[0]; }
  int32_t divisor() const { return divisor_; }
766 767
  LOperand* temp1() { return temps_[0]; }
  LOperand* temp2() { return temps_[1]; }
768
  LOperand* temp3() { return temps_[2]; }
769

770
  DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
771
  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
772 773 774

 private:
  int32_t divisor_;
775 776 777
};


778
class LFlooringDivI final : public LTemplateInstruction<1, 2, 1> {
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
 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)
};


795
class LMulI final : public LTemplateInstruction<1, 2, 1> {
796
 public:
797 798 799 800 801
  LMulI(LOperand* left, LOperand* right, LOperand* temp) {
    inputs_[0] = left;
    inputs_[1] = right;
    temps_[0] = temp;
  }
802

803 804 805 806
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }
  LOperand* temp() { return temps_[0]; }

807 808 809 810 811
  DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
  DECLARE_HYDROGEN_ACCESSOR(Mul)
};


812
class LCompareNumericAndBranch final : public LControlInstruction<2, 0> {
813
 public:
814
  LCompareNumericAndBranch(LOperand* left, LOperand* right) {
815 816 817
    inputs_[0] = left;
    inputs_[1] = right;
  }
818

819 820 821
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

822 823 824
  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
                               "compare-numeric-and-branch")
  DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
825

826 827
  Token::Value op() const { return hydrogen()->token(); }
  bool is_double() const {
828
    return hydrogen()->representation().IsDouble();
829
  }
830

831
  void PrintDataTo(StringStream* stream) override;
832 833 834
};


835
class LMathFloor final : public LTemplateInstruction<1, 1, 0> {
836
 public:
837 838 839 840 841 842 843 844 845 846 847
  explicit LMathFloor(LOperand* value) {
    inputs_[0] = value;
  }

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

  DECLARE_CONCRETE_INSTRUCTION(MathFloor, "math-floor")
  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
};


848
class LMathRound final : public LTemplateInstruction<1, 1, 1> {
849
 public:
850
  LMathRound(LOperand* value, LOperand* temp) {
851
    inputs_[0] = value;
852
    temps_[0] = temp;
853
  }
854

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

858
  DECLARE_CONCRETE_INSTRUCTION(MathRound, "math-round")
859
  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
860
};
861

862

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

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

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


873
class LMathAbs final : public LTemplateInstruction<1, 2, 0> {
874 875 876 877 878 879 880 881 882 883 884 885 886 887
 public:
  LMathAbs(LOperand* context, LOperand* value) {
    inputs_[1] = context;
    inputs_[0] = value;
  }

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

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


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

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

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


900
class LMathClz32 final : public LTemplateInstruction<1, 1, 0> {
901 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
class LMathExp final : public LTemplateInstruction<1, 1, 2> {
913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
 public:
  LMathExp(LOperand* value,
           LOperand* temp1,
           LOperand* temp2) {
    inputs_[0] = value;
    temps_[0] = temp1;
    temps_[1] = temp2;
    ExternalReference::InitializeMathExpData();
  }

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

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


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

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

939
  DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt")
940 941 942
};


943
class LMathPowHalf final : public LTemplateInstruction<1, 1, 1> {
944
 public:
945
  LMathPowHalf(LOperand* value, LOperand* temp) {
946 947 948 949 950 951 952
    inputs_[0] = value;
    temps_[0] = temp;
  }

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

953
  DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half")
954 955 956
};


957
class LCmpObjectEqAndBranch final : public LControlInstruction<2, 0> {
958
 public:
959
  LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
960 961 962
    inputs_[0] = left;
    inputs_[1] = right;
  }
963

964 965 966
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

967 968 969 970
  DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
};


971
class LCmpHoleAndBranch final : public LControlInstruction<1, 0> {
972 973 974 975 976 977 978 979 980
 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)
981 982 983
};


984
class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 1> {
985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
 public:
  LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
    inputs_[0] = value;
    temps_[0] = temp;
  }

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

  DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
                               "cmp-minus-zero-and-branch")
  DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
};


1000
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
1001 1002 1003 1004 1005 1006
 public:
  LIsStringAndBranch(LOperand* value, LOperand* temp) {
    inputs_[0] = value;
    temps_[0] = temp;
  }

1007 1008 1009
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

1010
  DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
1011
  DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
1012

1013
  void PrintDataTo(StringStream* stream) override;
1014 1015 1016
};


1017
class LIsSmiAndBranch final : public LControlInstruction<1, 0> {
1018
 public:
1019 1020 1021
  explicit LIsSmiAndBranch(LOperand* value) {
    inputs_[0] = value;
  }
1022

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

1025
  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
1026
  DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
1027

1028
  void PrintDataTo(StringStream* stream) override;
1029 1030 1031
};


1032
class LIsUndetectableAndBranch final : public LControlInstruction<1, 1> {
1033
 public:
1034
  LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
1035 1036 1037 1038
    inputs_[0] = value;
    temps_[0] = temp;
  }

1039 1040 1041
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

1042 1043
  DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
                               "is-undetectable-and-branch")
1044
  DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
1045

1046
  void PrintDataTo(StringStream* stream) override;
1047 1048 1049
};


1050
class LStringCompareAndBranch final : public LControlInstruction<3, 0> {
1051 1052 1053 1054 1055 1056 1057
 public:
  LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) {
    inputs_[0] = context;
    inputs_[1] = left;
    inputs_[2] = right;
  }

1058
  LOperand* context() { return inputs_[0]; }
1059 1060 1061
  LOperand* left() { return inputs_[1]; }
  LOperand* right() { return inputs_[2]; }

1062 1063 1064 1065
  DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
                               "string-compare-and-branch")
  DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)

1066
  void PrintDataTo(StringStream* stream) override;
1067 1068 1069 1070 1071

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


1072
class LHasInstanceTypeAndBranch final : public LControlInstruction<1, 1> {
1073
 public:
1074 1075 1076 1077
  LHasInstanceTypeAndBranch(LOperand* value, LOperand* temp) {
    inputs_[0] = value;
    temps_[0] = temp;
  }
1078

1079 1080 1081
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

1082 1083
  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
                               "has-instance-type-and-branch")
1084
  DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
1085

1086
  void PrintDataTo(StringStream* stream) override;
1087 1088 1089
};


1090
class LGetCachedArrayIndex final : public LTemplateInstruction<1, 1, 0> {
1091 1092 1093 1094 1095
 public:
  explicit LGetCachedArrayIndex(LOperand* value) {
    inputs_[0] = value;
  }

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

1098 1099 1100 1101 1102
  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
  DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
};


1103
class LHasCachedArrayIndexAndBranch final : public LControlInstruction<1, 0> {
1104
 public:
1105 1106 1107
  explicit LHasCachedArrayIndexAndBranch(LOperand* value) {
    inputs_[0] = value;
  }
1108

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

1111 1112
  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
                               "has-cached-array-index-and-branch")
1113

1114
  void PrintDataTo(StringStream* stream) override;
1115 1116 1117
};


1118
class LIsConstructCallAndBranch final : public LControlInstruction<0, 1> {
1119 1120 1121 1122 1123
 public:
  explicit LIsConstructCallAndBranch(LOperand* temp) {
    temps_[0] = temp;
  }

1124 1125
  LOperand* temp() { return temps_[0]; }

1126 1127 1128 1129 1130
  DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
                               "is-construct-call-and-branch")
};


1131
class LClassOfTestAndBranch final : public LControlInstruction<1, 2> {
1132
 public:
1133 1134 1135 1136 1137
  LClassOfTestAndBranch(LOperand* value, LOperand* temp, LOperand* temp2) {
    inputs_[0] = value;
    temps_[0] = temp;
    temps_[1] = temp2;
  }
1138

1139 1140 1141 1142
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }
  LOperand* temp2() { return temps_[1]; }

1143 1144
  DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
                               "class-of-test-and-branch")
1145
  DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
1146

1147
  void PrintDataTo(StringStream* stream) override;
1148 1149 1150
};


1151
class LCmpT final : public LTemplateInstruction<1, 3, 0> {
1152
 public:
1153
  LCmpT(LOperand* context, LOperand* left, LOperand* right) {
1154 1155 1156
    inputs_[0] = context;
    inputs_[1] = left;
    inputs_[2] = right;
1157
  }
1158

1159 1160
  DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
  DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
1161

1162
  Strength strength() { return hydrogen()->strength(); }
1163

1164
  LOperand* context() { return inputs_[0]; }
1165 1166 1167 1168
  Token::Value op() const { return hydrogen()->token(); }
};


1169
class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
1170
 public:
1171 1172 1173 1174
  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
    inputs_[0] = context;
    inputs_[1] = left;
    inputs_[2] = right;
1175
  }
1176

1177 1178 1179
  LOperand* context() const { return inputs_[0]; }
  LOperand* left() const { return inputs_[1]; }
  LOperand* right() const { return inputs_[2]; }
1180 1181

  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
1182 1183 1184
};


1185
class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 1> {
1186
 public:
1187 1188 1189 1190 1191
  LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype,
                                LOperand* scratch) {
    inputs_[0] = object;
    inputs_[1] = prototype;
    temps_[0] = scratch;
1192
  }
1193

1194 1195 1196
  LOperand* object() const { return inputs_[0]; }
  LOperand* prototype() const { return inputs_[1]; }
  LOperand* scratch() const { return temps_[0]; }
1197

1198 1199 1200
  DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch,
                               "has-in-prototype-chain-and-branch")
  DECLARE_HYDROGEN_ACCESSOR(HasInPrototypeChainAndBranch)
1201 1202 1203
};


1204
class LBoundsCheck final : public LTemplateInstruction<0, 2, 0> {
1205
 public:
1206 1207 1208 1209
  LBoundsCheck(LOperand* index, LOperand* length) {
    inputs_[0] = index;
    inputs_[1] = length;
  }
1210

1211 1212
  LOperand* index() { return inputs_[0]; }
  LOperand* length() { return inputs_[1]; }
1213 1214

  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
1215
  DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
1216 1217 1218
};


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

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

  DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
1230
  DECLARE_HYDROGEN_ACCESSOR(Bitwise)
1231 1232

  Token::Value op() const { return hydrogen()->op(); }
1233 1234 1235
};


1236
class LShiftI final : public LTemplateInstruction<1, 2, 0> {
1237 1238
 public:
  LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
1239 1240 1241 1242
      : op_(op), can_deopt_(can_deopt) {
    inputs_[0] = left;
    inputs_[1] = right;
  }
1243

1244 1245
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }
1246 1247 1248

  DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")

1249 1250 1251
  Token::Value op() const { return op_; }
  bool can_deopt() const { return can_deopt_; }

1252 1253 1254 1255 1256 1257
 private:
  Token::Value op_;
  bool can_deopt_;
};


1258
class LSubI final : public LTemplateInstruction<1, 2, 0> {
1259
 public:
1260 1261 1262 1263
  LSubI(LOperand* left, LOperand* right) {
    inputs_[0] = left;
    inputs_[1] = right;
  }
1264

1265 1266 1267
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

1268 1269 1270 1271 1272
  DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
  DECLARE_HYDROGEN_ACCESSOR(Sub)
};


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

1278
  int32_t value() const { return hydrogen()->Integer32Value(); }
1279 1280 1281
};


1282
class LConstantS final : public LTemplateInstruction<1, 0, 0> {
1283 1284 1285 1286 1287 1288 1289 1290
 public:
  DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
  DECLARE_HYDROGEN_ACCESSOR(Constant)

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


1291
class LConstantD final : public LTemplateInstruction<1, 0, 1> {
1292
 public:
1293 1294 1295 1296
  explicit LConstantD(LOperand* temp) {
    temps_[0] = temp;
  }

1297 1298
  LOperand* temp() { return temps_[0]; }

1299
  DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
1300
  DECLARE_HYDROGEN_ACCESSOR(Constant)
1301

1302
  uint64_t bits() const { return hydrogen()->DoubleValueAsBits(); }
1303 1304 1305
};


1306
class LConstantE final : public LTemplateInstruction<1, 0, 0> {
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
 public:
  DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
  DECLARE_HYDROGEN_ACCESSOR(Constant)

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


1317
class LConstantT final : public LTemplateInstruction<1, 0, 0> {
1318 1319
 public:
  DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
1320
  DECLARE_HYDROGEN_ACCESSOR(Constant)
1321

1322 1323 1324
  Handle<Object> value(Isolate* isolate) const {
    return hydrogen()->handle(isolate);
  }
1325 1326 1327
};


1328
class LBranch final : public LControlInstruction<1, 1> {
1329
 public:
1330
  LBranch(LOperand* value, LOperand* temp) {
1331
    inputs_[0] = value;
1332
    temps_[0] = temp;
1333
  }
1334

1335 1336 1337
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

1338
  DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
1339
  DECLARE_HYDROGEN_ACCESSOR(Branch)
1340

1341
  void PrintDataTo(StringStream* stream) override;
1342 1343 1344
};


1345
class LCmpMapAndBranch final : public LControlInstruction<1, 0> {
1346
 public:
1347 1348 1349
  explicit LCmpMapAndBranch(LOperand* value) {
    inputs_[0] = value;
  }
1350

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

1353
  DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
1354
  DECLARE_HYDROGEN_ACCESSOR(CompareMap)
1355

1356
  Handle<Map> map() const { return hydrogen()->map().handle(); }
1357 1358 1359
};


1360
class LMapEnumLength final : public LTemplateInstruction<1, 1, 0> {
1361 1362 1363 1364 1365
 public:
  explicit LMapEnumLength(LOperand* value) {
    inputs_[0] = value;
  }

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

1368 1369 1370 1371
  DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length")
};


1372
class LDateField final : public LTemplateInstruction<1, 1, 1> {
1373
 public:
1374
  LDateField(LOperand* date, LOperand* temp, Smi* index)
1375 1376 1377 1378 1379
      : index_(index) {
    inputs_[0] = date;
    temps_[0] = temp;
  }

1380 1381 1382
  LOperand* date() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

1383
  DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
1384 1385
  DECLARE_HYDROGEN_ACCESSOR(DateField)

1386
  Smi* index() const { return index_; }
1387 1388

 private:
1389
  Smi* index_;
1390 1391 1392
};


1393
class LSeqStringGetChar final : public LTemplateInstruction<1, 2, 0> {
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407
 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)
};


1408
class LSeqStringSetChar final : public LTemplateInstruction<1, 4, 0> {
1409
 public:
1410 1411
  LSeqStringSetChar(LOperand* context,
                    LOperand* string,
1412
                    LOperand* index,
1413
                    LOperand* value) {
1414 1415 1416 1417
    inputs_[0] = context;
    inputs_[1] = string;
    inputs_[2] = index;
    inputs_[3] = value;
1418 1419
  }

1420 1421 1422
  LOperand* string() { return inputs_[1]; }
  LOperand* index() { return inputs_[2]; }
  LOperand* value() { return inputs_[3]; }
1423 1424 1425 1426 1427 1428

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


1429
class LAddI final : public LTemplateInstruction<1, 2, 0> {
1430
 public:
1431 1432 1433 1434
  LAddI(LOperand* left, LOperand* right) {
    inputs_[0] = left;
    inputs_[1] = right;
  }
1435

1436 1437 1438
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

1439 1440 1441 1442 1443
  static bool UseLea(HAdd* add) {
    return !add->CheckFlag(HValue::kCanOverflow) &&
        add->BetterLeftOperand()->UseCount() > 1;
  }

1444 1445 1446 1447 1448
  DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
  DECLARE_HYDROGEN_ACCESSOR(Add)
};


1449
class LMathMinMax final : public LTemplateInstruction<1, 2, 0> {
1450 1451 1452 1453 1454 1455
 public:
  LMathMinMax(LOperand* left, LOperand* right) {
    inputs_[0] = left;
    inputs_[1] = right;
  }

1456 1457 1458
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

1459
  DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max")
1460 1461 1462 1463
  DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
};


1464
class LPower final : public LTemplateInstruction<1, 2, 0> {
1465
 public:
1466 1467 1468 1469
  LPower(LOperand* left, LOperand* right) {
    inputs_[0] = left;
    inputs_[1] = right;
  }
1470

1471 1472 1473
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

1474 1475 1476 1477 1478
  DECLARE_CONCRETE_INSTRUCTION(Power, "power")
  DECLARE_HYDROGEN_ACCESSOR(Power)
};


1479
class LArithmeticD final : public LTemplateInstruction<1, 2, 0> {
1480 1481
 public:
  LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
1482 1483 1484 1485
      : op_(op) {
    inputs_[0] = left;
    inputs_[1] = right;
  }
1486

1487 1488 1489
  LOperand* left() { return inputs_[0]; }
  LOperand* right() { return inputs_[1]; }

1490 1491
  Token::Value op() const { return op_; }

1492 1493 1494
  Opcode opcode() const override { return LInstruction::kArithmeticD; }
  void CompileToNative(LCodeGen* generator) override;
  const char* Mnemonic() const override;
1495 1496 1497 1498 1499 1500

 private:
  Token::Value op_;
};


1501
class LArithmeticT final : public LTemplateInstruction<1, 3, 0> {
1502
 public:
1503 1504 1505 1506
  LArithmeticT(Token::Value op,
               LOperand* context,
               LOperand* left,
               LOperand* right)
1507
      : op_(op) {
1508 1509 1510
    inputs_[0] = context;
    inputs_[1] = left;
    inputs_[2] = right;
1511
  }
1512

1513 1514 1515
  LOperand* context() { return inputs_[0]; }
  LOperand* left() { return inputs_[1]; }
  LOperand* right() { return inputs_[2]; }
conradw's avatar
conradw committed
1516
  Token::Value op() const { return op_; }
1517

1518 1519 1520
  Opcode opcode() const override { return LInstruction::kArithmeticT; }
  void CompileToNative(LCodeGen* generator) override;
  const char* Mnemonic() const override;
1521

conradw's avatar
conradw committed
1522 1523
  DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)

1524
  Strength strength() { return hydrogen()->strength(); }
1525 1526 1527 1528 1529 1530

 private:
  Token::Value op_;
};


1531
class LReturn final : public LTemplateInstruction<0, 3, 0> {
1532
 public:
1533 1534
  explicit LReturn(LOperand* value,
                   LOperand* context,
1535
                   LOperand* parameter_count) {
1536
    inputs_[0] = value;
1537
    inputs_[1] = context;
1538
    inputs_[2] = parameter_count;
1539
  }
1540

1541 1542 1543 1544
  bool has_constant_parameter_count() {
    return parameter_count()->IsConstantOperand();
  }
  LConstantOperand* constant_parameter_count() {
1545
    DCHECK(has_constant_parameter_count());
1546 1547 1548 1549
    return LConstantOperand::cast(parameter_count());
  }
  LOperand* parameter_count() { return inputs_[2]; }

1550
  DECLARE_CONCRETE_INSTRUCTION(Return, "return")
1551
  DECLARE_HYDROGEN_ACCESSOR(Return)
1552 1553 1554
};


1555
class LLoadNamedField final : public LTemplateInstruction<1, 1, 0> {
1556
 public:
1557
  explicit LLoadNamedField(LOperand* object) {
1558
    inputs_[0] = object;
1559 1560
  }

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

1563 1564
  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
  DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
1565 1566 1567
};


1568
class LLoadNamedGeneric final : public LTemplateInstruction<1, 2, 1> {
1569
 public:
1570
  LLoadNamedGeneric(LOperand* context, LOperand* object, LOperand* vector) {
1571 1572
    inputs_[0] = context;
    inputs_[1] = object;
1573
    temps_[0] = vector;
1574
  }
1575

1576 1577
  LOperand* context() { return inputs_[0]; }
  LOperand* object() { return inputs_[1]; }
1578
  LOperand* temp_vector() { return temps_[0]; }
1579

1580 1581 1582 1583 1584 1585 1586
  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
  DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)

  Handle<Object> name() const { return hydrogen()->name(); }
};


1587
class LLoadFunctionPrototype final : public LTemplateInstruction<1, 1, 1> {
1588
 public:
1589 1590 1591 1592
  LLoadFunctionPrototype(LOperand* function, LOperand* temp) {
    inputs_[0] = function;
    temps_[0] = temp;
  }
1593

1594 1595 1596
  LOperand* function() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

1597 1598 1599 1600 1601
  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
  DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
};


1602
class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
1603 1604 1605 1606 1607 1608 1609 1610
 public:
  DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root")
  DECLARE_HYDROGEN_ACCESSOR(LoadRoot)

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


1611
class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
1612
 public:
1613
  LLoadKeyed(LOperand* elements, LOperand* key) {
1614 1615 1616
    inputs_[0] = elements;
    inputs_[1] = key;
  }
1617 1618
  LOperand* elements() { return inputs_[0]; }
  LOperand* key() { return inputs_[1]; }
1619 1620 1621
  ElementsKind elements_kind() const {
    return hydrogen()->elements_kind();
  }
1622 1623 1624
  bool is_fixed_typed_array() const {
    return hydrogen()->is_fixed_typed_array();
  }
1625

1626 1627
  DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
  DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
1628

1629
  void PrintDataTo(StringStream* stream) override;
1630
  uint32_t base_offset() const { return hydrogen()->base_offset(); }
1631 1632 1633
  bool key_is_smi() {
    return hydrogen()->key()->representation().IsTagged();
  }
1634 1635 1636
};


1637 1638 1639
inline static bool ExternalArrayOpRequiresTemp(
    Representation key_representation,
    ElementsKind elements_kind) {
1640 1641 1642
  // 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.
1643
  return key_representation.IsSmi() &&
1644 1645
         (elements_kind == UINT8_ELEMENTS || elements_kind == INT8_ELEMENTS ||
          elements_kind == UINT8_CLAMPED_ELEMENTS);
1646 1647 1648
}


1649
class LLoadKeyedGeneric final : public LTemplateInstruction<1, 3, 1> {
1650
 public:
1651 1652
  LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key,
                    LOperand* vector) {
1653 1654 1655
    inputs_[0] = context;
    inputs_[1] = obj;
    inputs_[2] = key;
1656
    temps_[0] = vector;
1657
  }
1658

1659 1660 1661
  LOperand* context() { return inputs_[0]; }
  LOperand* object() { return inputs_[1]; }
  LOperand* key() { return inputs_[2]; }
1662
  LOperand* temp_vector() { return temps_[0]; }
1663 1664

  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
1665
  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
1666 1667 1668
};


1669
class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
1670
 public:
1671 1672
  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
                     LOperand* vector) {
1673 1674
    inputs_[0] = context;
    inputs_[1] = global_object;
1675
    temps_[0] = vector;
1676 1677
  }

1678 1679
  LOperand* context() { return inputs_[0]; }
  LOperand* global_object() { return inputs_[1]; }
1680
  LOperand* temp_vector() { return temps_[0]; }
1681

1682 1683 1684 1685
  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)

  Handle<Object> name() const { return hydrogen()->name(); }
1686
  TypeofMode typeof_mode() const { return hydrogen()->typeof_mode(); }
1687 1688 1689
};


1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705
class LLoadGlobalViaContext final : public LTemplateInstruction<1, 1, 1> {
 public:
  explicit LLoadGlobalViaContext(LOperand* context) { inputs_[0] = context; }

  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalViaContext, "load-global-via-context")
  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalViaContext)

  void PrintDataTo(StringStream* stream) override;

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

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


1706
class LLoadContextSlot final : public LTemplateInstruction<1, 1, 0> {
1707
 public:
1708 1709 1710 1711
  explicit LLoadContextSlot(LOperand* context) {
    inputs_[0] = context;
  }

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

1714 1715 1716
  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
  DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)

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

1719
  void PrintDataTo(StringStream* stream) override;
1720 1721 1722
};


1723
class LStoreContextSlot final : public LTemplateInstruction<0, 2, 1> {
1724 1725 1726 1727 1728 1729 1730
 public:
  LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
    inputs_[0] = context;
    inputs_[1] = value;
    temps_[0] = temp;
  }

1731 1732 1733 1734
  LOperand* context() { return inputs_[0]; }
  LOperand* value() { return inputs_[1]; }
  LOperand* temp() { return temps_[0]; }

1735 1736 1737 1738 1739
  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
  DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)

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

1740
  void PrintDataTo(StringStream* stream) override;
1741 1742 1743
};


1744
class LPushArgument final : public LTemplateInstruction<0, 1, 0> {
1745
 public:
1746 1747 1748
  explicit LPushArgument(LOperand* value) {
    inputs_[0] = value;
  }
1749

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

1752 1753 1754 1755
  DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument")
};


1756
class LDrop final : public LTemplateInstruction<0, 0, 0> {
1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768
 public:
  explicit LDrop(int count) : count_(count) { }

  int count() const { return count_; }

  DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")

 private:
  int count_;
};


1769
class LStoreCodeEntry final : public LTemplateInstruction<0, 2, 0> {
1770 1771 1772
 public:
  LStoreCodeEntry(LOperand* function, LOperand* code_object) {
    inputs_[0] = function;
1773
    inputs_[1] = code_object;
1774 1775 1776
  }

  LOperand* function() { return inputs_[0]; }
1777
  LOperand* code_object() { return inputs_[1]; }
1778

1779
  void PrintDataTo(StringStream* stream) override;
1780 1781 1782 1783 1784 1785

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


1786
class LInnerAllocatedObject final : public LTemplateInstruction<1, 2, 0> {
1787
 public:
1788
  LInnerAllocatedObject(LOperand* base_object, LOperand* offset) {
1789
    inputs_[0] = base_object;
1790
    inputs_[1] = offset;
1791 1792
  }

1793 1794
  LOperand* base_object() const { return inputs_[0]; }
  LOperand* offset() const { return inputs_[1]; }
1795

1796
  void PrintDataTo(StringStream* stream) override;
1797

1798
  DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object")
1799 1800 1801
};


1802
class LThisFunction final : public LTemplateInstruction<1, 0, 0> {
1803
 public:
1804
  DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
1805
  DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
1806 1807 1808
};


1809
class LContext final : public LTemplateInstruction<1, 0, 0> {
1810 1811
 public:
  DECLARE_CONCRETE_INSTRUCTION(Context, "context")
1812
  DECLARE_HYDROGEN_ACCESSOR(Context)
1813 1814 1815
};


1816
class LDeclareGlobals final : public LTemplateInstruction<0, 1, 0> {
1817 1818 1819 1820 1821
 public:
  explicit LDeclareGlobals(LOperand* context) {
    inputs_[0] = context;
  }

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

1824 1825 1826 1827 1828
  DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
  DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
};


1829
class LCallJSFunction final : public LTemplateInstruction<1, 1, 0> {
1830
 public:
1831 1832 1833 1834 1835 1836 1837 1838
  explicit LCallJSFunction(LOperand* function) {
    inputs_[0] = function;
  }

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

  DECLARE_CONCRETE_INSTRUCTION(CallJSFunction, "call-js-function")
  DECLARE_HYDROGEN_ACCESSOR(CallJSFunction)
1839

1840
  void PrintDataTo(StringStream* stream) override;
1841 1842 1843 1844 1845

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


1846
class LCallWithDescriptor final : public LTemplateResultInstruction<1> {
1847
 public:
1848
  LCallWithDescriptor(CallInterfaceDescriptor descriptor,
1849
                      const ZoneList<LOperand*>& operands, Zone* zone)
1850 1851 1852 1853 1854 1855
      : inputs_(descriptor.GetRegisterParameterCount() +
                    kImplicitRegisterParameterCount,
                zone) {
    DCHECK(descriptor.GetRegisterParameterCount() +
               kImplicitRegisterParameterCount ==
           operands.length());
1856
    inputs_.AddAll(operands, zone);
1857 1858
  }

1859
  LOperand* target() const { return inputs_[0]; }
1860

1861 1862
  DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)

1863 1864 1865 1866
  // The target and context are passed as implicit parameters that are not
  // explicitly listed in the descriptor.
  static const int kImplicitRegisterParameterCount = 2;

1867 1868
 private:
  DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
1869

1870
  void PrintDataTo(StringStream* stream) override;
1871 1872 1873

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

1874
  ZoneList<LOperand*> inputs_;
1875

1876
  // Iterator support.
1877 1878
  int InputCount() final { return inputs_.length(); }
  LOperand* InputAt(int i) final { return inputs_[i]; }
1879

1880 1881
  int TempCount() final { return 0; }
  LOperand* TempAt(int i) final { return NULL; }
1882 1883 1884
};


1885
class LInvokeFunction final : public LTemplateInstruction<1, 2, 0> {
1886
 public:
1887
  LInvokeFunction(LOperand* context, LOperand* function) {
1888
    inputs_[0] = context;
1889
    inputs_[1] = function;
1890 1891
  }

1892
  LOperand* context() { return inputs_[0]; }
1893
  LOperand* function() { return inputs_[1]; }
1894

1895 1896
  DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
  DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
1897

1898
  void PrintDataTo(StringStream* stream) override;
1899 1900 1901 1902 1903

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


1904
class LCallFunction final : public LTemplateInstruction<1, 2, 2> {
1905
 public:
1906 1907
  LCallFunction(LOperand* context, LOperand* function, LOperand* slot,
                LOperand* vector) {
1908
    inputs_[0] = context;
1909
    inputs_[1] = function;
1910 1911
    temps_[0] = slot;
    temps_[1] = vector;
1912 1913
  }

1914 1915
  LOperand* context() { return inputs_[0]; }
  LOperand* function() { return inputs_[1]; }
1916 1917
  LOperand* temp_slot() { return temps_[0]; }
  LOperand* temp_vector() { return temps_[1]; }
1918

1919 1920 1921
  DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
  DECLARE_HYDROGEN_ACCESSOR(CallFunction)

1922
  void PrintDataTo(StringStream* stream) override;
1923
  int arity() const { return hydrogen()->argument_count() - 1; }
1924 1925 1926
};


1927
class LCallNew final : public LTemplateInstruction<1, 2, 0> {
1928
 public:
1929 1930 1931
  LCallNew(LOperand* context, LOperand* constructor) {
    inputs_[0] = context;
    inputs_[1] = constructor;
1932
  }
1933

1934 1935 1936
  LOperand* context() { return inputs_[0]; }
  LOperand* constructor() { return inputs_[1]; }

1937 1938 1939
  DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
  DECLARE_HYDROGEN_ACCESSOR(CallNew)

1940
  void PrintDataTo(StringStream* stream) override;
1941 1942 1943 1944 1945

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


1946
class LCallNewArray final : public LTemplateInstruction<1, 2, 0> {
1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958
 public:
  LCallNewArray(LOperand* context, LOperand* constructor) {
    inputs_[0] = context;
    inputs_[1] = constructor;
  }

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

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

1959
  void PrintDataTo(StringStream* stream) override;
1960 1961 1962 1963 1964

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


1965
class LCallRuntime final : public LTemplateInstruction<1, 1, 0> {
1966
 public:
1967 1968 1969
  explicit LCallRuntime(LOperand* context) {
    inputs_[0] = context;
  }
1970 1971 1972

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

1973 1974 1975
  DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
  DECLARE_HYDROGEN_ACCESSOR(CallRuntime)

1976
  bool ClobbersDoubleRegisters(Isolate* isolate) const override {
1977 1978 1979
    return save_doubles() == kDontSaveFPRegs;
  }

1980
  const Runtime::Function* function() const { return hydrogen()->function(); }
1981
  int arity() const { return hydrogen()->argument_count(); }
1982
  SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); }
1983 1984 1985
};


1986
class LInteger32ToDouble final : public LTemplateInstruction<1, 1, 0> {
1987
 public:
1988 1989 1990
  explicit LInteger32ToDouble(LOperand* value) {
    inputs_[0] = value;
  }
1991

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

1994 1995 1996 1997
  DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
};


1998
class LUint32ToDouble final : public LTemplateInstruction<1, 1, 0> {
1999
 public:
2000
  explicit LUint32ToDouble(LOperand* value) {
2001 2002 2003
    inputs_[0] = value;
  }

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

2006 2007 2008 2009
  DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
};


2010
class LNumberTagI final : public LTemplateInstruction<1, 1, 1> {
2011
 public:
2012
  LNumberTagI(LOperand* value, LOperand* temp) {
2013
    inputs_[0] = value;
2014
    temps_[0] = temp;
2015
  }
2016

2017
  LOperand* value() { return inputs_[0]; }
2018
  LOperand* temp() { return temps_[0]; }
2019

2020 2021 2022 2023
  DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i")
};


2024
class LNumberTagU final : public LTemplateInstruction<1, 1, 1> {
2025
 public:
2026
  LNumberTagU(LOperand* value, LOperand* temp) {
2027
    inputs_[0] = value;
2028
    temps_[0] = temp;
2029 2030
  }

2031
  LOperand* value() { return inputs_[0]; }
2032
  LOperand* temp() { return temps_[0]; }
2033

2034 2035 2036 2037
  DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
};


2038
class LNumberTagD final : public LTemplateInstruction<1, 1, 1> {
2039
 public:
2040
  LNumberTagD(LOperand* value, LOperand* temp) {
2041 2042 2043
    inputs_[0] = value;
    temps_[0] = temp;
  }
2044

2045 2046 2047
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

2048
  DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
2049
  DECLARE_HYDROGEN_ACCESSOR(Change)
2050 2051 2052 2053
};


// Sometimes truncating conversion from a tagged value to an int32.
2054
class LDoubleToI final : public LTemplateInstruction<1, 1, 1> {
2055
 public:
2056 2057 2058 2059
  LDoubleToI(LOperand* value, LOperand* temp) {
    inputs_[0] = value;
    temps_[0] = temp;
  }
2060

2061 2062 2063
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

2064
  DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
2065
  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
2066 2067 2068 2069 2070

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


2071
class LDoubleToSmi final : public LTemplateInstruction<1, 1, 0> {
2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083
 public:
  explicit LDoubleToSmi(LOperand* value) {
    inputs_[0] = value;
  }

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

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


2084
// Truncating conversion from a tagged value to an int32.
2085
class LTaggedToI final : public LTemplateInstruction<1, 1, 1> {
2086
 public:
2087 2088 2089 2090
  LTaggedToI(LOperand* value, LOperand* temp) {
    inputs_[0] = value;
    temps_[0] = temp;
  }
2091

2092 2093 2094
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

2095
  DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
2096
  DECLARE_HYDROGEN_ACCESSOR(Change)
2097 2098 2099 2100 2101

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


2102
class LSmiTag final : public LTemplateInstruction<1, 1, 0> {
2103
 public:
2104 2105 2106
  explicit LSmiTag(LOperand* value) {
    inputs_[0] = value;
  }
2107

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

2110
  DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
2111
  DECLARE_HYDROGEN_ACCESSOR(Change)
2112 2113 2114
};


2115
class LNumberUntagD final : public LTemplateInstruction<1, 1, 1> {
2116
 public:
2117
  explicit LNumberUntagD(LOperand* value, LOperand* temp) {
2118
    inputs_[0] = value;
2119
    temps_[0] = temp;
2120
  }
2121

2122 2123 2124
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

2125
  DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
2126
  DECLARE_HYDROGEN_ACCESSOR(Change);
2127 2128 2129
};


2130
class LSmiUntag final : public LTemplateInstruction<1, 1, 0> {
2131
 public:
2132 2133 2134 2135
  LSmiUntag(LOperand* value, bool needs_check)
      : needs_check_(needs_check) {
    inputs_[0] = value;
  }
2136

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

2139 2140 2141 2142 2143 2144 2145 2146 2147
  DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")

  bool needs_check() const { return needs_check_; }

 private:
  bool needs_check_;
};


2148
class LStoreNamedField final : public LTemplateInstruction<0, 2, 2> {
2149
 public:
2150 2151
  LStoreNamedField(LOperand* obj,
                   LOperand* val,
2152 2153
                   LOperand* temp,
                   LOperand* temp_map) {
2154 2155
    inputs_[0] = obj;
    inputs_[1] = val;
2156
    temps_[0] = temp;
2157
    temps_[1] = temp_map;
2158
  }
2159

2160 2161 2162
  LOperand* object() { return inputs_[0]; }
  LOperand* value() { return inputs_[1]; }
  LOperand* temp() { return temps_[0]; }
2163
  LOperand* temp_map() { return temps_[1]; }
2164

2165 2166
  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
  DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
2167

2168
  void PrintDataTo(StringStream* stream) override;
2169 2170 2171
};


2172
class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
2173
 public:
2174 2175
  LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value,
                     LOperand* slot, LOperand* vector) {
2176 2177 2178
    inputs_[0] = context;
    inputs_[1] = object;
    inputs_[2] = value;
2179 2180
    temps_[0] = slot;
    temps_[1] = vector;
2181
  }
2182

2183 2184 2185
  LOperand* context() { return inputs_[0]; }
  LOperand* object() { return inputs_[1]; }
  LOperand* value() { return inputs_[2]; }
2186 2187
  LOperand* temp_slot() { return temps_[0]; }
  LOperand* temp_vector() { return temps_[1]; }
2188

2189
  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
2190
  DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
2191

2192
  void PrintDataTo(StringStream* stream) override;
2193
  Handle<Object> name() const { return hydrogen()->name(); }
2194
  LanguageMode language_mode() { return hydrogen()->language_mode(); }
2195 2196 2197
};


2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219
class LStoreGlobalViaContext final : public LTemplateInstruction<0, 2, 0> {
 public:
  LStoreGlobalViaContext(LOperand* context, LOperand* value) {
    inputs_[0] = context;
    inputs_[1] = value;
  }

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

  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalViaContext,
                               "store-global-via-context")
  DECLARE_HYDROGEN_ACCESSOR(StoreGlobalViaContext)

  void PrintDataTo(StringStream* stream) override;

  int depth() { return hydrogen()->depth(); }
  int slot_index() { return hydrogen()->slot_index(); }
  LanguageMode language_mode() { return hydrogen()->language_mode(); }
};


2220
class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
2221
 public:
2222
  LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) {
2223 2224 2225
    inputs_[0] = obj;
    inputs_[1] = key;
    inputs_[2] = val;
2226
  }
2227

2228 2229 2230
  bool is_fixed_typed_array() const {
    return hydrogen()->is_fixed_typed_array();
  }
2231 2232 2233
  LOperand* elements() { return inputs_[0]; }
  LOperand* key() { return inputs_[1]; }
  LOperand* value() { return inputs_[2]; }
2234 2235 2236
  ElementsKind elements_kind() const {
    return hydrogen()->elements_kind();
  }
2237

2238 2239
  DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
  DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
2240

2241
  void PrintDataTo(StringStream* stream) override;
2242
  uint32_t base_offset() const { return hydrogen()->base_offset(); }
2243
  bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
2244 2245 2246
};


2247
class LStoreKeyedGeneric final : public LTemplateInstruction<0, 4, 2> {
2248
 public:
2249 2250
  LStoreKeyedGeneric(LOperand* context, LOperand* object, LOperand* key,
                     LOperand* value, LOperand* slot, LOperand* vector) {
2251 2252 2253 2254
    inputs_[0] = context;
    inputs_[1] = object;
    inputs_[2] = key;
    inputs_[3] = value;
2255 2256
    temps_[0] = slot;
    temps_[1] = vector;
2257
  }
2258

2259 2260 2261 2262
  LOperand* context() { return inputs_[0]; }
  LOperand* object() { return inputs_[1]; }
  LOperand* key() { return inputs_[2]; }
  LOperand* value() { return inputs_[3]; }
2263 2264
  LOperand* temp_slot() { return temps_[0]; }
  LOperand* temp_vector() { return temps_[1]; }
2265

2266
  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
mmaly@chromium.org's avatar
mmaly@chromium.org committed
2267
  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
2268

2269
  void PrintDataTo(StringStream* stream) override;
2270

2271
  LanguageMode language_mode() { return hydrogen()->language_mode(); }
2272 2273 2274
};


2275
class LTransitionElementsKind final : public LTemplateInstruction<0, 2, 2> {
2276 2277
 public:
  LTransitionElementsKind(LOperand* object,
2278
                          LOperand* context,
2279
                          LOperand* new_map_temp,
2280
                          LOperand* temp) {
2281
    inputs_[0] = object;
2282
    inputs_[1] = context;
2283
    temps_[0] = new_map_temp;
2284
    temps_[1] = temp;
2285 2286
  }

2287
  LOperand* context() { return inputs_[1]; }
2288 2289 2290 2291
  LOperand* object() { return inputs_[0]; }
  LOperand* new_map_temp() { return temps_[0]; }
  LOperand* temp() { return temps_[1]; }

2292 2293 2294 2295
  DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
                               "transition-elements-kind")
  DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)

2296
  void PrintDataTo(StringStream* stream) override;
2297

2298 2299 2300 2301
  Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
  Handle<Map> transitioned_map() {
    return hydrogen()->transitioned_map().handle();
  }
2302 2303
  ElementsKind from_kind() { return hydrogen()->from_kind(); }
  ElementsKind to_kind() { return hydrogen()->to_kind(); }
2304 2305 2306
};


2307
class LTrapAllocationMemento final : public LTemplateInstruction<0, 1, 1> {
2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322
 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")
};


2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344
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")
};


2345
class LStringAdd final : public LTemplateInstruction<1, 3, 0> {
2346
 public:
2347 2348 2349 2350
  LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
    inputs_[0] = context;
    inputs_[1] = left;
    inputs_[2] = right;
2351 2352
  }

2353 2354 2355
  LOperand* context() { return inputs_[0]; }
  LOperand* left() { return inputs_[1]; }
  LOperand* right() { return inputs_[2]; }
2356 2357 2358

  DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
  DECLARE_HYDROGEN_ACCESSOR(StringAdd)
2359 2360 2361
};


2362
class LStringCharCodeAt final : public LTemplateInstruction<1, 3, 0> {
2363
 public:
2364 2365 2366 2367
  LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
    inputs_[0] = context;
    inputs_[1] = string;
    inputs_[2] = index;
2368 2369
  }

2370 2371 2372
  LOperand* context() { return inputs_[0]; }
  LOperand* string() { return inputs_[1]; }
  LOperand* index() { return inputs_[2]; }
2373 2374 2375

  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
  DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
2376 2377 2378
};


2379
class LStringCharFromCode final : public LTemplateInstruction<1, 2, 0> {
2380
 public:
2381 2382 2383
  LStringCharFromCode(LOperand* context, LOperand* char_code) {
    inputs_[0] = context;
    inputs_[1] = char_code;
2384 2385
  }

2386 2387
  LOperand* context() { return inputs_[0]; }
  LOperand* char_code() { return inputs_[1]; }
2388 2389 2390

  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
  DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
2391 2392 2393
};


2394
class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
2395
 public:
2396
  explicit LCheckValue(LOperand* value) {
2397 2398
    inputs_[0] = value;
  }
2399

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

2402 2403
  DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value")
  DECLARE_HYDROGEN_ACCESSOR(CheckValue)
2404 2405 2406
};


2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423
class LCheckArrayBufferNotNeutered final
    : public LTemplateInstruction<0, 1, 1> {
 public:
  explicit LCheckArrayBufferNotNeutered(LOperand* view, LOperand* scratch) {
    inputs_[0] = view;
    temps_[0] = scratch;
  }

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

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


2424
class LCheckInstanceType final : public LTemplateInstruction<0, 1, 1> {
2425
 public:
2426 2427 2428 2429
  LCheckInstanceType(LOperand* value, LOperand* temp) {
    inputs_[0] = value;
    temps_[0] = temp;
  }
2430

2431 2432 2433
  LOperand* value() { return inputs_[0]; }
  LOperand* temp() { return temps_[0]; }

2434 2435 2436 2437 2438
  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
  DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
};


2439
class LCheckMaps final : public LTemplateInstruction<0, 1, 0> {
2440
 public:
2441
  explicit LCheckMaps(LOperand* value = NULL) {
2442 2443
    inputs_[0] = value;
  }
2444

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

2447 2448
  DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
  DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
2449 2450 2451
};


2452
class LCheckSmi final : public LTemplateInstruction<1, 1, 0> {
2453
 public:
2454
  explicit LCheckSmi(LOperand* value) {
2455 2456
    inputs_[0] = value;
  }
2457

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

2460 2461
  DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
};
2462

2463

2464
class LClampDToUint8 final : public LTemplateInstruction<1, 1, 0> {
2465
 public:
2466
  explicit LClampDToUint8(LOperand* value) {
2467 2468 2469 2470 2471
    inputs_[0] = value;
  }

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

2472
  DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
2473 2474 2475
};


2476
class LClampIToUint8 final : public LTemplateInstruction<1, 1, 0> {
2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487
 public:
  explicit LClampIToUint8(LOperand* value) {
    inputs_[0] = value;
  }

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

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


2488
class LClampTToUint8 final : public LTemplateInstruction<1, 1, 1> {
2489
 public:
2490
  LClampTToUint8(LOperand* value, LOperand* temp_xmm) {
2491
    inputs_[0] = value;
2492
    temps_[0] = temp_xmm;
2493 2494 2495
  }

  LOperand* unclamped() { return inputs_[0]; }
2496
  LOperand* temp_xmm() { return temps_[0]; }
2497

2498
  DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
2499 2500 2501
};


2502
class LCheckNonSmi final : public LTemplateInstruction<0, 1, 0> {
2503 2504 2505
 public:
  explicit LCheckNonSmi(LOperand* value) {
    inputs_[0] = value;
2506 2507
  }

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

2510
  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
2511
  DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject)
2512 2513 2514
};


2515
class LDoubleBits final : public LTemplateInstruction<1, 1, 0> {
2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527
 public:
  explicit LDoubleBits(LOperand* value) {
    inputs_[0] = value;
  }

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

  DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
  DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
};


2528
class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541
 public:
  LConstructDouble(LOperand* hi, LOperand* lo) {
    inputs_[0] = hi;
    inputs_[1] = lo;
  }

  LOperand* hi() { return inputs_[0]; }
  LOperand* lo() { return inputs_[1]; }

  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
};


2542
class LAllocate final : public LTemplateInstruction<1, 2, 1> {
2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558
 public:
  LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
    inputs_[0] = context;
    inputs_[1] = size;
    temps_[0] = temp;
  }

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

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


2559
class LRegExpLiteral final : public LTemplateInstruction<1, 1, 0> {
2560
 public:
2561 2562 2563 2564 2565 2566
  explicit LRegExpLiteral(LOperand* context) {
    inputs_[0] = context;
  }

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

2567 2568 2569 2570 2571
  DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
  DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
};


2572
class LToFastProperties final : public LTemplateInstruction<1, 1, 0> {
2573 2574 2575 2576 2577
 public:
  explicit LToFastProperties(LOperand* value) {
    inputs_[0] = value;
  }

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

2580 2581 2582 2583 2584
  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
  DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
};


2585
class LTypeof final : public LTemplateInstruction<1, 2, 0> {
2586
 public:
2587 2588 2589
  LTypeof(LOperand* context, LOperand* value) {
    inputs_[0] = context;
    inputs_[1] = value;
2590
  }
2591

2592 2593 2594
  LOperand* context() { return inputs_[0]; }
  LOperand* value() { return inputs_[1]; }

2595 2596 2597 2598
  DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
};


2599
class LTypeofIsAndBranch final : public LControlInstruction<1, 0> {
2600
 public:
2601 2602 2603
  explicit LTypeofIsAndBranch(LOperand* value) {
    inputs_[0] = value;
  }
2604

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

2607
  DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
2608
  DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
2609

2610
  Handle<String> type_literal() { return hydrogen()->type_literal(); }
2611

2612
  void PrintDataTo(StringStream* stream) override;
2613 2614 2615
};


2616
class LOsrEntry final : public LTemplateInstruction<0, 0, 0> {
2617
 public:
2618
  bool HasInterestingComment(LCodeGen* gen) const override { return false; }
2619 2620 2621 2622
  DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
};


2623
class LStackCheck final : public LTemplateInstruction<0, 1, 0> {
2624
 public:
2625 2626 2627 2628 2629 2630
  explicit LStackCheck(LOperand* context) {
    inputs_[0] = context;
  }

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

2631
  DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
2632 2633 2634 2635 2636 2637
  DECLARE_HYDROGEN_ACCESSOR(StackCheck)

  Label* done_label() { return &done_label_; }

 private:
  Label done_label_;
2638 2639 2640
};


2641
class LForInPrepareMap final : public LTemplateInstruction<1, 2, 0> {
2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654
 public:
  LForInPrepareMap(LOperand* context, LOperand* object) {
    inputs_[0] = context;
    inputs_[1] = object;
  }

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

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


2655
class LForInCacheArray final : public LTemplateInstruction<1, 1, 0> {
2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670
 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();
  }
};


2671
class LCheckMapValue final : public LTemplateInstruction<0, 2, 0> {
2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684
 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")
};


2685
class LLoadFieldByIndex final : public LTemplateInstruction<1, 2, 0> {
2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698
 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")
};


2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727
class LStoreFrameContext: public LTemplateInstruction<0, 1, 0> {
 public:
  explicit LStoreFrameContext(LOperand* context) {
    inputs_[0] = context;
  }

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

  DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext, "store-frame-context")
};


class LAllocateBlockContext: public LTemplateInstruction<1, 2, 0> {
 public:
  LAllocateBlockContext(LOperand* context, LOperand* function) {
    inputs_[0] = context;
    inputs_[1] = function;
  }

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

  Handle<ScopeInfo> scope_info() { return hydrogen()->scope_info(); }

  DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext, "allocate-block-context")
  DECLARE_HYDROGEN_ACCESSOR(AllocateBlockContext)
};


2728
class LChunkBuilder;
2729
class LPlatformChunk final : public LChunk {
2730
 public:
2731 2732
  LPlatformChunk(CompilationInfo* info, HGraph* graph)
      : LChunk(info, graph),
2733
        num_double_slots_(0) { }
2734

2735 2736
  int GetNextSpillIndex(RegisterKind kind);
  LOperand* GetNextSpillSlot(RegisterKind kind);
2737

2738
  int num_double_slots() const { return num_double_slots_; }
2739

2740
 private:
2741
  int num_double_slots_;
2742 2743 2744
};


2745
class LChunkBuilder final : public LChunkBuilderBase {
2746
 public:
2747
  LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
2748
      : LChunkBuilderBase(info, graph),
2749 2750 2751
        current_instruction_(NULL),
        current_block_(NULL),
        next_block_(NULL),
2752
        allocator_(allocator) {}
2753

2754
  // Build the sequence for the graph.
2755
  LPlatformChunk* Build();
2756 2757 2758 2759 2760 2761

  // 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

2762 2763
  LInstruction* DoMathFloor(HUnaryMathOperation* instr);
  LInstruction* DoMathRound(HUnaryMathOperation* instr);
2764
  LInstruction* DoMathFround(HUnaryMathOperation* instr);
2765 2766 2767 2768 2769
  LInstruction* DoMathAbs(HUnaryMathOperation* instr);
  LInstruction* DoMathLog(HUnaryMathOperation* instr);
  LInstruction* DoMathExp(HUnaryMathOperation* instr);
  LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
  LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
2770
  LInstruction* DoMathClz32(HUnaryMathOperation* instr);
2771
  LInstruction* DoDivByPowerOf2I(HDiv* instr);
2772
  LInstruction* DoDivByConstI(HDiv* instr);
2773
  LInstruction* DoDivI(HDiv* instr);
2774
  LInstruction* DoModByPowerOf2I(HMod* instr);
2775
  LInstruction* DoModByConstI(HMod* instr);
2776 2777 2778
  LInstruction* DoModI(HMod* instr);
  LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr);
  LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr);
2779
  LInstruction* DoFlooringDivI(HMathFloorOfDiv* instr);
2780

2781 2782 2783 2784 2785 2786
 private:
  // Methods for getting operands for Use / Define / Temp.
  LUnallocated* ToUnallocated(Register reg);
  LUnallocated* ToUnallocated(XMMRegister reg);

  // Methods for setting up define-use relationships.
2787 2788 2789 2790
  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);
2791 2792 2793 2794 2795 2796 2797 2798 2799

  // 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).
2800 2801
  MUST_USE_RESULT LOperand* UseRegister(HValue* value);
  MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
2802

2803
  // An input operand in a register that may be trashed.
2804
  MUST_USE_RESULT LOperand* UseTempRegister(HValue* value);
2805 2806

  // An input operand in a register or stack slot.
2807 2808
  MUST_USE_RESULT LOperand* Use(HValue* value);
  MUST_USE_RESULT LOperand* UseAtStart(HValue* value);
2809 2810

  // An input operand in a register, stack slot or a constant operand.
2811 2812
  MUST_USE_RESULT LOperand* UseOrConstant(HValue* value);
  MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value);
2813

2814 2815 2816 2817
  // An input operand in a fixed register or a constant operand.
  MUST_USE_RESULT LOperand* UseFixedOrConstant(HValue* value,
                                               Register fixed_register);

2818
  // An input operand in a register or a constant operand.
2819 2820 2821
  MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
  MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);

2822 2823 2824
  // An input operand in a constant operand.
  MUST_USE_RESULT LOperand* UseConstant(HValue* value);

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

2829 2830 2831 2832
  // 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);
2833 2834 2835

  // Methods for setting up define-use relationships.
  // Return the same instruction that they are passed.
2836 2837 2838 2839 2840 2841 2842 2843 2844 2845
  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);
2846 2847
  // Assigns an environment to an instruction.  An instruction which can
  // deoptimize must have an environment.
2848
  LInstruction* AssignEnvironment(LInstruction* instr);
2849 2850
  // Assigns a pointer map to an instruction.  An instruction which can
  // trigger a GC or a lazy deoptimization must have a pointer map.
2851 2852 2853 2854
  LInstruction* AssignPointerMap(LInstruction* instr);

  enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };

2855 2856
  LOperand* GetSeqStringSetCharOperand(HSeqStringSetChar* instr);

2857 2858 2859
  // 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.
2860 2861 2862 2863
  LInstruction* MarkAsCall(
      LInstruction* instr,
      HInstruction* hinstr,
      CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
2864

2865
  void VisitInstruction(HInstruction* current);
2866
  void AddInstruction(LInstruction* instr, HInstruction* current);
2867 2868 2869 2870 2871 2872

  void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block);
  LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr);
  LInstruction* DoArithmeticD(Token::Value op,
                              HArithmeticBinaryOperation* instr);
  LInstruction* DoArithmeticT(Token::Value op,
2873
                              HBinaryOperation* instr);
2874

2875 2876
  LOperand* GetStoreKeyedValueOperand(HStoreKeyed* instr);

2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887
  HInstruction* current_instruction_;
  HBasicBlock* current_block_;
  HBasicBlock* next_block_;
  LAllocator* allocator_;

  DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
};

#undef DECLARE_HYDROGEN_ACCESSOR
#undef DECLARE_CONCRETE_INSTRUCTION

2888 2889
}  // namespace internal
}  // namespace v8
2890 2891

#endif  // V8_IA32_LITHIUM_IA32_H_