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