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