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