blob: ff1ab1a36e59495be4e606beddd0c851b66b35cd [file] [log] [blame]
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_HYDROGEN_INSTRUCTIONS_H_
29#define V8_HYDROGEN_INSTRUCTIONS_H_
30
31#include "v8.h"
32#include "code-stubs.h"
33#include "string-stream.h"
34#include "zone.h"
35
36namespace v8 {
37namespace internal {
38
39// Forward declarations.
40class HBasicBlock;
41class HEnvironment;
42class HInstruction;
43class HLoopInformation;
44class HValue;
45class LInstruction;
46class LChunkBuilder;
47
48
49// Type hierarchy:
50//
51// HValue
52// HInstruction
53// HAccessArgumentsAt
54// HApplyArguments
55// HArgumentsElements
56// HArgumentsLength
57// HArgumentsObject
58// HBinaryOperation
59// HArithmeticBinaryOperation
60// HAdd
61// HDiv
62// HMod
63// HMul
64// HSub
65// HBitwiseBinaryOperation
66// HBitAnd
67// HBitOr
68// HBitXor
69// HSar
70// HShl
71// HShr
72// HBoundsCheck
73// HCompare
74// HCompareJSObjectEq
75// HInstanceOf
76// HLoadKeyed
77// HLoadKeyedFastElement
78// HLoadKeyedGeneric
79// HLoadNamedGeneric
80// HStoreNamed
81// HStoreNamedField
82// HStoreNamedGeneric
83// HBlockEntry
84// HCall
85// HCallConstantFunction
86// HCallFunction
87// HCallGlobal
88// HCallKeyed
89// HCallKnownGlobal
90// HCallNamed
91// HCallNew
92// HCallRuntime
93// HCallStub
94// HConstant
95// HControlInstruction
96// HGoto
97// HUnaryControlInstruction
98// HBranch
99// HCompareMapAndBranch
100// HReturn
101// HThrow
102// HDeoptimize
103// HEnterInlined
104// HFunctionLiteral
105// HGlobalObject
106// HGlobalReceiver
107// HLeaveInlined
108// HLoadGlobal
109// HMaterializedLiteral
110// HArrayLiteral
111// HObjectLiteral
112// HRegExpLiteral
113// HOsrEntry
114// HParameter
115// HSimulate
116// HStackCheck
117// HStoreKeyed
118// HStoreKeyedFastElement
119// HStoreKeyedGeneric
120// HUnaryOperation
121// HArrayLength
122// HBitNot
123// HChange
124// HCheckFunction
125// HCheckInstanceType
126// HCheckMap
127// HCheckNonSmi
128// HCheckPrototypeMaps
129// HCheckSmi
130// HDeleteProperty
131// HLoadElements
132// HTypeofIs
133// HLoadNamedField
134// HPushArgument
135// HTypeof
136// HUnaryMathOperation
137// HUnaryPredicate
138// HClassOfTest
139// HHasCachedArrayIndex
140// HHasInstanceType
141// HIsNull
142// HIsSmi
143// HValueOf
144// HUnknownOSRValue
145// HPhi
146
147#define HYDROGEN_ALL_INSTRUCTION_LIST(V) \
148 V(ArithmeticBinaryOperation) \
149 V(BinaryOperation) \
150 V(BitwiseBinaryOperation) \
151 V(Call) \
152 V(ControlInstruction) \
153 V(Instruction) \
154 V(LoadKeyed) \
155 V(MaterializedLiteral) \
156 V(Phi) \
157 V(StoreKeyed) \
158 V(StoreNamed) \
159 V(UnaryControlInstruction) \
160 V(UnaryOperation) \
161 HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
162
163
164#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
165 V(AccessArgumentsAt) \
166 V(Add) \
167 V(ApplyArguments) \
168 V(ArgumentsElements) \
169 V(ArgumentsLength) \
170 V(ArgumentsObject) \
171 V(ArrayLength) \
172 V(ArrayLiteral) \
173 V(BitAnd) \
174 V(BitNot) \
175 V(BitOr) \
176 V(BitXor) \
177 V(BlockEntry) \
178 V(BoundsCheck) \
179 V(Branch) \
180 V(CallConstantFunction) \
181 V(CallFunction) \
182 V(CallGlobal) \
183 V(CallKeyed) \
184 V(CallKnownGlobal) \
185 V(CallNamed) \
186 V(CallNew) \
187 V(CallRuntime) \
188 V(CallStub) \
189 V(Change) \
190 V(CheckFunction) \
191 V(CheckInstanceType) \
192 V(CheckMap) \
193 V(CheckNonSmi) \
194 V(CheckPrototypeMaps) \
195 V(CheckSmi) \
196 V(Compare) \
197 V(CompareJSObjectEq) \
198 V(CompareMapAndBranch) \
199 V(Constant) \
200 V(DeleteProperty) \
201 V(Deoptimize) \
202 V(Div) \
203 V(EnterInlined) \
204 V(FunctionLiteral) \
205 V(GlobalObject) \
206 V(GlobalReceiver) \
207 V(Goto) \
208 V(InstanceOf) \
209 V(IsNull) \
210 V(IsSmi) \
211 V(HasInstanceType) \
212 V(HasCachedArrayIndex) \
213 V(ClassOfTest) \
214 V(LeaveInlined) \
215 V(LoadElements) \
216 V(LoadGlobal) \
217 V(LoadKeyedFastElement) \
218 V(LoadKeyedGeneric) \
219 V(LoadNamedField) \
220 V(LoadNamedGeneric) \
221 V(Mod) \
222 V(Mul) \
223 V(ObjectLiteral) \
224 V(OsrEntry) \
225 V(Parameter) \
226 V(PushArgument) \
227 V(RegExpLiteral) \
228 V(Return) \
229 V(Sar) \
230 V(Shl) \
231 V(Shr) \
232 V(Simulate) \
233 V(StackCheck) \
234 V(StoreGlobal) \
235 V(StoreKeyedFastElement) \
236 V(StoreKeyedGeneric) \
237 V(StoreNamedField) \
238 V(StoreNamedGeneric) \
239 V(Sub) \
240 V(Throw) \
241 V(Typeof) \
242 V(TypeofIs) \
243 V(UnaryMathOperation) \
244 V(UnknownOSRValue) \
245 V(ValueOf)
246
247#define GVN_FLAG_LIST(V) \
248 V(Calls) \
249 V(InobjectFields) \
250 V(BackingStoreFields) \
251 V(ArrayElements) \
252 V(GlobalVars) \
253 V(Maps) \
254 V(ArrayLengths) \
255 V(OsrEntries)
256
257#define DECLARE_INSTRUCTION(type) \
258 virtual bool Is##type() const { return true; } \
259 static H##type* cast(HValue* value) { \
260 ASSERT(value->Is##type()); \
261 return reinterpret_cast<H##type*>(value); \
262 } \
263 Opcode opcode() const { return HValue::k##type; }
264
265
266#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
267 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
268 virtual const char* Mnemonic() const { return mnemonic; } \
269 DECLARE_INSTRUCTION(type)
270
271
272
273template<int kSize>
274class HOperandVector : public EmbeddedVector<HValue*, kSize> {
275 public:
276 HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
277};
278
279
280class Range: public ZoneObject {
281 public:
282 Range() : lower_(kMinInt),
283 upper_(kMaxInt),
284 next_(NULL),
285 can_be_minus_zero_(false) { }
286
287 Range(int32_t lower, int32_t upper)
288 : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
289
290 bool IsInSmiRange() const {
291 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
292 }
293 void KeepOrder();
294 void Verify() const;
295 int32_t upper() const { return upper_; }
296 int32_t lower() const { return lower_; }
297 Range* next() const { return next_; }
298 Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
299 Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
300 void ClearLower() { lower_ = kMinInt; }
301 void ClearUpper() { upper_ = kMaxInt; }
302 Range* Copy() const { return new Range(lower_, upper_); }
303 bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
304 int32_t Mask() const;
305 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
306 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
307 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
308 bool CanBeNegative() const { return lower_ < 0; }
309 bool Includes(int value) const {
310 return lower_ <= value && upper_ >= value;
311 }
312
313 void Sar(int32_t value) {
314 int32_t bits = value & 0x1F;
315 lower_ = lower_ >> bits;
316 upper_ = upper_ >> bits;
317 set_can_be_minus_zero(false);
318 }
319
320 void Shl(int32_t value) {
321 int32_t bits = value & 0x1F;
322 int old_lower = lower_;
323 int old_upper = upper_;
324 lower_ = lower_ << bits;
325 upper_ = upper_ << bits;
326 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
327 upper_ = kMaxInt;
328 lower_ = kMinInt;
329 }
330 set_can_be_minus_zero(false);
331 }
332
333 void StackUpon(Range* other) {
334 Intersect(other);
335 next_ = other;
336 }
337
338 void Intersect(Range* other) {
339 upper_ = Min(upper_, other->upper_);
340 lower_ = Max(lower_, other->lower_);
341 bool b = CanBeMinusZero() && other->CanBeMinusZero();
342 set_can_be_minus_zero(b);
343 }
344
345 void Union(Range* other) {
346 upper_ = Max(upper_, other->upper_);
347 lower_ = Min(lower_, other->lower_);
348 bool b = CanBeMinusZero() || other->CanBeMinusZero();
349 set_can_be_minus_zero(b);
350 }
351
352 void Add(int32_t value);
353 bool AddAndCheckOverflow(Range* other);
354 bool SubAndCheckOverflow(Range* other);
355 bool MulAndCheckOverflow(Range* other);
356
357 private:
358 int32_t lower_;
359 int32_t upper_;
360 Range* next_;
361 bool can_be_minus_zero_;
362};
363
364
365class Representation {
366 public:
367 enum Kind {
368 kNone,
369 kTagged,
370 kDouble,
371 kInteger32,
372 kNumRepresentations
373 };
374
375 Representation() : kind_(kNone) { }
376
377 static Representation None() { return Representation(kNone); }
378 static Representation Tagged() { return Representation(kTagged); }
379 static Representation Integer32() { return Representation(kInteger32); }
380 static Representation Double() { return Representation(kDouble); }
381
382 bool Equals(const Representation& other) const {
383 return kind_ == other.kind_;
384 }
385
386 Kind kind() const { return kind_; }
387 bool IsNone() const { return kind_ == kNone; }
388 bool IsTagged() const { return kind_ == kTagged; }
389 bool IsInteger32() const { return kind_ == kInteger32; }
390 bool IsDouble() const { return kind_ == kDouble; }
391 bool IsSpecialization() const {
392 return kind_ == kInteger32 || kind_ == kDouble;
393 }
394 const char* Mnemonic() const;
395
396 private:
397 explicit Representation(Kind k) : kind_(k) { }
398
399 Kind kind_;
400};
401
402
403class HType {
404 public:
405 HType() : type_(kUninitialized) { }
406
407 static HType Tagged() { return HType(kTagged); }
408 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
409 static HType TaggedNumber() { return HType(kTaggedNumber); }
410 static HType Smi() { return HType(kSmi); }
411 static HType HeapNumber() { return HType(kHeapNumber); }
412 static HType String() { return HType(kString); }
413 static HType Boolean() { return HType(kBoolean); }
414 static HType NonPrimitive() { return HType(kNonPrimitive); }
415 static HType JSArray() { return HType(kJSArray); }
416 static HType JSObject() { return HType(kJSObject); }
417 static HType Uninitialized() { return HType(kUninitialized); }
418
419 // Return the weakest (least precise) common type.
420 HType Combine(HType other) {
421 return HType(static_cast<Type>(type_ & other.type_));
422 }
423
424 bool Equals(const HType& other) {
425 return type_ == other.type_;
426 }
427
428 bool IsSubtypeOf(const HType& other) {
429 return Combine(other).Equals(other);
430 }
431
432 bool IsTagged() {
433 ASSERT(type_ != kUninitialized);
434 return ((type_ & kTagged) == kTagged);
435 }
436
437 bool IsTaggedPrimitive() {
438 ASSERT(type_ != kUninitialized);
439 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
440 }
441
442 bool IsTaggedNumber() {
443 ASSERT(type_ != kUninitialized);
444 return ((type_ & kTaggedNumber) == kTaggedNumber);
445 }
446
447 bool IsSmi() {
448 ASSERT(type_ != kUninitialized);
449 return ((type_ & kSmi) == kSmi);
450 }
451
452 bool IsHeapNumber() {
453 ASSERT(type_ != kUninitialized);
454 return ((type_ & kHeapNumber) == kHeapNumber);
455 }
456
457 bool IsString() {
458 ASSERT(type_ != kUninitialized);
459 return ((type_ & kString) == kString);
460 }
461
462 bool IsBoolean() {
463 ASSERT(type_ != kUninitialized);
464 return ((type_ & kBoolean) == kBoolean);
465 }
466
467 bool IsNonPrimitive() {
468 ASSERT(type_ != kUninitialized);
469 return ((type_ & kNonPrimitive) == kNonPrimitive);
470 }
471
472 bool IsJSArray() {
473 ASSERT(type_ != kUninitialized);
474 return ((type_ & kJSArray) == kJSArray);
475 }
476
477 bool IsJSObject() {
478 ASSERT(type_ != kUninitialized);
479 return ((type_ & kJSObject) == kJSObject);
480 }
481
482 bool IsUninitialized() {
483 return type_ == kUninitialized;
484 }
485
486 static HType TypeFromValue(Handle<Object> value);
487
488 const char* ToString();
489 const char* ToShortString();
490
491 private:
492 enum Type {
493 kTagged = 0x1, // 0000 0000 0000 0001
494 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
495 kTaggedNumber = 0xd, // 0000 0000 0000 1101
496 kSmi = 0x1d, // 0000 0000 0001 1101
497 kHeapNumber = 0x2d, // 0000 0000 0010 1101
498 kString = 0x45, // 0000 0000 0100 0101
499 kBoolean = 0x85, // 0000 0000 1000 0101
500 kNonPrimitive = 0x101, // 0000 0001 0000 0001
501 kJSObject = 0x301, // 0000 0011 0000 0001
502 kJSArray = 0x701, // 0000 0111 1000 0001
503 kUninitialized = 0x1fff // 0001 1111 1111 1111
504 };
505
506 explicit HType(Type t) : type_(t) { }
507
508 Type type_;
509};
510
511
512class HValue: public ZoneObject {
513 public:
514 static const int kNoNumber = -1;
515
516 // There must be one corresponding kDepends flag for every kChanges flag and
517 // the order of the kChanges flags must be exactly the same as of the kDepends
518 // flags.
519 enum Flag {
520 // Declare global value numbering flags.
521 #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
522 GVN_FLAG_LIST(DECLARE_DO)
523 #undef DECLARE_DO
524 kFlexibleRepresentation,
525 kUseGVN,
526 kCanOverflow,
527 kBailoutOnMinusZero,
528 kCanBeDivByZero,
529 kIsArguments,
530 kTruncatingToInt32,
531 kLastFlag = kTruncatingToInt32
532 };
533
534 STATIC_ASSERT(kLastFlag < kBitsPerInt);
535
536 static const int kChangesToDependsFlagsLeftShift = 1;
537
538 static int ChangesFlagsMask() {
539 int result = 0;
540 // Create changes mask.
541#define DECLARE_DO(type) result |= (1 << kChanges##type);
542 GVN_FLAG_LIST(DECLARE_DO)
543#undef DECLARE_DO
544 return result;
545 }
546
547 static int DependsFlagsMask() {
548 return ConvertChangesToDependsFlags(ChangesFlagsMask());
549 }
550
551 static int ConvertChangesToDependsFlags(int flags) {
552 return flags << kChangesToDependsFlagsLeftShift;
553 }
554
555 // A flag mask to mark an instruction as having arbitrary side effects.
556 static int AllSideEffects() {
557 return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
558 }
559
560 static HValue* cast(HValue* value) { return value; }
561
562 enum Opcode {
563 // Declare a unique enum value for each hydrogen instruction.
564 #define DECLARE_DO(type) k##type,
565 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
566 #undef DECLARE_DO
567 kMaxInstructionClass
568 };
569
570 HValue() : block_(NULL),
571 id_(kNoNumber),
572 uses_(2),
573 type_(HType::Tagged()),
574 range_(NULL),
575 flags_(0) {}
576 virtual ~HValue() {}
577
578 HBasicBlock* block() const { return block_; }
579 void SetBlock(HBasicBlock* block);
580
581 int id() const { return id_; }
582 void set_id(int id) { id_ = id; }
583
584 const ZoneList<HValue*>* uses() const { return &uses_; }
585
586 virtual bool EmitAtUses() const { return false; }
587 Representation representation() const { return representation_; }
588 void ChangeRepresentation(Representation r) {
589 // Representation was already set and is allowed to be changed.
590 ASSERT(!representation_.IsNone());
591 ASSERT(!r.IsNone());
592 ASSERT(CheckFlag(kFlexibleRepresentation));
593 RepresentationChanged(r);
594 representation_ = r;
595 }
596
597 HType type() const { return type_; }
598 void set_type(HType type) {
599 ASSERT(uses_.length() == 0);
600 type_ = type;
601 }
602
603 // An operation needs to override this function iff:
604 // 1) it can produce an int32 output.
605 // 2) the true value of its output can potentially be minus zero.
606 // The implementation must set a flag so that it bails out in the case where
607 // it would otherwise output what should be a minus zero as an int32 zero.
608 // If the operation also exists in a form that takes int32 and outputs int32
609 // then the operation should return its input value so that we can propagate
610 // back. There are two operations that need to propagate back to more than
611 // one input. They are phi and binary add. They always return NULL and
612 // expect the caller to take care of things.
613 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
614 visited->Add(id());
615 return NULL;
616 }
617
618 bool HasSideEffects() const {
619 return (flags_ & AllSideEffects()) != 0;
620 }
621 bool IsDefinedAfter(HBasicBlock* other) const;
622
623 // Operands.
624 virtual int OperandCount() const { return 0; }
625 virtual HValue* OperandAt(int index) const {
626 UNREACHABLE();
627 return NULL;
628 }
629 void SetOperandAt(int index, HValue* value);
630
631 int LookupOperandIndex(int occurrence_index, HValue* op) const;
632 bool UsesMultipleTimes(HValue* op) const;
633
634 void ReplaceAndDelete(HValue* other);
635 void ReplaceValue(HValue* other);
636 void ReplaceAtUse(HValue* use, HValue* other);
637 void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
638 bool HasNoUses() const { return uses_.is_empty(); }
639 void ClearOperands();
640 void Delete();
641
642 int flags() const { return flags_; }
643 void SetFlagMask(int mask) { flags_ |= mask; }
644 void SetFlag(Flag f) { SetFlagMask(1 << f); }
645 void ClearFlagMask(int mask) { flags_ &= ~mask; }
646 void ClearFlag(Flag f) { ClearFlagMask(1 << f); }
647 bool CheckFlag(Flag f) const { return CheckFlagMask(1 << f); }
648 bool CheckFlagMask(int mask) const { return (flags_ & mask) != 0; }
649
650 Range* range() const { return range_; }
651 bool HasRange() const { return range_ != NULL; }
652 void AddNewRange(Range* r);
653 void RemoveLastAddedRange();
654 void ComputeInitialRange();
655
656 // Representation helpers.
657 virtual Representation RequiredInputRepresentation(int index) const {
658 return Representation::None();
659 }
660 virtual Representation InferredRepresentation() const {
661 return representation();
662 }
663
664 // This gives the instruction an opportunity to replace itself with an
665 // instruction that does the same in some better way. To replace an
666 // instruction with a new one, first add the new instruction to the graph,
667 // then return it. Return NULL to have the instruction deleted.
668 virtual HValue* Canonicalize() { return this; }
669
670 // Declare virtual type testers.
671#define DECLARE_DO(type) virtual bool Is##type() const { return false; }
672 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
673#undef DECLARE_DO
674
675 bool Equals(HValue* other) const;
676 virtual intptr_t Hashcode() const;
677
678 // Printing support.
679 virtual void PrintTo(StringStream* stream) const = 0;
680 void PrintNameTo(StringStream* stream);
681 static void PrintTypeTo(HType type, StringStream* stream);
682
683 virtual const char* Mnemonic() const = 0;
684 virtual Opcode opcode() const = 0;
685
686 // Updated the inferred type of this instruction and returns true if
687 // it has changed.
688 bool UpdateInferredType();
689
690 virtual HType CalculateInferredType() const;
691
692 // Helper for type conversions used by normal and phi instructions.
693 void InsertInputConversion(HInstruction* previous, int index, HType type);
694
695#ifdef DEBUG
696 virtual void Verify() const = 0;
697#endif
698
699 protected:
700 virtual bool DataEquals(HValue* other) const { return true; }
701 virtual void RepresentationChanged(Representation to) { }
702 virtual Range* InferRange();
703 virtual void DeleteFromGraph() = 0;
704 virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
705 void clear_block() {
706 ASSERT(block_ != NULL);
707 block_ = NULL;
708 }
709
710 void set_representation(Representation r) {
711 // Representation is set-once.
712 ASSERT(representation_.IsNone() && !r.IsNone());
713 representation_ = r;
714 }
715
716 private:
717 void InternalReplaceAtUse(HValue* use, HValue* other);
718 void RegisterUse(int index, HValue* new_value);
719
720 HBasicBlock* block_;
721
722 // The id of this instruction in the hydrogen graph, assigned when first
723 // added to the graph. Reflects creation order.
724 int id_;
725
726 Representation representation_;
727 ZoneList<HValue*> uses_;
728 HType type_;
729 Range* range_;
730 int flags_;
731
732 DISALLOW_COPY_AND_ASSIGN(HValue);
733};
734
735
736class HInstruction: public HValue {
737 public:
738 HInstruction* next() const { return next_; }
739 HInstruction* previous() const { return previous_; }
740
741 void PrintTo(StringStream* stream) const;
742 virtual void PrintDataTo(StringStream* stream) const {}
743
744 bool IsLinked() const { return block() != NULL; }
745 void Unlink();
746 void InsertBefore(HInstruction* next);
747 void InsertAfter(HInstruction* previous);
748
749 int position() const { return position_; }
750 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
751 void set_position(int position) { position_ = position; }
752
753 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
754
755#ifdef DEBUG
756 virtual void Verify() const;
757#endif
758
759 DECLARE_INSTRUCTION(Instruction)
760
761 protected:
762 HInstruction()
763 : next_(NULL),
764 previous_(NULL),
765 position_(RelocInfo::kNoPosition) {
766 SetFlag(kDependsOnOsrEntries);
767 }
768
769 virtual void DeleteFromGraph() { Unlink(); }
770
771 private:
772 void InitializeAsFirst(HBasicBlock* block) {
773 ASSERT(!IsLinked());
774 SetBlock(block);
775 }
776
777 HInstruction* next_;
778 HInstruction* previous_;
779 int position_;
780
781 friend class HBasicBlock;
782};
783
784
785class HBlockEntry: public HInstruction {
786 public:
787 DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
788};
789
790
791class HControlInstruction: public HInstruction {
792 public:
793 virtual HBasicBlock* FirstSuccessor() const { return NULL; }
794 virtual HBasicBlock* SecondSuccessor() const { return NULL; }
795
796 DECLARE_INSTRUCTION(ControlInstruction)
797};
798
799
800class HDeoptimize: public HControlInstruction {
801 public:
802 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
803};
804
805
806class HGoto: public HControlInstruction {
807 public:
808 explicit HGoto(HBasicBlock* destination)
809 : destination_(destination),
810 include_stack_check_(false) {}
811
812 virtual HBasicBlock* FirstSuccessor() const { return destination_; }
813 void set_include_stack_check(bool include_stack_check) {
814 include_stack_check_ = include_stack_check;
815 }
816 bool include_stack_check() const { return include_stack_check_; }
817
818 virtual void PrintDataTo(StringStream* stream) const;
819
820 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
821
822 private:
823 HBasicBlock* destination_;
824 bool include_stack_check_;
825};
826
827
828class HUnaryControlInstruction: public HControlInstruction {
829 public:
830 explicit HUnaryControlInstruction(HValue* value) {
831 SetOperandAt(0, value);
832 }
833
834 virtual Representation RequiredInputRepresentation(int index) const {
835 return Representation::Tagged();
836 }
837
838 HValue* value() const { return OperandAt(0); }
839 virtual int OperandCount() const { return 1; }
840 virtual HValue* OperandAt(int index) const { return operands_[index]; }
841
842 DECLARE_INSTRUCTION(UnaryControlInstruction)
843
844 protected:
845 virtual void InternalSetOperandAt(int index, HValue* value) {
846 operands_[index] = value;
847 }
848
849 private:
850 HOperandVector<1> operands_;
851};
852
853
854class HBranch: public HUnaryControlInstruction {
855 public:
856 HBranch(HBasicBlock* true_destination,
857 HBasicBlock* false_destination,
858 HValue* boolean_value)
859 : HUnaryControlInstruction(boolean_value),
860 true_destination_(true_destination),
861 false_destination_(false_destination) {
862 ASSERT(true_destination != NULL && false_destination != NULL);
863 }
864
865 virtual Representation RequiredInputRepresentation(int index) const {
866 return Representation::None();
867 }
868
869 virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
870 virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
871
872 virtual void PrintDataTo(StringStream* stream) const;
873
874 DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
875
876 private:
877 HBasicBlock* true_destination_;
878 HBasicBlock* false_destination_;
879};
880
881
882class HCompareMapAndBranch: public HUnaryControlInstruction {
883 public:
884 HCompareMapAndBranch(HValue* result,
885 Handle<Map> map,
886 HBasicBlock* true_destination,
887 HBasicBlock* false_destination)
888 : HUnaryControlInstruction(result),
889 map_(map),
890 true_destination_(true_destination),
891 false_destination_(false_destination) {
892 ASSERT(true_destination != NULL);
893 ASSERT(false_destination != NULL);
894 ASSERT(!map.is_null());
895 }
896
897 virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
898 virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
899
900 Handle<Map> map() const { return map_; }
901
902 DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch")
903
904 private:
905 Handle<Map> map_;
906 HBasicBlock* true_destination_;
907 HBasicBlock* false_destination_;
908};
909
910
911class HReturn: public HUnaryControlInstruction {
912 public:
913 explicit HReturn(HValue* result) : HUnaryControlInstruction(result) { }
914
915 virtual void PrintDataTo(StringStream* stream) const;
916
917 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
918};
919
920
921class HThrow: public HUnaryControlInstruction {
922 public:
923 explicit HThrow(HValue* value) : HUnaryControlInstruction(value) { }
924
925 virtual void PrintDataTo(StringStream* stream) const;
926
927 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
928};
929
930
931class HUnaryOperation: public HInstruction {
932 public:
933 explicit HUnaryOperation(HValue* value) {
934 SetOperandAt(0, value);
935 }
936
937 HValue* value() const { return OperandAt(0); }
938 virtual void PrintDataTo(StringStream* stream) const;
939 virtual int OperandCount() const { return 1; }
940 virtual HValue* OperandAt(int index) const { return operands_[index]; }
941
942 DECLARE_INSTRUCTION(UnaryOperation)
943
944 protected:
945 virtual void InternalSetOperandAt(int index, HValue* value) {
946 operands_[index] = value;
947 }
948
949 private:
950 HOperandVector<1> operands_;
951};
952
953
954class HChange: public HUnaryOperation {
955 public:
956 HChange(HValue* value,
957 Representation from,
958 Representation to)
959 : HUnaryOperation(value), from_(from), to_(to) {
960 ASSERT(!from.IsNone() && !to.IsNone());
961 ASSERT(!from.Equals(to));
962 set_representation(to);
963 SetFlag(kUseGVN);
964
965 if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
966 value->range()->IsInSmiRange()) {
967 set_type(HType::Smi());
968 }
969 }
970
971 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
972
973 Representation from() const { return from_; }
974 Representation to() const { return to_; }
975 virtual Representation RequiredInputRepresentation(int index) const {
976 return from_;
977 }
978
979 bool CanTruncateToInt32() const {
980 for (int i = 0; i < uses()->length(); ++i) {
981 if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
982 }
983 return true;
984 }
985
986 virtual void PrintDataTo(StringStream* stream) const;
987
988 DECLARE_CONCRETE_INSTRUCTION(Change,
989 CanTruncateToInt32() ? "truncate" : "change")
990
991 protected:
992 virtual bool DataEquals(HValue* other) const {
993 if (!other->IsChange()) return false;
994 HChange* change = HChange::cast(other);
995 return value() == change->value()
996 && to().Equals(change->to())
997 && CanTruncateToInt32() == change->CanTruncateToInt32();
998 }
999
1000 private:
1001 Representation from_;
1002 Representation to_;
1003};
1004
1005
1006class HSimulate: public HInstruction {
1007 public:
1008 HSimulate(int ast_id, int pop_count, int environment_height)
1009 : ast_id_(ast_id),
1010 pop_count_(pop_count),
1011 environment_height_(environment_height),
1012 values_(2),
1013 assigned_indexes_(2) {}
1014 virtual ~HSimulate() {}
1015
1016 virtual void PrintDataTo(StringStream* stream) const;
1017
1018 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
1019 int ast_id() const { return ast_id_; }
1020 void set_ast_id(int id) {
1021 ASSERT(!HasAstId());
1022 ast_id_ = id;
1023 }
1024
1025 int environment_height() const { return environment_height_; }
1026 int pop_count() const { return pop_count_; }
1027 const ZoneList<HValue*>* values() const { return &values_; }
1028 int GetAssignedIndexAt(int index) const {
1029 ASSERT(HasAssignedIndexAt(index));
1030 return assigned_indexes_[index];
1031 }
1032 bool HasAssignedIndexAt(int index) const {
1033 return assigned_indexes_[index] != kNoIndex;
1034 }
1035 void AddAssignedValue(int index, HValue* value) {
1036 AddValue(index, value);
1037 }
1038 void AddPushedValue(HValue* value) {
1039 AddValue(kNoIndex, value);
1040 }
1041 virtual int OperandCount() const { return values_.length(); }
1042 virtual HValue* OperandAt(int index) const { return values_[index]; }
1043
1044 DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
1045
1046#ifdef DEBUG
1047 virtual void Verify() const;
1048#endif
1049
1050 protected:
1051 virtual void InternalSetOperandAt(int index, HValue* value) {
1052 values_[index] = value;
1053 }
1054
1055 private:
1056 static const int kNoIndex = -1;
1057 void AddValue(int index, HValue* value) {
1058 assigned_indexes_.Add(index);
1059 // Resize the list of pushed values.
1060 values_.Add(NULL);
1061 // Set the operand through the base method in HValue to make sure that the
1062 // use lists are correctly updated.
1063 SetOperandAt(values_.length() - 1, value);
1064 }
1065 int ast_id_;
1066 int pop_count_;
1067 int environment_height_;
1068 ZoneList<HValue*> values_;
1069 ZoneList<int> assigned_indexes_;
1070};
1071
1072
1073class HStackCheck: public HInstruction {
1074 public:
1075 HStackCheck() { }
1076
1077 DECLARE_CONCRETE_INSTRUCTION(Throw, "stack_check")
1078};
1079
1080
1081class HEnterInlined: public HInstruction {
1082 public:
1083 HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
1084 : closure_(closure), function_(function) {
1085 }
1086
1087 virtual void PrintDataTo(StringStream* stream) const;
1088
1089 Handle<JSFunction> closure() const { return closure_; }
1090 FunctionLiteral* function() const { return function_; }
1091
1092 DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
1093
1094 private:
1095 Handle<JSFunction> closure_;
1096 FunctionLiteral* function_;
1097};
1098
1099
1100class HLeaveInlined: public HInstruction {
1101 public:
1102 HLeaveInlined() {}
1103
1104 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
1105};
1106
1107
1108class HPushArgument: public HUnaryOperation {
1109 public:
1110 explicit HPushArgument(HValue* value)
1111 : HUnaryOperation(value), argument_index_(-1) {
1112 set_representation(Representation::Tagged());
1113 }
1114
1115 virtual Representation RequiredInputRepresentation(int index) const {
1116 return Representation::Tagged();
1117 }
1118
1119 virtual void PrintDataTo(StringStream* stream) const;
1120 HValue* argument() const { return OperandAt(0); }
1121 int argument_index() const { return argument_index_; }
1122 void set_argument_index(int index) {
1123 ASSERT(argument_index_ == -1 || index == argument_index_);
1124 argument_index_ = index;
1125 }
1126
1127 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
1128
1129 private:
1130 int argument_index_;
1131};
1132
1133
1134class HGlobalObject: public HInstruction {
1135 public:
1136 HGlobalObject() {
1137 set_representation(Representation::Tagged());
1138 SetFlag(kUseGVN);
1139 SetFlag(kDependsOnCalls);
1140 }
1141
1142 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
1143};
1144
1145
1146class HGlobalReceiver: public HInstruction {
1147 public:
1148 HGlobalReceiver() {
1149 set_representation(Representation::Tagged());
1150 SetFlag(kUseGVN);
1151 SetFlag(kDependsOnCalls);
1152 }
1153
1154 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
1155};
1156
1157
1158class HCall: public HInstruction {
1159 public:
1160 // Construct a call with uninitialized arguments. The argument count
1161 // includes the receiver.
1162 explicit HCall(int count);
1163
1164 virtual HType CalculateInferredType() const { return HType::Tagged(); }
1165
1166 // TODO(3190496): This needs a cleanup. We don't want the arguments
1167 // be operands of the call instruction. This results in bad code quality.
1168 virtual int argument_count() const { return arguments_.length(); }
1169 virtual int OperandCount() const { return argument_count(); }
1170 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1171 virtual HPushArgument* PushArgumentAt(int index) const {
1172 return HPushArgument::cast(OperandAt(index));
1173 }
1174 virtual HValue* ArgumentAt(int index) const {
1175 return PushArgumentAt(index)->argument();
1176 }
1177 virtual void SetArgumentAt(int index, HPushArgument* push_argument);
1178
1179 virtual void PrintDataTo(StringStream* stream) const;
1180
1181 DECLARE_INSTRUCTION(Call)
1182
1183 protected:
1184 virtual void InternalSetOperandAt(int index, HValue* value) {
1185 arguments_[index] = value;
1186 }
1187
1188 int argument_count_;
1189 Vector<HValue*> arguments_;
1190};
1191
1192
1193class HCallConstantFunction: public HCall {
1194 public:
1195 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1196 : HCall(argument_count), function_(function) { }
1197
1198 Handle<JSFunction> function() const { return function_; }
1199 bool IsApplyFunction() const {
1200 return function_->code() == Builtins::builtin(Builtins::FunctionApply);
1201 }
1202
1203 virtual void PrintDataTo(StringStream* stream) const;
1204
1205 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
1206
1207 private:
1208 Handle<JSFunction> function_;
1209};
1210
1211
1212class HCallKeyed: public HCall {
1213 public:
1214 HCallKeyed(HValue* key, int argument_count)
1215 : HCall(argument_count + 1) {
1216 SetOperandAt(0, key);
1217 }
1218
1219 virtual Representation RequiredInputRepresentation(int index) const {
1220 return Representation::Tagged();
1221 }
1222
1223 // TODO(3190496): This is a hack to get an additional operand that
1224 // is not an argument to work with the current setup. This _needs_ a cleanup.
1225 // (see HCall)
1226 virtual void PrintDataTo(StringStream* stream) const;
1227 HValue* key() const { return OperandAt(0); }
1228 virtual int argument_count() const { return arguments_.length() - 1; }
1229 virtual int OperandCount() const { return arguments_.length(); }
1230 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1231 virtual HPushArgument* PushArgumentAt(int index) const {
1232 return HPushArgument::cast(OperandAt(index + 1));
1233 }
1234 virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
1235 HCall::SetArgumentAt(index + 1, push_argument);
1236 }
1237
1238 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
1239};
1240
1241
1242class HCallNamed: public HCall {
1243 public:
1244 HCallNamed(Handle<String> name, int argument_count)
1245 : HCall(argument_count), name_(name) { }
1246 virtual void PrintDataTo(StringStream* stream) const;
1247
1248 Handle<String> name() const { return name_; }
1249
1250 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
1251
1252 private:
1253 Handle<String> name_;
1254};
1255
1256
1257class HCallFunction: public HCall {
1258 public:
1259 explicit HCallFunction(int argument_count) : HCall(argument_count) { }
1260
1261 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
1262};
1263
1264
1265class HCallGlobal: public HCall {
1266 public:
1267 HCallGlobal(Handle<String> name, int argument_count)
1268 : HCall(argument_count), name_(name) { }
1269
1270 virtual void PrintDataTo(StringStream* stream) const;
1271
1272 Handle<String> name() const { return name_; }
1273
1274 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
1275
1276 private:
1277 Handle<String> name_;
1278};
1279
1280
1281class HCallKnownGlobal: public HCall {
1282 public:
1283 HCallKnownGlobal(Handle<JSFunction> target,
1284 int argument_count)
1285 : HCall(argument_count), target_(target) { }
1286
1287 Handle<JSFunction> target() const { return target_; }
1288
1289 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
1290
1291 private:
1292 Handle<JSFunction> target_;
1293};
1294
1295
1296class HCallNew: public HCall {
1297 public:
1298 explicit HCallNew(int argument_count) : HCall(argument_count) { }
1299
1300 virtual Representation RequiredInputRepresentation(int index) const {
1301 return Representation::Tagged();
1302 }
1303
1304 HValue* constructor() const { return ArgumentAt(0); }
1305
1306 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
1307};
1308
1309
1310class HCallRuntime: public HCall {
1311 public:
1312 HCallRuntime(Handle<String> name,
1313 Runtime::Function* c_function,
1314 int argument_count)
1315 : HCall(argument_count), c_function_(c_function), name_(name) { }
1316 virtual void PrintDataTo(StringStream* stream) const;
1317
1318 Runtime::Function* function() const { return c_function_; }
1319 Handle<String> name() const { return name_; }
1320
1321 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
1322
1323 private:
1324 Runtime::Function* c_function_;
1325 Handle<String> name_;
1326};
1327
1328
1329class HArrayLength: public HUnaryOperation {
1330 public:
1331 explicit HArrayLength(HValue* value) : HUnaryOperation(value) {
1332 // The length of an array is stored as a tagged value in the array
1333 // object. It is guaranteed to be 32 bit integer, but it can be
1334 // represented as either a smi or heap number.
1335 set_representation(Representation::Tagged());
1336 SetFlag(kDependsOnArrayLengths);
1337 SetFlag(kUseGVN);
1338 }
1339
1340 virtual Representation RequiredInputRepresentation(int index) const {
1341 return Representation::Tagged();
1342 }
1343
1344 DECLARE_CONCRETE_INSTRUCTION(ArrayLength, "array_length")
1345};
1346
1347
1348class HBitNot: public HUnaryOperation {
1349 public:
1350 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1351 set_representation(Representation::Integer32());
1352 SetFlag(kUseGVN);
1353 SetFlag(kTruncatingToInt32);
1354 }
1355
1356 virtual Representation RequiredInputRepresentation(int index) const {
1357 return Representation::Integer32();
1358 }
1359 virtual HType CalculateInferredType() const;
1360
1361 DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
1362};
1363
1364
1365class HUnaryMathOperation: public HUnaryOperation {
1366 public:
1367 HUnaryMathOperation(HValue* value, MathFunctionId op)
1368 : HUnaryOperation(value), op_(op) {
1369 switch (op) {
1370 case kMathFloor:
1371 case kMathRound:
1372 case kMathCeil:
1373 set_representation(Representation::Integer32());
1374 break;
1375 case kMathAbs:
1376 set_representation(Representation::Tagged());
1377 SetFlag(kFlexibleRepresentation);
1378 break;
1379 case kMathSqrt:
1380 default:
1381 set_representation(Representation::Double());
1382 }
1383 SetFlag(kUseGVN);
1384 }
1385
1386 virtual void PrintDataTo(StringStream* stream) const;
1387
1388 virtual HType CalculateInferredType() const;
1389
1390 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1391
1392 virtual Representation RequiredInputRepresentation(int index) const {
1393 switch (op_) {
1394 case kMathFloor:
1395 case kMathRound:
1396 case kMathCeil:
1397 case kMathSqrt:
1398 return Representation::Double();
1399 break;
1400 case kMathAbs:
1401 return representation();
1402 break;
1403 default:
1404 return Representation::None();
1405 }
1406 }
1407
1408 virtual HValue* Canonicalize() {
1409 // If the input is integer32 then we replace the floor instruction
1410 // with its inputs. This happens before the representation changes are
1411 // introduced.
1412 if (op() == kMathFloor) {
1413 if (value()->representation().IsInteger32()) return value();
1414 }
1415 return this;
1416 }
1417
1418 MathFunctionId op() const { return op_; }
1419 const char* OpName() const;
1420
1421 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
1422
1423 private:
1424 MathFunctionId op_;
1425};
1426
1427
1428class HLoadElements: public HUnaryOperation {
1429 public:
1430 explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1431 set_representation(Representation::Tagged());
1432 SetFlag(kUseGVN);
1433 SetFlag(kDependsOnMaps);
1434 }
1435
1436 virtual Representation RequiredInputRepresentation(int index) const {
1437 return Representation::Tagged();
1438 }
1439
1440 DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
1441};
1442
1443
1444class HCheckMap: public HUnaryOperation {
1445 public:
1446 HCheckMap(HValue* value, Handle<Map> map)
1447 : HUnaryOperation(value), map_(map) {
1448 set_representation(Representation::Tagged());
1449 SetFlag(kUseGVN);
1450 SetFlag(kDependsOnMaps);
1451 }
1452
1453 virtual Representation RequiredInputRepresentation(int index) const {
1454 return Representation::Tagged();
1455 }
1456 virtual void PrintDataTo(StringStream* stream) const;
1457 virtual HType CalculateInferredType() const;
1458
1459#ifdef DEBUG
1460 virtual void Verify() const;
1461#endif
1462
1463 Handle<Map> map() const { return map_; }
1464
1465 DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
1466
1467 protected:
1468 virtual bool DataEquals(HValue* other) const {
1469 HCheckMap* b = HCheckMap::cast(other);
1470 return map_.is_identical_to(b->map());
1471 }
1472
1473 private:
1474 Handle<Map> map_;
1475};
1476
1477
1478class HCheckFunction: public HUnaryOperation {
1479 public:
1480 HCheckFunction(HValue* value, Handle<JSFunction> function)
1481 : HUnaryOperation(value), target_(function) {
1482 set_representation(Representation::Tagged());
1483 SetFlag(kUseGVN);
1484 }
1485
1486 virtual Representation RequiredInputRepresentation(int index) const {
1487 return Representation::Tagged();
1488 }
1489 virtual void PrintDataTo(StringStream* stream) const;
1490 virtual HType CalculateInferredType() const;
1491
1492#ifdef DEBUG
1493 virtual void Verify() const;
1494#endif
1495
1496 Handle<JSFunction> target() const { return target_; }
1497
1498 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
1499
1500 protected:
1501 virtual bool DataEquals(HValue* other) const {
1502 HCheckFunction* b = HCheckFunction::cast(other);
1503 return target_.is_identical_to(b->target());
1504 }
1505
1506 private:
1507 Handle<JSFunction> target_;
1508};
1509
1510
1511class HCheckInstanceType: public HUnaryOperation {
1512 public:
1513 // Check that the instance type is in the range [first, last] where
1514 // both first and last are included.
1515 HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
1516 : HUnaryOperation(value), first_(first), last_(last) {
1517 ASSERT(first <= last);
1518 set_representation(Representation::Tagged());
1519 SetFlag(kUseGVN);
1520 }
1521
1522 virtual Representation RequiredInputRepresentation(int index) const {
1523 return Representation::Tagged();
1524 }
1525
1526#ifdef DEBUG
1527 virtual void Verify() const;
1528#endif
1529
1530 static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
1531
1532 InstanceType first() const { return first_; }
1533 InstanceType last() const { return last_; }
1534
1535 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")
1536
1537 protected:
1538 // TODO(ager): It could be nice to allow the ommision of instance
1539 // type checks if we have already performed an instance type check
1540 // with a larger range.
1541 virtual bool DataEquals(HValue* other) const {
1542 HCheckInstanceType* b = HCheckInstanceType::cast(other);
1543 return (first_ == b->first()) && (last_ == b->last());
1544 }
1545
1546 private:
1547 InstanceType first_;
1548 InstanceType last_;
1549};
1550
1551
1552class HCheckNonSmi: public HUnaryOperation {
1553 public:
1554 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
1555 set_representation(Representation::Tagged());
1556 SetFlag(kUseGVN);
1557 }
1558
1559 virtual Representation RequiredInputRepresentation(int index) const {
1560 return Representation::Tagged();
1561 }
1562
1563 virtual HType CalculateInferredType() const;
1564
1565#ifdef DEBUG
1566 virtual void Verify() const;
1567#endif
1568
1569 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
1570};
1571
1572
1573class HCheckPrototypeMaps: public HUnaryOperation {
1574 public:
1575 HCheckPrototypeMaps(HValue* value,
1576 Handle<JSObject> holder,
1577 Handle<Map> receiver_map)
1578 : HUnaryOperation(value),
1579 holder_(holder),
1580 receiver_map_(receiver_map) {
1581 set_representation(Representation::Tagged());
1582 SetFlag(kUseGVN);
1583 SetFlag(kDependsOnMaps);
1584 }
1585
1586 virtual Representation RequiredInputRepresentation(int index) const {
1587 return Representation::Tagged();
1588 }
1589
1590#ifdef DEBUG
1591 virtual void Verify() const;
1592#endif
1593
1594 Handle<JSObject> holder() const { return holder_; }
1595 Handle<Map> receiver_map() const { return receiver_map_; }
1596
1597 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
1598
1599 protected:
1600 virtual bool DataEquals(HValue* other) const {
1601 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
1602 return holder_.is_identical_to(b->holder()) &&
1603 receiver_map_.is_identical_to(b->receiver_map());
1604 }
1605
1606 private:
1607 Handle<JSObject> holder_;
1608 Handle<Map> receiver_map_;
1609};
1610
1611
1612class HCheckSmi: public HUnaryOperation {
1613 public:
1614 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
1615 set_representation(Representation::Tagged());
1616 SetFlag(kUseGVN);
1617 }
1618
1619 virtual Representation RequiredInputRepresentation(int index) const {
1620 return Representation::Tagged();
1621 }
1622 virtual HType CalculateInferredType() const;
1623
1624#ifdef DEBUG
1625 virtual void Verify() const;
1626#endif
1627
1628 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
1629};
1630
1631
1632class HPhi: public HValue {
1633 public:
1634 explicit HPhi(int merged_index)
1635 : inputs_(2),
1636 merged_index_(merged_index),
1637 phi_id_(-1) {
1638 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1639 non_phi_uses_[i] = 0;
1640 indirect_uses_[i] = 0;
1641 }
1642 ASSERT(merged_index >= 0);
1643 set_representation(Representation::Tagged());
1644 SetFlag(kFlexibleRepresentation);
1645 }
1646
1647 virtual Representation InferredRepresentation() const {
1648 bool double_occurred = false;
1649 bool int32_occurred = false;
1650 for (int i = 0; i < OperandCount(); ++i) {
1651 HValue* value = OperandAt(i);
1652 if (value->representation().IsDouble()) double_occurred = true;
1653 if (value->representation().IsInteger32()) int32_occurred = true;
1654 if (value->representation().IsTagged()) return Representation::Tagged();
1655 }
1656
1657 if (double_occurred) return Representation::Double();
1658 if (int32_occurred) return Representation::Integer32();
1659 return Representation::None();
1660 }
1661
1662 virtual Range* InferRange();
1663 virtual Representation RequiredInputRepresentation(int index) const {
1664 return representation();
1665 }
1666 virtual HType CalculateInferredType() const;
1667 virtual int OperandCount() const { return inputs_.length(); }
1668 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
1669 HValue* GetRedundantReplacement() const;
1670 void AddInput(HValue* value);
1671
1672 bool HasReceiverOperand();
1673
1674 int merged_index() const { return merged_index_; }
1675
1676 virtual const char* Mnemonic() const { return "phi"; }
1677
1678 virtual void PrintTo(StringStream* stream) const;
1679
1680#ifdef DEBUG
1681 virtual void Verify() const;
1682#endif
1683
1684 DECLARE_INSTRUCTION(Phi)
1685
1686 void InitRealUses(int id);
1687 void AddNonPhiUsesFrom(HPhi* other);
1688 void AddIndirectUsesTo(int* use_count);
1689
1690 int tagged_non_phi_uses() const {
1691 return non_phi_uses_[Representation::kTagged];
1692 }
1693 int int32_non_phi_uses() const {
1694 return non_phi_uses_[Representation::kInteger32];
1695 }
1696 int double_non_phi_uses() const {
1697 return non_phi_uses_[Representation::kDouble];
1698 }
1699 int tagged_indirect_uses() const {
1700 return indirect_uses_[Representation::kTagged];
1701 }
1702 int int32_indirect_uses() const {
1703 return indirect_uses_[Representation::kInteger32];
1704 }
1705 int double_indirect_uses() const {
1706 return indirect_uses_[Representation::kDouble];
1707 }
1708 int phi_id() { return phi_id_; }
1709
1710 protected:
1711 virtual void DeleteFromGraph();
1712 virtual void InternalSetOperandAt(int index, HValue* value) {
1713 inputs_[index] = value;
1714 }
1715
1716 private:
1717 ZoneList<HValue*> inputs_;
1718 int merged_index_;
1719
1720 int non_phi_uses_[Representation::kNumRepresentations];
1721 int indirect_uses_[Representation::kNumRepresentations];
1722 int phi_id_;
1723};
1724
1725
1726class HArgumentsObject: public HInstruction {
1727 public:
1728 HArgumentsObject() {
1729 set_representation(Representation::Tagged());
1730 SetFlag(kIsArguments);
1731 }
1732
1733 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
1734};
1735
1736
1737class HConstant: public HInstruction {
1738 public:
1739 HConstant(Handle<Object> handle, Representation r);
1740
1741 Handle<Object> handle() const { return handle_; }
1742
1743 virtual bool EmitAtUses() const { return !representation().IsDouble(); }
1744 virtual void PrintDataTo(StringStream* stream) const;
1745 virtual HType CalculateInferredType() const;
1746 bool IsInteger() const { return handle_->IsSmi(); }
1747 HConstant* CopyToRepresentation(Representation r) const;
1748 HConstant* CopyToTruncatedInt32() const;
1749 bool HasInteger32Value() const { return has_int32_value_; }
1750 int32_t Integer32Value() const {
1751 ASSERT(HasInteger32Value());
1752 return int32_value_;
1753 }
1754 bool HasDoubleValue() const { return has_double_value_; }
1755 double DoubleValue() const {
1756 ASSERT(HasDoubleValue());
1757 return double_value_;
1758 }
1759 bool HasStringValue() const { return handle_->IsString(); }
1760
1761 virtual intptr_t Hashcode() const {
1762 ASSERT(!Heap::allow_allocation(false));
1763 return reinterpret_cast<intptr_t>(*handle());
1764 }
1765
1766#ifdef DEBUG
1767 virtual void Verify() const { }
1768#endif
1769
1770 DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
1771
1772 protected:
1773 virtual Range* InferRange();
1774
1775 virtual bool DataEquals(HValue* other) const {
1776 HConstant* other_constant = HConstant::cast(other);
1777 return handle().is_identical_to(other_constant->handle());
1778 }
1779
1780 private:
1781 Handle<Object> handle_;
1782 HType constant_type_;
1783
1784 // The following two values represent the int32 and the double value of the
1785 // given constant if there is a lossless conversion between the constant
1786 // and the specific representation.
1787 bool has_int32_value_;
1788 int32_t int32_value_;
1789 bool has_double_value_;
1790 double double_value_;
1791};
1792
1793
1794class HBinaryOperation: public HInstruction {
1795 public:
1796 HBinaryOperation(HValue* left, HValue* right) {
1797 ASSERT(left != NULL && right != NULL);
1798 SetOperandAt(0, left);
1799 SetOperandAt(1, right);
1800 }
1801
1802 HValue* left() const { return OperandAt(0); }
1803 HValue* right() const { return OperandAt(1); }
1804
1805 // TODO(kasperl): Move these helpers to the IA-32 Lithium
1806 // instruction sequence builder.
1807 HValue* LeastConstantOperand() const {
1808 if (IsCommutative() && left()->IsConstant()) return right();
1809 return left();
1810 }
1811 HValue* MostConstantOperand() const {
1812 if (IsCommutative() && left()->IsConstant()) return left();
1813 return right();
1814 }
1815
1816 virtual bool IsCommutative() const { return false; }
1817
1818 virtual void PrintDataTo(StringStream* stream) const;
1819 virtual int OperandCount() const { return operands_.length(); }
1820 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1821
1822 DECLARE_INSTRUCTION(BinaryOperation)
1823
1824 protected:
1825 virtual void InternalSetOperandAt(int index, HValue* value) {
1826 operands_[index] = value;
1827 }
1828
1829 private:
1830 HOperandVector<2> operands_;
1831};
1832
1833
1834class HApplyArguments: public HInstruction {
1835 public:
1836 HApplyArguments(HValue* function,
1837 HValue* receiver,
1838 HValue* length,
1839 HValue* elements) {
1840 set_representation(Representation::Tagged());
1841 SetOperandAt(0, function);
1842 SetOperandAt(1, receiver);
1843 SetOperandAt(2, length);
1844 SetOperandAt(3, elements);
1845 }
1846
1847 virtual Representation RequiredInputRepresentation(int index) const {
1848 // The length is untagged, all other inputs are tagged.
1849 return (index == 2)
1850 ? Representation::Integer32()
1851 : Representation::Tagged();
1852 }
1853
1854 HValue* function() const { return OperandAt(0); }
1855 HValue* receiver() const { return OperandAt(1); }
1856 HValue* length() const { return OperandAt(2); }
1857 HValue* elements() const { return OperandAt(3); }
1858
1859 virtual int OperandCount() const { return operands_.length(); }
1860 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1861
1862 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
1863
1864
1865
1866 protected:
1867 virtual void InternalSetOperandAt(int index, HValue* value) {
1868 operands_[index] = value;
1869 }
1870
1871 private:
1872 HOperandVector<4> operands_;
1873};
1874
1875
1876class HArgumentsElements: public HInstruction {
1877 public:
1878 HArgumentsElements() {
1879 // The value produced by this instruction is a pointer into the stack
1880 // that looks as if it was a smi because of alignment.
1881 set_representation(Representation::Tagged());
1882 SetFlag(kUseGVN);
1883 }
1884
1885 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
1886};
1887
1888
1889class HArgumentsLength: public HUnaryOperation {
1890 public:
1891 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
1892 set_representation(Representation::Integer32());
1893 SetFlag(kUseGVN);
1894 }
1895
1896 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
1897};
1898
1899
1900class HAccessArgumentsAt: public HInstruction {
1901 public:
1902 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
1903 set_representation(Representation::Tagged());
1904 SetFlag(kUseGVN);
1905 SetOperandAt(0, arguments);
1906 SetOperandAt(1, length);
1907 SetOperandAt(2, index);
1908 }
1909
1910 virtual void PrintDataTo(StringStream* stream) const;
1911
1912 virtual Representation RequiredInputRepresentation(int index) const {
1913 // The arguments elements is considered tagged.
1914 return index == 0
1915 ? Representation::Tagged()
1916 : Representation::Integer32();
1917 }
1918
1919 HValue* arguments() const { return operands_[0]; }
1920 HValue* length() const { return operands_[1]; }
1921 HValue* index() const { return operands_[2]; }
1922
1923 virtual int OperandCount() const { return operands_.length(); }
1924 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1925
1926 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
1927
1928 protected:
1929 virtual void InternalSetOperandAt(int index, HValue* value) {
1930 operands_[index] = value;
1931 }
1932
1933 private:
1934 HOperandVector<3> operands_;
1935};
1936
1937
1938class HBoundsCheck: public HBinaryOperation {
1939 public:
1940 HBoundsCheck(HValue* index, HValue* length)
1941 : HBinaryOperation(index, length) {
1942 SetFlag(kUseGVN);
1943 }
1944
1945 virtual Representation RequiredInputRepresentation(int index) const {
1946 return Representation::Integer32();
1947 }
1948
1949#ifdef DEBUG
1950 virtual void Verify() const;
1951#endif
1952
1953 HValue* index() const { return left(); }
1954 HValue* length() const { return right(); }
1955
1956 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
1957};
1958
1959
1960class HBitwiseBinaryOperation: public HBinaryOperation {
1961 public:
1962 HBitwiseBinaryOperation(HValue* left, HValue* right)
1963 : HBinaryOperation(left, right) {
1964 // Default to truncating, Integer32, UseGVN.
1965 set_representation(Representation::Integer32());
1966 SetFlag(kTruncatingToInt32);
1967 SetFlag(kUseGVN);
1968 }
1969
1970 virtual Representation RequiredInputRepresentation(int index) const {
1971 return Representation::Integer32();
1972 }
1973
1974 DECLARE_INSTRUCTION(BitwiseBinaryOperation)
1975};
1976
1977
1978class HArithmeticBinaryOperation: public HBinaryOperation {
1979 public:
1980 HArithmeticBinaryOperation(HValue* left, HValue* right)
1981 : HBinaryOperation(left, right) {
1982 set_representation(Representation::Tagged());
1983 SetFlag(kFlexibleRepresentation);
1984 SetFlagMask(AllSideEffects());
1985 }
1986
1987 virtual void RepresentationChanged(Representation to) {
1988 if (!to.IsTagged()) {
1989 ClearFlagMask(AllSideEffects());
1990 SetFlag(kUseGVN);
1991 }
1992 }
1993
1994 virtual HType CalculateInferredType() const;
1995 virtual Representation RequiredInputRepresentation(int index) const {
1996 return representation();
1997 }
1998 virtual Representation InferredRepresentation() const {
1999 if (left()->representation().Equals(right()->representation())) {
2000 return left()->representation();
2001 }
2002 return HValue::InferredRepresentation();
2003 }
2004
2005 DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
2006};
2007
2008
2009class HCompare: public HBinaryOperation {
2010 public:
2011 HCompare(HValue* left, HValue* right, Token::Value token)
2012 : HBinaryOperation(left, right), token_(token) {
2013 ASSERT(Token::IsCompareOp(token));
2014 set_representation(Representation::Tagged());
2015 SetFlagMask(AllSideEffects());
2016 }
2017
2018 void SetInputRepresentation(Representation r);
2019 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2020 virtual Representation RequiredInputRepresentation(int index) const {
2021 return input_representation_;
2022 }
2023 Representation GetInputRepresentation() const {
2024 return input_representation_;
2025 }
2026 Token::Value token() const { return token_; }
2027 virtual void PrintDataTo(StringStream* stream) const;
2028
2029 virtual HType CalculateInferredType() const;
2030
2031 virtual intptr_t Hashcode() const {
2032 return HValue::Hashcode() * 7 + token_;
2033 }
2034
2035 DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
2036
2037 protected:
2038 virtual bool DataEquals(HValue* other) const {
2039 HCompare* comp = HCompare::cast(other);
2040 return token_ == comp->token();
2041 }
2042
2043 private:
2044 Representation input_representation_;
2045 Token::Value token_;
2046};
2047
2048
2049class HCompareJSObjectEq: public HBinaryOperation {
2050 public:
2051 HCompareJSObjectEq(HValue* left, HValue* right)
2052 : HBinaryOperation(left, right) {
2053 set_representation(Representation::Tagged());
2054 SetFlag(kUseGVN);
2055 }
2056
2057 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2058 virtual Representation RequiredInputRepresentation(int index) const {
2059 return Representation::Tagged();
2060 }
2061 virtual HType CalculateInferredType() const;
2062
2063 DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
2064};
2065
2066
2067class HUnaryPredicate: public HUnaryOperation {
2068 public:
2069 explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
2070 set_representation(Representation::Tagged());
2071 SetFlag(kUseGVN);
2072 }
2073 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2074 virtual Representation RequiredInputRepresentation(int index) const {
2075 return Representation::Tagged();
2076 }
2077 virtual HType CalculateInferredType() const;
2078};
2079
2080
2081class HIsNull: public HUnaryPredicate {
2082 public:
2083 HIsNull(HValue* value, bool is_strict)
2084 : HUnaryPredicate(value), is_strict_(is_strict) { }
2085
2086 bool is_strict() const { return is_strict_; }
2087
2088 DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
2089
2090 private:
2091 bool is_strict_;
2092};
2093
2094
2095class HIsSmi: public HUnaryPredicate {
2096 public:
2097 explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
2098
2099 DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
2100};
2101
2102
2103class HHasInstanceType: public HUnaryPredicate {
2104 public:
2105 HHasInstanceType(HValue* value, InstanceType type)
2106 : HUnaryPredicate(value), from_(type), to_(type) { }
2107 HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
2108 : HUnaryPredicate(value), from_(from), to_(to) {
2109 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
2110 }
2111
2112 InstanceType from() { return from_; }
2113 InstanceType to() { return to_; }
2114
2115 virtual void PrintDataTo(StringStream* stream) const;
2116
2117 DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
2118
2119 private:
2120 InstanceType from_;
2121 InstanceType to_; // Inclusive range, not all combinations work.
2122};
2123
2124
2125class HHasCachedArrayIndex: public HUnaryPredicate {
2126 public:
2127 explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
2128
2129 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
2130};
2131
2132
2133class HClassOfTest: public HUnaryPredicate {
2134 public:
2135 HClassOfTest(HValue* value, Handle<String> class_name)
2136 : HUnaryPredicate(value), class_name_(class_name) { }
2137
2138 DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
2139
2140 virtual void PrintDataTo(StringStream* stream) const;
2141
2142 Handle<String> class_name() const { return class_name_; }
2143
2144 private:
2145 Handle<String> class_name_;
2146};
2147
2148
2149class HTypeofIs: public HUnaryPredicate {
2150 public:
2151 HTypeofIs(HValue* value, Handle<String> type_literal)
2152 : HUnaryPredicate(value), type_literal_(type_literal) { }
2153
2154 Handle<String> type_literal() { return type_literal_; }
2155 virtual void PrintDataTo(StringStream* stream) const;
2156
2157 DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
2158
2159 protected:
2160 virtual bool DataEquals(HValue* other) const {
2161 HTypeofIs* b = HTypeofIs::cast(other);
2162 return type_literal_.is_identical_to(b->type_literal_);
2163 }
2164
2165 private:
2166 Handle<String> type_literal_;
2167};
2168
2169
2170class HInstanceOf: public HBinaryOperation {
2171 public:
2172 HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
2173 set_representation(Representation::Tagged());
2174 SetFlagMask(AllSideEffects());
2175 }
2176
2177 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2178
2179 virtual Representation RequiredInputRepresentation(int index) const {
2180 return Representation::Tagged();
2181 }
2182
2183 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
2184};
2185
2186
2187class HAdd: public HArithmeticBinaryOperation {
2188 public:
2189 HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2190 SetFlag(kCanOverflow);
2191 }
2192
2193 // Add is only commutative if two integer values are added and not if two
2194 // tagged values are added (because it might be a String concatenation).
2195 virtual bool IsCommutative() const {
2196 return !representation().IsTagged();
2197 }
2198
2199 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2200
2201 virtual HType CalculateInferredType() const;
2202
2203 DECLARE_CONCRETE_INSTRUCTION(Add, "add")
2204
2205 protected:
2206 virtual Range* InferRange();
2207};
2208
2209
2210class HSub: public HArithmeticBinaryOperation {
2211 public:
2212 HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2213 SetFlag(kCanOverflow);
2214 }
2215
2216 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2217
2218 DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
2219
2220 protected:
2221 virtual Range* InferRange();
2222};
2223
2224
2225class HMul: public HArithmeticBinaryOperation {
2226 public:
2227 HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2228 SetFlag(kCanOverflow);
2229 }
2230
2231 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2232
2233 // Only commutative if it is certain that not two objects are multiplicated.
2234 virtual bool IsCommutative() const {
2235 return !representation().IsTagged();
2236 }
2237
2238 DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
2239
2240 protected:
2241 virtual Range* InferRange();
2242};
2243
2244
2245class HMod: public HArithmeticBinaryOperation {
2246 public:
2247 HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2248 SetFlag(kCanBeDivByZero);
2249 }
2250
2251 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2252
2253 DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
2254
2255 protected:
2256 virtual Range* InferRange();
2257};
2258
2259
2260class HDiv: public HArithmeticBinaryOperation {
2261 public:
2262 HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2263 SetFlag(kCanBeDivByZero);
2264 SetFlag(kCanOverflow);
2265 }
2266
2267 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2268
2269 DECLARE_CONCRETE_INSTRUCTION(Div, "div")
2270
2271 protected:
2272 virtual Range* InferRange();
2273};
2274
2275
2276class HBitAnd: public HBitwiseBinaryOperation {
2277 public:
2278 HBitAnd(HValue* left, HValue* right)
2279 : HBitwiseBinaryOperation(left, right) { }
2280
2281 virtual bool IsCommutative() const { return true; }
2282 virtual HType CalculateInferredType() const;
2283
2284 DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
2285
2286 protected:
2287 virtual Range* InferRange();
2288};
2289
2290
2291class HBitXor: public HBitwiseBinaryOperation {
2292 public:
2293 HBitXor(HValue* left, HValue* right)
2294 : HBitwiseBinaryOperation(left, right) { }
2295
2296 virtual bool IsCommutative() const { return true; }
2297 virtual HType CalculateInferredType() const;
2298
2299 DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
2300};
2301
2302
2303class HBitOr: public HBitwiseBinaryOperation {
2304 public:
2305 HBitOr(HValue* left, HValue* right)
2306 : HBitwiseBinaryOperation(left, right) { }
2307
2308 virtual bool IsCommutative() const { return true; }
2309 virtual HType CalculateInferredType() const;
2310
2311 DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
2312
2313 protected:
2314 virtual Range* InferRange();
2315};
2316
2317
2318class HShl: public HBitwiseBinaryOperation {
2319 public:
2320 HShl(HValue* left, HValue* right)
2321 : HBitwiseBinaryOperation(left, right) { }
2322
2323 virtual Range* InferRange();
2324 virtual HType CalculateInferredType() const;
2325
2326 DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
2327};
2328
2329
2330class HShr: public HBitwiseBinaryOperation {
2331 public:
2332 HShr(HValue* left, HValue* right)
2333 : HBitwiseBinaryOperation(left, right) { }
2334
2335 virtual HType CalculateInferredType() const;
2336
2337 DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
2338};
2339
2340
2341class HSar: public HBitwiseBinaryOperation {
2342 public:
2343 HSar(HValue* left, HValue* right)
2344 : HBitwiseBinaryOperation(left, right) { }
2345
2346 virtual Range* InferRange();
2347 virtual HType CalculateInferredType() const;
2348
2349 DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
2350};
2351
2352
2353class HOsrEntry: public HInstruction {
2354 public:
2355 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
2356 SetFlag(kChangesOsrEntries);
2357 }
2358
2359 int ast_id() const { return ast_id_; }
2360
2361 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
2362
2363 private:
2364 int ast_id_;
2365};
2366
2367
2368class HParameter: public HInstruction {
2369 public:
2370 explicit HParameter(unsigned index) : index_(index) {
2371 set_representation(Representation::Tagged());
2372 }
2373
2374 unsigned index() const { return index_; }
2375
2376 virtual void PrintDataTo(StringStream* stream) const;
2377
2378 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2379
2380 private:
2381 unsigned index_;
2382};
2383
2384
2385class HCallStub: public HInstruction {
2386 public:
2387 HCallStub(CodeStub::Major major_key, int argument_count)
2388 : major_key_(major_key),
2389 argument_count_(argument_count),
2390 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
2391 set_representation(Representation::Tagged());
2392 SetFlagMask(AllSideEffects());
2393 }
2394
2395 CodeStub::Major major_key() { return major_key_; }
2396 int argument_count() { return argument_count_; }
2397
2398 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
2399 transcendental_type_ = transcendental_type;
2400 }
2401 TranscendentalCache::Type transcendental_type() {
2402 return transcendental_type_;
2403 }
2404 virtual void PrintDataTo(StringStream* stream) const;
2405
2406 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
2407
2408 private:
2409 CodeStub::Major major_key_;
2410 int argument_count_;
2411 TranscendentalCache::Type transcendental_type_;
2412};
2413
2414
2415class HUnknownOSRValue: public HInstruction {
2416 public:
2417 HUnknownOSRValue() { set_representation(Representation::Tagged()); }
2418
2419 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
2420};
2421
2422
2423class HLoadGlobal: public HInstruction {
2424 public:
2425 HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
2426 : cell_(cell), check_hole_value_(check_hole_value) {
2427 set_representation(Representation::Tagged());
2428 SetFlag(kUseGVN);
2429 SetFlag(kDependsOnGlobalVars);
2430 }
2431
2432 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2433 bool check_hole_value() const { return check_hole_value_; }
2434
2435 virtual Representation RequiredInputRepresentation(int index) const {
2436 return Representation::Tagged();
2437 }
2438 virtual void PrintDataTo(StringStream* stream) const;
2439
2440 virtual intptr_t Hashcode() const {
2441 ASSERT(!Heap::allow_allocation(false));
2442 return reinterpret_cast<intptr_t>(*cell_);
2443 }
2444
2445 DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
2446
2447 protected:
2448 virtual bool DataEquals(HValue* other) const {
2449 HLoadGlobal* b = HLoadGlobal::cast(other);
2450 return cell_.is_identical_to(b->cell());
2451 }
2452
2453 private:
2454 Handle<JSGlobalPropertyCell> cell_;
2455 bool check_hole_value_;
2456};
2457
2458
2459class HStoreGlobal: public HUnaryOperation {
2460 public:
2461 HStoreGlobal(HValue* value, Handle<JSGlobalPropertyCell> cell)
2462 : HUnaryOperation(value), cell_(cell) {
2463 SetFlag(kChangesGlobalVars);
2464 }
2465
2466 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2467
2468 virtual Representation RequiredInputRepresentation(int index) const {
2469 return Representation::Tagged();
2470 }
2471 virtual void PrintDataTo(StringStream* stream) const;
2472
2473 DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
2474
2475 protected:
2476 virtual bool DataEquals(HValue* other) const {
2477 HStoreGlobal* b = HStoreGlobal::cast(other);
2478 return cell_.is_identical_to(b->cell());
2479 }
2480
2481 private:
2482 Handle<JSGlobalPropertyCell> cell_;
2483};
2484
2485
2486class HLoadNamedField: public HUnaryOperation {
2487 public:
2488 HLoadNamedField(HValue* object, bool is_in_object, int offset)
2489 : HUnaryOperation(object),
2490 is_in_object_(is_in_object),
2491 offset_(offset) {
2492 set_representation(Representation::Tagged());
2493 SetFlag(kUseGVN);
2494 if (is_in_object) {
2495 SetFlag(kDependsOnInobjectFields);
2496 } else {
2497 SetFlag(kDependsOnBackingStoreFields);
2498 }
2499 }
2500
2501 HValue* object() const { return OperandAt(0); }
2502 bool is_in_object() const { return is_in_object_; }
2503 int offset() const { return offset_; }
2504
2505 virtual Representation RequiredInputRepresentation(int index) const {
2506 return Representation::Tagged();
2507 }
2508 virtual void PrintDataTo(StringStream* stream) const;
2509
2510 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
2511
2512 protected:
2513 virtual bool DataEquals(HValue* other) const {
2514 HLoadNamedField* b = HLoadNamedField::cast(other);
2515 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
2516 }
2517
2518 private:
2519 bool is_in_object_;
2520 int offset_;
2521};
2522
2523
2524class HLoadNamedGeneric: public HUnaryOperation {
2525 public:
2526 HLoadNamedGeneric(HValue* object, Handle<Object> name)
2527 : HUnaryOperation(object), name_(name) {
2528 set_representation(Representation::Tagged());
2529 SetFlagMask(AllSideEffects());
2530 }
2531
2532 HValue* object() const { return OperandAt(0); }
2533 Handle<Object> name() const { return name_; }
2534
2535 virtual Representation RequiredInputRepresentation(int index) const {
2536 return Representation::Tagged();
2537 }
2538
2539 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
2540
2541 protected:
2542 virtual bool DataEquals(HValue* other) const {
2543 HLoadNamedGeneric* b = HLoadNamedGeneric::cast(other);
2544 return name_.is_identical_to(b->name_);
2545 }
2546
2547 private:
2548 Handle<Object> name_;
2549};
2550
2551
2552class HLoadKeyed: public HBinaryOperation {
2553 public:
2554 HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
2555 set_representation(Representation::Tagged());
2556 }
2557
2558 virtual void PrintDataTo(StringStream* stream) const;
2559
2560 virtual Representation RequiredInputRepresentation(int index) const {
2561 return Representation::Tagged();
2562 }
2563 HValue* object() const { return OperandAt(0); }
2564 HValue* key() const { return OperandAt(1); }
2565
2566 DECLARE_INSTRUCTION(LoadKeyed)
2567};
2568
2569
2570class HLoadKeyedFastElement: public HLoadKeyed {
2571 public:
2572 HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2573 SetFlag(kDependsOnArrayElements);
2574 SetFlag(kUseGVN);
2575 }
2576
2577 virtual Representation RequiredInputRepresentation(int index) const {
2578 // The key is supposed to be Integer32.
2579 return (index == 1) ? Representation::Integer32()
2580 : Representation::Tagged();
2581 }
2582
2583 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
2584 "load_keyed_fast_element")
2585};
2586
2587
2588class HLoadKeyedGeneric: public HLoadKeyed {
2589 public:
2590 HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2591 SetFlagMask(AllSideEffects());
2592 }
2593
2594 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
2595};
2596
2597
2598class HStoreNamed: public HBinaryOperation {
2599 public:
2600 HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
2601 : HBinaryOperation(obj, val), name_(name) {
2602 }
2603
2604 virtual Representation RequiredInputRepresentation(int index) const {
2605 return Representation::Tagged();
2606 }
2607
2608 virtual void PrintDataTo(StringStream* stream) const;
2609
2610 HValue* object() const { return OperandAt(0); }
2611 Handle<Object> name() const { return name_; }
2612 HValue* value() const { return OperandAt(1); }
2613 void set_value(HValue* value) { SetOperandAt(1, value); }
2614
2615 DECLARE_INSTRUCTION(StoreNamed)
2616
2617 protected:
2618 virtual bool DataEquals(HValue* other) const {
2619 HStoreNamed* b = HStoreNamed::cast(other);
2620 return name_.is_identical_to(b->name_);
2621 }
2622
2623 private:
2624 Handle<Object> name_;
2625};
2626
2627
2628class HStoreNamedField: public HStoreNamed {
2629 public:
2630 HStoreNamedField(HValue* obj,
2631 Handle<Object> name,
2632 HValue* val,
2633 bool in_object,
2634 int offset)
2635 : HStoreNamed(obj, name, val),
2636 is_in_object_(in_object),
2637 offset_(offset) {
2638 if (is_in_object_) {
2639 SetFlag(kChangesInobjectFields);
2640 } else {
2641 SetFlag(kChangesBackingStoreFields);
2642 }
2643 }
2644
2645 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
2646
2647 virtual Representation RequiredInputRepresentation(int index) const {
2648 return Representation::Tagged();
2649 }
2650 virtual void PrintDataTo(StringStream* stream) const;
2651
2652 bool is_in_object() const { return is_in_object_; }
2653 int offset() const { return offset_; }
2654 Handle<Map> transition() const { return transition_; }
2655 void set_transition(Handle<Map> map) { transition_ = map; }
2656
2657 private:
2658 bool is_in_object_;
2659 int offset_;
2660 Handle<Map> transition_;
2661};
2662
2663
2664class HStoreNamedGeneric: public HStoreNamed {
2665 public:
2666 HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
2667 : HStoreNamed(obj, name, val) {
2668 SetFlagMask(AllSideEffects());
2669 }
2670
2671 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
2672};
2673
2674
2675class HStoreKeyed: public HInstruction {
2676 public:
2677 HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
2678 SetOperandAt(0, obj);
2679 SetOperandAt(1, key);
2680 SetOperandAt(2, val);
2681 }
2682
2683 virtual void PrintDataTo(StringStream* stream) const;
2684 virtual int OperandCount() const { return operands_.length(); }
2685 virtual HValue* OperandAt(int index) const { return operands_[index]; }
2686
2687 virtual Representation RequiredInputRepresentation(int index) const {
2688 return Representation::Tagged();
2689 }
2690
2691 HValue* object() const { return OperandAt(0); }
2692 HValue* key() const { return OperandAt(1); }
2693 HValue* value() const { return OperandAt(2); }
2694
2695 DECLARE_INSTRUCTION(StoreKeyed)
2696
2697 protected:
2698 virtual void InternalSetOperandAt(int index, HValue* value) {
2699 operands_[index] = value;
2700 }
2701
2702 private:
2703 HOperandVector<3> operands_;
2704};
2705
2706
2707class HStoreKeyedFastElement: public HStoreKeyed {
2708 public:
2709 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
2710 : HStoreKeyed(obj, key, val) {
2711 SetFlag(kChangesArrayElements);
2712 }
2713
2714 bool NeedsWriteBarrier() const {
2715 return !value()->type().IsSmi();
2716 }
2717
2718 virtual Representation RequiredInputRepresentation(int index) const {
2719 // The key is supposed to be Integer32.
2720 return (index == 1) ? Representation::Integer32()
2721 : Representation::Tagged();
2722 }
2723
2724 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
2725 "store_keyed_fast_element")
2726};
2727
2728
2729class HStoreKeyedGeneric: public HStoreKeyed {
2730 public:
2731 HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
2732 : HStoreKeyed(obj, key, val) {
2733 SetFlagMask(AllSideEffects());
2734 }
2735
2736 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
2737};
2738
2739
2740class HMaterializedLiteral: public HInstruction {
2741 public:
2742 HMaterializedLiteral(int index, int depth)
2743 : literal_index_(index), depth_(depth) {
2744 set_representation(Representation::Tagged());
2745 }
2746
2747 int literal_index() const { return literal_index_; }
2748 int depth() const { return depth_; }
2749
2750 DECLARE_INSTRUCTION(MaterializedLiteral)
2751
2752 private:
2753 int literal_index_;
2754 int depth_;
2755};
2756
2757
2758class HArrayLiteral: public HMaterializedLiteral {
2759 public:
2760 HArrayLiteral(Handle<FixedArray> constant_elements,
2761 int length,
2762 int literal_index,
2763 int depth)
2764 : HMaterializedLiteral(literal_index, depth),
2765 length_(length),
2766 constant_elements_(constant_elements) {}
2767
2768 Handle<FixedArray> constant_elements() const { return constant_elements_; }
2769 int length() const { return length_; }
2770
2771 bool IsCopyOnWrite() const;
2772
2773 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
2774
2775 private:
2776 int length_;
2777 Handle<FixedArray> constant_elements_;
2778};
2779
2780
2781class HObjectLiteral: public HMaterializedLiteral {
2782 public:
2783 HObjectLiteral(Handle<FixedArray> constant_properties,
2784 bool fast_elements,
2785 int literal_index,
2786 int depth)
2787 : HMaterializedLiteral(literal_index, depth),
2788 constant_properties_(constant_properties),
2789 fast_elements_(fast_elements) {}
2790
2791 Handle<FixedArray> constant_properties() const {
2792 return constant_properties_;
2793 }
2794 bool fast_elements() const { return fast_elements_; }
2795
2796 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
2797
2798 private:
2799 Handle<FixedArray> constant_properties_;
2800 bool fast_elements_;
2801};
2802
2803
2804class HRegExpLiteral: public HMaterializedLiteral {
2805 public:
2806 HRegExpLiteral(Handle<String> pattern,
2807 Handle<String> flags,
2808 int literal_index)
2809 : HMaterializedLiteral(literal_index, 0),
2810 pattern_(pattern),
2811 flags_(flags) { }
2812
2813 Handle<String> pattern() { return pattern_; }
2814 Handle<String> flags() { return flags_; }
2815
2816 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
2817
2818 private:
2819 Handle<String> pattern_;
2820 Handle<String> flags_;
2821};
2822
2823
2824class HFunctionLiteral: public HInstruction {
2825 public:
2826 HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
2827 : shared_info_(shared), pretenure_(pretenure) {
2828 set_representation(Representation::Tagged());
2829 }
2830
2831 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
2832
2833 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
2834 bool pretenure() const { return pretenure_; }
2835
2836 private:
2837 Handle<SharedFunctionInfo> shared_info_;
2838 bool pretenure_;
2839};
2840
2841
2842class HTypeof: public HUnaryOperation {
2843 public:
2844 explicit HTypeof(HValue* value) : HUnaryOperation(value) {
2845 set_representation(Representation::Tagged());
2846 }
2847
2848 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
2849};
2850
2851
2852class HValueOf: public HUnaryOperation {
2853 public:
2854 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
2855 set_representation(Representation::Tagged());
2856 }
2857
2858 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
2859};
2860
2861
2862class HDeleteProperty: public HBinaryOperation {
2863 public:
2864 HDeleteProperty(HValue* obj, HValue* key)
2865 : HBinaryOperation(obj, key) {
2866 set_representation(Representation::Tagged());
2867 SetFlagMask(AllSideEffects());
2868 }
2869
2870 virtual Representation RequiredInputRepresentation(int index) const {
2871 return Representation::Tagged();
2872 }
2873
2874 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
2875
2876 HValue* object() const { return left(); }
2877 HValue* key() const { return right(); }
2878};
2879
2880#undef DECLARE_INSTRUCTION
2881#undef DECLARE_CONCRETE_INSTRUCTION
2882
2883} } // namespace v8::internal
2884
2885#endif // V8_HYDROGEN_INSTRUCTIONS_H_