blob: eaab8adef2b0eec3406abff64bac5f8333d76ea9 [file] [log] [blame]
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001// Copyright 2011 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// 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
kasperl@chromium.orga5551262010-12-07 12:49:48 +000049#define HYDROGEN_ALL_INSTRUCTION_LIST(V) \
50 V(ArithmeticBinaryOperation) \
51 V(BinaryOperation) \
52 V(BitwiseBinaryOperation) \
53 V(Call) \
54 V(ControlInstruction) \
55 V(Instruction) \
56 V(LoadKeyed) \
57 V(MaterializedLiteral) \
58 V(Phi) \
59 V(StoreKeyed) \
60 V(StoreNamed) \
61 V(UnaryControlInstruction) \
62 V(UnaryOperation) \
63 HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
64
65
66#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000067 V(AbnormalExit) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000068 V(AccessArgumentsAt) \
69 V(Add) \
70 V(ApplyArguments) \
71 V(ArgumentsElements) \
72 V(ArgumentsLength) \
73 V(ArgumentsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000074 V(ArrayLiteral) \
75 V(BitAnd) \
76 V(BitNot) \
77 V(BitOr) \
78 V(BitXor) \
79 V(BlockEntry) \
80 V(BoundsCheck) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000081 V(CallConstantFunction) \
82 V(CallFunction) \
83 V(CallGlobal) \
84 V(CallKeyed) \
85 V(CallKnownGlobal) \
86 V(CallNamed) \
87 V(CallNew) \
88 V(CallRuntime) \
89 V(CallStub) \
90 V(Change) \
91 V(CheckFunction) \
92 V(CheckInstanceType) \
93 V(CheckMap) \
94 V(CheckNonSmi) \
95 V(CheckPrototypeMaps) \
96 V(CheckSmi) \
97 V(Compare) \
98 V(CompareJSObjectEq) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000099 V(CompareMap) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000100 V(Constant) \
101 V(DeleteProperty) \
102 V(Deoptimize) \
103 V(Div) \
104 V(EnterInlined) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000105 V(FixedArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000106 V(FunctionLiteral) \
107 V(GlobalObject) \
108 V(GlobalReceiver) \
109 V(Goto) \
110 V(InstanceOf) \
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000111 V(InstanceOfKnownGlobal) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000112 V(IsNull) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000113 V(IsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000114 V(IsSmi) \
115 V(HasInstanceType) \
116 V(HasCachedArrayIndex) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000117 V(JSArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000118 V(ClassOfTest) \
119 V(LeaveInlined) \
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000120 V(LoadContextSlot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000121 V(LoadElements) \
ager@chromium.org378b34e2011-01-28 08:04:38 +0000122 V(LoadFunctionPrototype) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000123 V(LoadGlobal) \
124 V(LoadKeyedFastElement) \
125 V(LoadKeyedGeneric) \
126 V(LoadNamedField) \
127 V(LoadNamedGeneric) \
128 V(Mod) \
129 V(Mul) \
130 V(ObjectLiteral) \
131 V(OsrEntry) \
132 V(Parameter) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000133 V(Power) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000134 V(PushArgument) \
135 V(RegExpLiteral) \
136 V(Return) \
137 V(Sar) \
138 V(Shl) \
139 V(Shr) \
140 V(Simulate) \
141 V(StackCheck) \
142 V(StoreGlobal) \
143 V(StoreKeyedFastElement) \
144 V(StoreKeyedGeneric) \
145 V(StoreNamedField) \
146 V(StoreNamedGeneric) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000147 V(StringCharCodeAt) \
148 V(StringLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000149 V(Sub) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000150 V(Test) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000151 V(Throw) \
152 V(Typeof) \
153 V(TypeofIs) \
154 V(UnaryMathOperation) \
155 V(UnknownOSRValue) \
156 V(ValueOf)
157
158#define GVN_FLAG_LIST(V) \
159 V(Calls) \
160 V(InobjectFields) \
161 V(BackingStoreFields) \
162 V(ArrayElements) \
163 V(GlobalVars) \
164 V(Maps) \
165 V(ArrayLengths) \
166 V(OsrEntries)
167
168#define DECLARE_INSTRUCTION(type) \
169 virtual bool Is##type() const { return true; } \
170 static H##type* cast(HValue* value) { \
171 ASSERT(value->Is##type()); \
172 return reinterpret_cast<H##type*>(value); \
173 } \
174 Opcode opcode() const { return HValue::k##type; }
175
176
177#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
178 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
179 virtual const char* Mnemonic() const { return mnemonic; } \
180 DECLARE_INSTRUCTION(type)
181
182
183
184template<int kSize>
185class HOperandVector : public EmbeddedVector<HValue*, kSize> {
186 public:
187 HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
188};
189
190
191class Range: public ZoneObject {
192 public:
193 Range() : lower_(kMinInt),
194 upper_(kMaxInt),
195 next_(NULL),
196 can_be_minus_zero_(false) { }
197
198 Range(int32_t lower, int32_t upper)
199 : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
200
201 bool IsInSmiRange() const {
202 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
203 }
204 void KeepOrder();
205 void Verify() const;
206 int32_t upper() const { return upper_; }
207 int32_t lower() const { return lower_; }
208 Range* next() const { return next_; }
209 Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
210 Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
211 void ClearLower() { lower_ = kMinInt; }
212 void ClearUpper() { upper_ = kMaxInt; }
213 Range* Copy() const { return new Range(lower_, upper_); }
214 bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
215 int32_t Mask() const;
216 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
217 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
218 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
219 bool CanBeNegative() const { return lower_ < 0; }
220 bool Includes(int value) const {
221 return lower_ <= value && upper_ >= value;
222 }
223
224 void Sar(int32_t value) {
225 int32_t bits = value & 0x1F;
226 lower_ = lower_ >> bits;
227 upper_ = upper_ >> bits;
228 set_can_be_minus_zero(false);
229 }
230
231 void Shl(int32_t value) {
232 int32_t bits = value & 0x1F;
233 int old_lower = lower_;
234 int old_upper = upper_;
235 lower_ = lower_ << bits;
236 upper_ = upper_ << bits;
237 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
238 upper_ = kMaxInt;
239 lower_ = kMinInt;
240 }
241 set_can_be_minus_zero(false);
242 }
243
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000244 // Adds a constant to the lower and upper bound of the range.
245 void AddConstant(int32_t value);
246
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000247 void StackUpon(Range* other) {
248 Intersect(other);
249 next_ = other;
250 }
251
252 void Intersect(Range* other) {
253 upper_ = Min(upper_, other->upper_);
254 lower_ = Max(lower_, other->lower_);
255 bool b = CanBeMinusZero() && other->CanBeMinusZero();
256 set_can_be_minus_zero(b);
257 }
258
259 void Union(Range* other) {
260 upper_ = Max(upper_, other->upper_);
261 lower_ = Min(lower_, other->lower_);
262 bool b = CanBeMinusZero() || other->CanBeMinusZero();
263 set_can_be_minus_zero(b);
264 }
265
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000266 // Compute a new result range and return true, if the operation
267 // can overflow.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000268 bool AddAndCheckOverflow(Range* other);
269 bool SubAndCheckOverflow(Range* other);
270 bool MulAndCheckOverflow(Range* other);
271
272 private:
273 int32_t lower_;
274 int32_t upper_;
275 Range* next_;
276 bool can_be_minus_zero_;
277};
278
279
280class Representation {
281 public:
282 enum Kind {
283 kNone,
284 kTagged,
285 kDouble,
286 kInteger32,
287 kNumRepresentations
288 };
289
290 Representation() : kind_(kNone) { }
291
292 static Representation None() { return Representation(kNone); }
293 static Representation Tagged() { return Representation(kTagged); }
294 static Representation Integer32() { return Representation(kInteger32); }
295 static Representation Double() { return Representation(kDouble); }
296
297 bool Equals(const Representation& other) const {
298 return kind_ == other.kind_;
299 }
300
301 Kind kind() const { return kind_; }
302 bool IsNone() const { return kind_ == kNone; }
303 bool IsTagged() const { return kind_ == kTagged; }
304 bool IsInteger32() const { return kind_ == kInteger32; }
305 bool IsDouble() const { return kind_ == kDouble; }
306 bool IsSpecialization() const {
307 return kind_ == kInteger32 || kind_ == kDouble;
308 }
309 const char* Mnemonic() const;
310
311 private:
312 explicit Representation(Kind k) : kind_(k) { }
313
314 Kind kind_;
315};
316
317
318class HType {
319 public:
320 HType() : type_(kUninitialized) { }
321
322 static HType Tagged() { return HType(kTagged); }
323 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
324 static HType TaggedNumber() { return HType(kTaggedNumber); }
325 static HType Smi() { return HType(kSmi); }
326 static HType HeapNumber() { return HType(kHeapNumber); }
327 static HType String() { return HType(kString); }
328 static HType Boolean() { return HType(kBoolean); }
329 static HType NonPrimitive() { return HType(kNonPrimitive); }
330 static HType JSArray() { return HType(kJSArray); }
331 static HType JSObject() { return HType(kJSObject); }
332 static HType Uninitialized() { return HType(kUninitialized); }
333
334 // Return the weakest (least precise) common type.
335 HType Combine(HType other) {
336 return HType(static_cast<Type>(type_ & other.type_));
337 }
338
339 bool Equals(const HType& other) {
340 return type_ == other.type_;
341 }
342
343 bool IsSubtypeOf(const HType& other) {
344 return Combine(other).Equals(other);
345 }
346
347 bool IsTagged() {
348 ASSERT(type_ != kUninitialized);
349 return ((type_ & kTagged) == kTagged);
350 }
351
352 bool IsTaggedPrimitive() {
353 ASSERT(type_ != kUninitialized);
354 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
355 }
356
357 bool IsTaggedNumber() {
358 ASSERT(type_ != kUninitialized);
359 return ((type_ & kTaggedNumber) == kTaggedNumber);
360 }
361
362 bool IsSmi() {
363 ASSERT(type_ != kUninitialized);
364 return ((type_ & kSmi) == kSmi);
365 }
366
367 bool IsHeapNumber() {
368 ASSERT(type_ != kUninitialized);
369 return ((type_ & kHeapNumber) == kHeapNumber);
370 }
371
372 bool IsString() {
373 ASSERT(type_ != kUninitialized);
374 return ((type_ & kString) == kString);
375 }
376
377 bool IsBoolean() {
378 ASSERT(type_ != kUninitialized);
379 return ((type_ & kBoolean) == kBoolean);
380 }
381
382 bool IsNonPrimitive() {
383 ASSERT(type_ != kUninitialized);
384 return ((type_ & kNonPrimitive) == kNonPrimitive);
385 }
386
387 bool IsJSArray() {
388 ASSERT(type_ != kUninitialized);
389 return ((type_ & kJSArray) == kJSArray);
390 }
391
392 bool IsJSObject() {
393 ASSERT(type_ != kUninitialized);
394 return ((type_ & kJSObject) == kJSObject);
395 }
396
397 bool IsUninitialized() {
398 return type_ == kUninitialized;
399 }
400
401 static HType TypeFromValue(Handle<Object> value);
402
403 const char* ToString();
404 const char* ToShortString();
405
406 private:
407 enum Type {
408 kTagged = 0x1, // 0000 0000 0000 0001
409 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
410 kTaggedNumber = 0xd, // 0000 0000 0000 1101
411 kSmi = 0x1d, // 0000 0000 0001 1101
412 kHeapNumber = 0x2d, // 0000 0000 0010 1101
413 kString = 0x45, // 0000 0000 0100 0101
414 kBoolean = 0x85, // 0000 0000 1000 0101
415 kNonPrimitive = 0x101, // 0000 0001 0000 0001
416 kJSObject = 0x301, // 0000 0011 0000 0001
417 kJSArray = 0x701, // 0000 0111 1000 0001
418 kUninitialized = 0x1fff // 0001 1111 1111 1111
419 };
420
421 explicit HType(Type t) : type_(t) { }
422
423 Type type_;
424};
425
426
427class HValue: public ZoneObject {
428 public:
429 static const int kNoNumber = -1;
430
431 // There must be one corresponding kDepends flag for every kChanges flag and
432 // the order of the kChanges flags must be exactly the same as of the kDepends
433 // flags.
434 enum Flag {
435 // Declare global value numbering flags.
436 #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
437 GVN_FLAG_LIST(DECLARE_DO)
438 #undef DECLARE_DO
439 kFlexibleRepresentation,
440 kUseGVN,
441 kCanOverflow,
442 kBailoutOnMinusZero,
443 kCanBeDivByZero,
444 kIsArguments,
445 kTruncatingToInt32,
446 kLastFlag = kTruncatingToInt32
447 };
448
449 STATIC_ASSERT(kLastFlag < kBitsPerInt);
450
451 static const int kChangesToDependsFlagsLeftShift = 1;
452
453 static int ChangesFlagsMask() {
454 int result = 0;
455 // Create changes mask.
456#define DECLARE_DO(type) result |= (1 << kChanges##type);
457 GVN_FLAG_LIST(DECLARE_DO)
458#undef DECLARE_DO
459 return result;
460 }
461
462 static int DependsFlagsMask() {
463 return ConvertChangesToDependsFlags(ChangesFlagsMask());
464 }
465
466 static int ConvertChangesToDependsFlags(int flags) {
467 return flags << kChangesToDependsFlagsLeftShift;
468 }
469
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000470 static HValue* cast(HValue* value) { return value; }
471
472 enum Opcode {
473 // Declare a unique enum value for each hydrogen instruction.
474 #define DECLARE_DO(type) k##type,
475 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
476 #undef DECLARE_DO
477 kMaxInstructionClass
478 };
479
480 HValue() : block_(NULL),
481 id_(kNoNumber),
482 uses_(2),
483 type_(HType::Tagged()),
484 range_(NULL),
485 flags_(0) {}
486 virtual ~HValue() {}
487
488 HBasicBlock* block() const { return block_; }
489 void SetBlock(HBasicBlock* block);
490
491 int id() const { return id_; }
492 void set_id(int id) { id_ = id; }
493
494 const ZoneList<HValue*>* uses() const { return &uses_; }
495
496 virtual bool EmitAtUses() const { return false; }
497 Representation representation() const { return representation_; }
498 void ChangeRepresentation(Representation r) {
499 // Representation was already set and is allowed to be changed.
500 ASSERT(!representation_.IsNone());
501 ASSERT(!r.IsNone());
502 ASSERT(CheckFlag(kFlexibleRepresentation));
503 RepresentationChanged(r);
504 representation_ = r;
505 }
506
507 HType type() const { return type_; }
508 void set_type(HType type) {
509 ASSERT(uses_.length() == 0);
510 type_ = type;
511 }
512
513 // An operation needs to override this function iff:
514 // 1) it can produce an int32 output.
515 // 2) the true value of its output can potentially be minus zero.
516 // The implementation must set a flag so that it bails out in the case where
517 // it would otherwise output what should be a minus zero as an int32 zero.
518 // If the operation also exists in a form that takes int32 and outputs int32
519 // then the operation should return its input value so that we can propagate
520 // back. There are two operations that need to propagate back to more than
521 // one input. They are phi and binary add. They always return NULL and
522 // expect the caller to take care of things.
523 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
524 visited->Add(id());
525 return NULL;
526 }
527
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000528 bool IsDefinedAfter(HBasicBlock* other) const;
529
530 // Operands.
531 virtual int OperandCount() const { return 0; }
532 virtual HValue* OperandAt(int index) const {
533 UNREACHABLE();
534 return NULL;
535 }
536 void SetOperandAt(int index, HValue* value);
537
538 int LookupOperandIndex(int occurrence_index, HValue* op) const;
539 bool UsesMultipleTimes(HValue* op) const;
540
541 void ReplaceAndDelete(HValue* other);
542 void ReplaceValue(HValue* other);
543 void ReplaceAtUse(HValue* use, HValue* other);
544 void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
545 bool HasNoUses() const { return uses_.is_empty(); }
546 void ClearOperands();
547 void Delete();
548
549 int flags() const { return flags_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000550 void SetFlag(Flag f) { flags_ |= (1 << f); }
551 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
552 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
553
554 void SetAllSideEffects() { flags_ |= AllSideEffects(); }
555 void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
556 bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000557
558 Range* range() const { return range_; }
559 bool HasRange() const { return range_ != NULL; }
560 void AddNewRange(Range* r);
561 void RemoveLastAddedRange();
562 void ComputeInitialRange();
563
564 // Representation helpers.
565 virtual Representation RequiredInputRepresentation(int index) const {
566 return Representation::None();
567 }
568 virtual Representation InferredRepresentation() const {
569 return representation();
570 }
571
572 // This gives the instruction an opportunity to replace itself with an
573 // instruction that does the same in some better way. To replace an
574 // instruction with a new one, first add the new instruction to the graph,
575 // then return it. Return NULL to have the instruction deleted.
576 virtual HValue* Canonicalize() { return this; }
577
578 // Declare virtual type testers.
579#define DECLARE_DO(type) virtual bool Is##type() const { return false; }
580 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
581#undef DECLARE_DO
582
583 bool Equals(HValue* other) const;
584 virtual intptr_t Hashcode() const;
585
586 // Printing support.
587 virtual void PrintTo(StringStream* stream) const = 0;
588 void PrintNameTo(StringStream* stream);
589 static void PrintTypeTo(HType type, StringStream* stream);
590
591 virtual const char* Mnemonic() const = 0;
592 virtual Opcode opcode() const = 0;
593
594 // Updated the inferred type of this instruction and returns true if
595 // it has changed.
596 bool UpdateInferredType();
597
598 virtual HType CalculateInferredType() const;
599
600 // Helper for type conversions used by normal and phi instructions.
601 void InsertInputConversion(HInstruction* previous, int index, HType type);
602
603#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000604 virtual void Verify() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000605#endif
606
607 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000608 // This function must be overridden for instructions with flag kUseGVN, to
609 // compare the non-Operand parts of the instruction.
610 virtual bool DataEquals(HValue* other) const {
611 UNREACHABLE();
612 return false;
613 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000614 virtual void RepresentationChanged(Representation to) { }
615 virtual Range* InferRange();
616 virtual void DeleteFromGraph() = 0;
617 virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
618 void clear_block() {
619 ASSERT(block_ != NULL);
620 block_ = NULL;
621 }
622
623 void set_representation(Representation r) {
624 // Representation is set-once.
625 ASSERT(representation_.IsNone() && !r.IsNone());
626 representation_ = r;
627 }
628
629 private:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000630 // A flag mask to mark an instruction as having arbitrary side effects.
631 static int AllSideEffects() {
632 return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
633 }
634
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000635 void InternalReplaceAtUse(HValue* use, HValue* other);
636 void RegisterUse(int index, HValue* new_value);
637
638 HBasicBlock* block_;
639
640 // The id of this instruction in the hydrogen graph, assigned when first
641 // added to the graph. Reflects creation order.
642 int id_;
643
644 Representation representation_;
645 ZoneList<HValue*> uses_;
646 HType type_;
647 Range* range_;
648 int flags_;
649
650 DISALLOW_COPY_AND_ASSIGN(HValue);
651};
652
653
654class HInstruction: public HValue {
655 public:
656 HInstruction* next() const { return next_; }
657 HInstruction* previous() const { return previous_; }
658
659 void PrintTo(StringStream* stream) const;
660 virtual void PrintDataTo(StringStream* stream) const {}
661
662 bool IsLinked() const { return block() != NULL; }
663 void Unlink();
664 void InsertBefore(HInstruction* next);
665 void InsertAfter(HInstruction* previous);
666
667 int position() const { return position_; }
668 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
669 void set_position(int position) { position_ = position; }
670
671 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
672
673#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000674 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000675#endif
676
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000677 // Returns whether this is some kind of deoptimizing check
678 // instruction.
679 virtual bool IsCheckInstruction() const { return false; }
680
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000681 DECLARE_INSTRUCTION(Instruction)
682
683 protected:
684 HInstruction()
685 : next_(NULL),
686 previous_(NULL),
687 position_(RelocInfo::kNoPosition) {
688 SetFlag(kDependsOnOsrEntries);
689 }
690
691 virtual void DeleteFromGraph() { Unlink(); }
692
693 private:
694 void InitializeAsFirst(HBasicBlock* block) {
695 ASSERT(!IsLinked());
696 SetBlock(block);
697 }
698
699 HInstruction* next_;
700 HInstruction* previous_;
701 int position_;
702
703 friend class HBasicBlock;
704};
705
706
707class HBlockEntry: public HInstruction {
708 public:
709 DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
710};
711
712
713class HControlInstruction: public HInstruction {
714 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000715 HControlInstruction(HBasicBlock* first, HBasicBlock* second)
716 : first_successor_(first), second_successor_(second) {
717 }
718
719 HBasicBlock* FirstSuccessor() const { return first_successor_; }
720 HBasicBlock* SecondSuccessor() const { return second_successor_; }
721
722 virtual void PrintDataTo(StringStream* stream) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000723
724 DECLARE_INSTRUCTION(ControlInstruction)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000725
726 private:
727 HBasicBlock* first_successor_;
728 HBasicBlock* second_successor_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000729};
730
731
732class HDeoptimize: public HControlInstruction {
733 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000734 HDeoptimize() : HControlInstruction(NULL, NULL) { }
735
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000736 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
737};
738
739
740class HGoto: public HControlInstruction {
741 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000742 explicit HGoto(HBasicBlock* target)
743 : HControlInstruction(target, NULL), include_stack_check_(false) {
744 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000745
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000746 void set_include_stack_check(bool include_stack_check) {
747 include_stack_check_ = include_stack_check;
748 }
749 bool include_stack_check() const { return include_stack_check_; }
750
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000751 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
752
753 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000754 bool include_stack_check_;
755};
756
757
758class HUnaryControlInstruction: public HControlInstruction {
759 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000760 explicit HUnaryControlInstruction(HValue* value,
761 HBasicBlock* true_target,
762 HBasicBlock* false_target)
763 : HControlInstruction(true_target, false_target) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000764 SetOperandAt(0, value);
765 }
766
767 virtual Representation RequiredInputRepresentation(int index) const {
768 return Representation::Tagged();
769 }
770
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000771 virtual void PrintDataTo(StringStream* stream) const;
772
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000773 HValue* value() const { return OperandAt(0); }
774 virtual int OperandCount() const { return 1; }
775 virtual HValue* OperandAt(int index) const { return operands_[index]; }
776
777 DECLARE_INSTRUCTION(UnaryControlInstruction)
778
779 protected:
780 virtual void InternalSetOperandAt(int index, HValue* value) {
781 operands_[index] = value;
782 }
783
784 private:
785 HOperandVector<1> operands_;
786};
787
788
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000789class HTest: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000790 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000791 HTest(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target)
792 : HUnaryControlInstruction(value, true_target, false_target) {
793 ASSERT(true_target != NULL && false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000794 }
795
796 virtual Representation RequiredInputRepresentation(int index) const {
797 return Representation::None();
798 }
799
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000800 DECLARE_CONCRETE_INSTRUCTION(Test, "test")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000801};
802
803
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000804class HCompareMap: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000805 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000806 HCompareMap(HValue* value,
807 Handle<Map> map,
808 HBasicBlock* true_target,
809 HBasicBlock* false_target)
810 : HUnaryControlInstruction(value, true_target, false_target),
811 map_(map) {
812 ASSERT(true_target != NULL);
813 ASSERT(false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000814 ASSERT(!map.is_null());
815 }
816
whesse@chromium.org023421e2010-12-21 12:19:12 +0000817 virtual void PrintDataTo(StringStream* stream) const;
818
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000819 Handle<Map> map() const { return map_; }
820
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000821 DECLARE_CONCRETE_INSTRUCTION(CompareMap, "compare_map")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000822
823 private:
824 Handle<Map> map_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000825};
826
827
828class HReturn: public HUnaryControlInstruction {
829 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000830 explicit HReturn(HValue* value)
831 : HUnaryControlInstruction(value, NULL, NULL) {
832 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000833
834 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
835};
836
837
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000838class HAbnormalExit: public HControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000839 public:
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000840 HAbnormalExit() : HControlInstruction(NULL, NULL) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000841
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000842 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000843};
844
845
846class HUnaryOperation: public HInstruction {
847 public:
848 explicit HUnaryOperation(HValue* value) {
849 SetOperandAt(0, value);
850 }
851
852 HValue* value() const { return OperandAt(0); }
853 virtual void PrintDataTo(StringStream* stream) const;
854 virtual int OperandCount() const { return 1; }
855 virtual HValue* OperandAt(int index) const { return operands_[index]; }
856
857 DECLARE_INSTRUCTION(UnaryOperation)
858
859 protected:
860 virtual void InternalSetOperandAt(int index, HValue* value) {
861 operands_[index] = value;
862 }
863
864 private:
865 HOperandVector<1> operands_;
866};
867
868
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000869class HThrow: public HUnaryOperation {
870 public:
871 explicit HThrow(HValue* value) : HUnaryOperation(value) {
872 SetAllSideEffects();
873 }
874
875 virtual Representation RequiredInputRepresentation(int index) const {
876 return Representation::Tagged();
877 }
878
879 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
880};
881
882
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000883class HChange: public HUnaryOperation {
884 public:
885 HChange(HValue* value,
886 Representation from,
887 Representation to)
888 : HUnaryOperation(value), from_(from), to_(to) {
889 ASSERT(!from.IsNone() && !to.IsNone());
890 ASSERT(!from.Equals(to));
891 set_representation(to);
892 SetFlag(kUseGVN);
893
894 if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
895 value->range()->IsInSmiRange()) {
896 set_type(HType::Smi());
897 }
898 }
899
900 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
901
902 Representation from() const { return from_; }
903 Representation to() const { return to_; }
904 virtual Representation RequiredInputRepresentation(int index) const {
905 return from_;
906 }
907
908 bool CanTruncateToInt32() const {
909 for (int i = 0; i < uses()->length(); ++i) {
910 if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
911 }
912 return true;
913 }
914
915 virtual void PrintDataTo(StringStream* stream) const;
916
917 DECLARE_CONCRETE_INSTRUCTION(Change,
918 CanTruncateToInt32() ? "truncate" : "change")
919
920 protected:
921 virtual bool DataEquals(HValue* other) const {
922 if (!other->IsChange()) return false;
923 HChange* change = HChange::cast(other);
924 return value() == change->value()
925 && to().Equals(change->to())
926 && CanTruncateToInt32() == change->CanTruncateToInt32();
927 }
928
929 private:
930 Representation from_;
931 Representation to_;
932};
933
934
935class HSimulate: public HInstruction {
936 public:
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000937 HSimulate(int ast_id, int pop_count, int environment_length)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000938 : ast_id_(ast_id),
939 pop_count_(pop_count),
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000940 environment_length_(environment_length),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000941 values_(2),
942 assigned_indexes_(2) {}
943 virtual ~HSimulate() {}
944
945 virtual void PrintDataTo(StringStream* stream) const;
946
947 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
948 int ast_id() const { return ast_id_; }
949 void set_ast_id(int id) {
950 ASSERT(!HasAstId());
951 ast_id_ = id;
952 }
953
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000954 int environment_length() const { return environment_length_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000955 int pop_count() const { return pop_count_; }
956 const ZoneList<HValue*>* values() const { return &values_; }
957 int GetAssignedIndexAt(int index) const {
958 ASSERT(HasAssignedIndexAt(index));
959 return assigned_indexes_[index];
960 }
961 bool HasAssignedIndexAt(int index) const {
962 return assigned_indexes_[index] != kNoIndex;
963 }
964 void AddAssignedValue(int index, HValue* value) {
965 AddValue(index, value);
966 }
967 void AddPushedValue(HValue* value) {
968 AddValue(kNoIndex, value);
969 }
970 virtual int OperandCount() const { return values_.length(); }
971 virtual HValue* OperandAt(int index) const { return values_[index]; }
972
973 DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
974
975#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000976 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000977#endif
978
979 protected:
980 virtual void InternalSetOperandAt(int index, HValue* value) {
981 values_[index] = value;
982 }
983
984 private:
985 static const int kNoIndex = -1;
986 void AddValue(int index, HValue* value) {
987 assigned_indexes_.Add(index);
988 // Resize the list of pushed values.
989 values_.Add(NULL);
990 // Set the operand through the base method in HValue to make sure that the
991 // use lists are correctly updated.
992 SetOperandAt(values_.length() - 1, value);
993 }
994 int ast_id_;
995 int pop_count_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000996 int environment_length_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000997 ZoneList<HValue*> values_;
998 ZoneList<int> assigned_indexes_;
999};
1000
1001
1002class HStackCheck: public HInstruction {
1003 public:
1004 HStackCheck() { }
1005
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001006 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001007};
1008
1009
1010class HEnterInlined: public HInstruction {
1011 public:
1012 HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
1013 : closure_(closure), function_(function) {
1014 }
1015
1016 virtual void PrintDataTo(StringStream* stream) const;
1017
1018 Handle<JSFunction> closure() const { return closure_; }
1019 FunctionLiteral* function() const { return function_; }
1020
1021 DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
1022
1023 private:
1024 Handle<JSFunction> closure_;
1025 FunctionLiteral* function_;
1026};
1027
1028
1029class HLeaveInlined: public HInstruction {
1030 public:
1031 HLeaveInlined() {}
1032
1033 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
1034};
1035
1036
1037class HPushArgument: public HUnaryOperation {
1038 public:
1039 explicit HPushArgument(HValue* value)
1040 : HUnaryOperation(value), argument_index_(-1) {
1041 set_representation(Representation::Tagged());
1042 }
1043
1044 virtual Representation RequiredInputRepresentation(int index) const {
1045 return Representation::Tagged();
1046 }
1047
1048 virtual void PrintDataTo(StringStream* stream) const;
1049 HValue* argument() const { return OperandAt(0); }
1050 int argument_index() const { return argument_index_; }
1051 void set_argument_index(int index) {
1052 ASSERT(argument_index_ == -1 || index == argument_index_);
1053 argument_index_ = index;
1054 }
1055
1056 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
1057
1058 private:
1059 int argument_index_;
1060};
1061
1062
1063class HGlobalObject: public HInstruction {
1064 public:
1065 HGlobalObject() {
1066 set_representation(Representation::Tagged());
1067 SetFlag(kUseGVN);
1068 SetFlag(kDependsOnCalls);
1069 }
1070
1071 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001072
1073 protected:
1074 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001075};
1076
1077
1078class HGlobalReceiver: public HInstruction {
1079 public:
1080 HGlobalReceiver() {
1081 set_representation(Representation::Tagged());
1082 SetFlag(kUseGVN);
1083 SetFlag(kDependsOnCalls);
1084 }
1085
1086 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001087
1088 protected:
1089 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001090};
1091
1092
1093class HCall: public HInstruction {
1094 public:
1095 // Construct a call with uninitialized arguments. The argument count
1096 // includes the receiver.
1097 explicit HCall(int count);
1098
1099 virtual HType CalculateInferredType() const { return HType::Tagged(); }
1100
1101 // TODO(3190496): This needs a cleanup. We don't want the arguments
1102 // be operands of the call instruction. This results in bad code quality.
1103 virtual int argument_count() const { return arguments_.length(); }
1104 virtual int OperandCount() const { return argument_count(); }
1105 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1106 virtual HPushArgument* PushArgumentAt(int index) const {
1107 return HPushArgument::cast(OperandAt(index));
1108 }
1109 virtual HValue* ArgumentAt(int index) const {
1110 return PushArgumentAt(index)->argument();
1111 }
1112 virtual void SetArgumentAt(int index, HPushArgument* push_argument);
1113
1114 virtual void PrintDataTo(StringStream* stream) const;
1115
1116 DECLARE_INSTRUCTION(Call)
1117
1118 protected:
1119 virtual void InternalSetOperandAt(int index, HValue* value) {
1120 arguments_[index] = value;
1121 }
1122
1123 int argument_count_;
1124 Vector<HValue*> arguments_;
1125};
1126
1127
1128class HCallConstantFunction: public HCall {
1129 public:
1130 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1131 : HCall(argument_count), function_(function) { }
1132
1133 Handle<JSFunction> function() const { return function_; }
1134 bool IsApplyFunction() const {
1135 return function_->code() == Builtins::builtin(Builtins::FunctionApply);
1136 }
1137
1138 virtual void PrintDataTo(StringStream* stream) const;
1139
1140 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
1141
1142 private:
1143 Handle<JSFunction> function_;
1144};
1145
1146
1147class HCallKeyed: public HCall {
1148 public:
1149 HCallKeyed(HValue* key, int argument_count)
1150 : HCall(argument_count + 1) {
1151 SetOperandAt(0, key);
1152 }
1153
1154 virtual Representation RequiredInputRepresentation(int index) const {
1155 return Representation::Tagged();
1156 }
1157
1158 // TODO(3190496): This is a hack to get an additional operand that
1159 // is not an argument to work with the current setup. This _needs_ a cleanup.
1160 // (see HCall)
1161 virtual void PrintDataTo(StringStream* stream) const;
1162 HValue* key() const { return OperandAt(0); }
1163 virtual int argument_count() const { return arguments_.length() - 1; }
1164 virtual int OperandCount() const { return arguments_.length(); }
1165 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1166 virtual HPushArgument* PushArgumentAt(int index) const {
1167 return HPushArgument::cast(OperandAt(index + 1));
1168 }
1169 virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
1170 HCall::SetArgumentAt(index + 1, push_argument);
1171 }
1172
1173 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
1174};
1175
1176
1177class HCallNamed: public HCall {
1178 public:
1179 HCallNamed(Handle<String> name, int argument_count)
1180 : HCall(argument_count), name_(name) { }
1181 virtual void PrintDataTo(StringStream* stream) const;
1182
1183 Handle<String> name() const { return name_; }
1184
1185 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
1186
1187 private:
1188 Handle<String> name_;
1189};
1190
1191
1192class HCallFunction: public HCall {
1193 public:
1194 explicit HCallFunction(int argument_count) : HCall(argument_count) { }
1195
1196 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
1197};
1198
1199
1200class HCallGlobal: public HCall {
1201 public:
1202 HCallGlobal(Handle<String> name, int argument_count)
1203 : HCall(argument_count), name_(name) { }
1204
1205 virtual void PrintDataTo(StringStream* stream) const;
1206
1207 Handle<String> name() const { return name_; }
1208
1209 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
1210
1211 private:
1212 Handle<String> name_;
1213};
1214
1215
1216class HCallKnownGlobal: public HCall {
1217 public:
1218 HCallKnownGlobal(Handle<JSFunction> target,
1219 int argument_count)
1220 : HCall(argument_count), target_(target) { }
1221
1222 Handle<JSFunction> target() const { return target_; }
1223
1224 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
1225
1226 private:
1227 Handle<JSFunction> target_;
1228};
1229
1230
1231class HCallNew: public HCall {
1232 public:
1233 explicit HCallNew(int argument_count) : HCall(argument_count) { }
1234
1235 virtual Representation RequiredInputRepresentation(int index) const {
1236 return Representation::Tagged();
1237 }
1238
1239 HValue* constructor() const { return ArgumentAt(0); }
1240
1241 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
1242};
1243
1244
1245class HCallRuntime: public HCall {
1246 public:
1247 HCallRuntime(Handle<String> name,
1248 Runtime::Function* c_function,
1249 int argument_count)
1250 : HCall(argument_count), c_function_(c_function), name_(name) { }
1251 virtual void PrintDataTo(StringStream* stream) const;
1252
1253 Runtime::Function* function() const { return c_function_; }
1254 Handle<String> name() const { return name_; }
1255
1256 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
1257
1258 private:
1259 Runtime::Function* c_function_;
1260 Handle<String> name_;
1261};
1262
1263
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001264class HJSArrayLength: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001265 public:
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001266 explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001267 // The length of an array is stored as a tagged value in the array
1268 // object. It is guaranteed to be 32 bit integer, but it can be
1269 // represented as either a smi or heap number.
1270 set_representation(Representation::Tagged());
1271 SetFlag(kDependsOnArrayLengths);
1272 SetFlag(kUseGVN);
1273 }
1274
1275 virtual Representation RequiredInputRepresentation(int index) const {
1276 return Representation::Tagged();
1277 }
1278
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001279 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001280
1281 protected:
1282 virtual bool DataEquals(HValue* other) const { return true; }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001283};
1284
1285
1286class HFixedArrayLength: public HUnaryOperation {
1287 public:
1288 explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
1289 set_representation(Representation::Tagged());
1290 SetFlag(kDependsOnArrayLengths);
1291 SetFlag(kUseGVN);
1292 }
1293
1294 virtual Representation RequiredInputRepresentation(int index) const {
1295 return Representation::Tagged();
1296 }
1297
1298 DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001299
1300 protected:
1301 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001302};
1303
1304
1305class HBitNot: public HUnaryOperation {
1306 public:
1307 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1308 set_representation(Representation::Integer32());
1309 SetFlag(kUseGVN);
1310 SetFlag(kTruncatingToInt32);
1311 }
1312
1313 virtual Representation RequiredInputRepresentation(int index) const {
1314 return Representation::Integer32();
1315 }
1316 virtual HType CalculateInferredType() const;
1317
1318 DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001319
1320 protected:
1321 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001322};
1323
1324
1325class HUnaryMathOperation: public HUnaryOperation {
1326 public:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001327 HUnaryMathOperation(HValue* value, BuiltinFunctionId op)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001328 : HUnaryOperation(value), op_(op) {
1329 switch (op) {
1330 case kMathFloor:
1331 case kMathRound:
1332 case kMathCeil:
1333 set_representation(Representation::Integer32());
1334 break;
1335 case kMathAbs:
1336 set_representation(Representation::Tagged());
1337 SetFlag(kFlexibleRepresentation);
1338 break;
1339 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001340 case kMathPowHalf:
1341 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001342 case kMathSin:
1343 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001344 set_representation(Representation::Double());
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001345 break;
1346 default:
1347 UNREACHABLE();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001348 }
1349 SetFlag(kUseGVN);
1350 }
1351
1352 virtual void PrintDataTo(StringStream* stream) const;
1353
1354 virtual HType CalculateInferredType() const;
1355
1356 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1357
1358 virtual Representation RequiredInputRepresentation(int index) const {
1359 switch (op_) {
1360 case kMathFloor:
1361 case kMathRound:
1362 case kMathCeil:
1363 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001364 case kMathPowHalf:
1365 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001366 case kMathSin:
1367 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001368 return Representation::Double();
1369 break;
1370 case kMathAbs:
1371 return representation();
1372 break;
1373 default:
1374 return Representation::None();
1375 }
1376 }
1377
1378 virtual HValue* Canonicalize() {
1379 // If the input is integer32 then we replace the floor instruction
1380 // with its inputs. This happens before the representation changes are
1381 // introduced.
1382 if (op() == kMathFloor) {
1383 if (value()->representation().IsInteger32()) return value();
1384 }
1385 return this;
1386 }
1387
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001388 BuiltinFunctionId op() const { return op_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001389 const char* OpName() const;
1390
1391 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
1392
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001393 protected:
1394 virtual bool DataEquals(HValue* other) const {
1395 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
1396 return op_ == b->op();
1397 }
1398
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001399 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001400 BuiltinFunctionId op_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001401};
1402
1403
1404class HLoadElements: public HUnaryOperation {
1405 public:
1406 explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1407 set_representation(Representation::Tagged());
1408 SetFlag(kUseGVN);
1409 SetFlag(kDependsOnMaps);
1410 }
1411
1412 virtual Representation RequiredInputRepresentation(int index) const {
1413 return Representation::Tagged();
1414 }
1415
1416 DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001417
1418 protected:
1419 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001420};
1421
1422
1423class HCheckMap: public HUnaryOperation {
1424 public:
1425 HCheckMap(HValue* value, Handle<Map> map)
1426 : HUnaryOperation(value), map_(map) {
1427 set_representation(Representation::Tagged());
1428 SetFlag(kUseGVN);
1429 SetFlag(kDependsOnMaps);
1430 }
1431
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001432 virtual bool IsCheckInstruction() const { return true; }
1433
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001434 virtual Representation RequiredInputRepresentation(int index) const {
1435 return Representation::Tagged();
1436 }
1437 virtual void PrintDataTo(StringStream* stream) const;
1438 virtual HType CalculateInferredType() const;
1439
1440#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001441 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001442#endif
1443
1444 Handle<Map> map() const { return map_; }
1445
1446 DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
1447
1448 protected:
1449 virtual bool DataEquals(HValue* other) const {
1450 HCheckMap* b = HCheckMap::cast(other);
1451 return map_.is_identical_to(b->map());
1452 }
1453
1454 private:
1455 Handle<Map> map_;
1456};
1457
1458
1459class HCheckFunction: public HUnaryOperation {
1460 public:
1461 HCheckFunction(HValue* value, Handle<JSFunction> function)
1462 : HUnaryOperation(value), target_(function) {
1463 set_representation(Representation::Tagged());
1464 SetFlag(kUseGVN);
1465 }
1466
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001467 virtual bool IsCheckInstruction() const { return true; }
1468
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001469 virtual Representation RequiredInputRepresentation(int index) const {
1470 return Representation::Tagged();
1471 }
1472 virtual void PrintDataTo(StringStream* stream) const;
1473 virtual HType CalculateInferredType() const;
1474
1475#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001476 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001477#endif
1478
1479 Handle<JSFunction> target() const { return target_; }
1480
1481 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
1482
1483 protected:
1484 virtual bool DataEquals(HValue* other) const {
1485 HCheckFunction* b = HCheckFunction::cast(other);
1486 return target_.is_identical_to(b->target());
1487 }
1488
1489 private:
1490 Handle<JSFunction> target_;
1491};
1492
1493
1494class HCheckInstanceType: public HUnaryOperation {
1495 public:
1496 // Check that the instance type is in the range [first, last] where
1497 // both first and last are included.
1498 HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
1499 : HUnaryOperation(value), first_(first), last_(last) {
1500 ASSERT(first <= last);
1501 set_representation(Representation::Tagged());
1502 SetFlag(kUseGVN);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001503 if ((FIRST_STRING_TYPE < first && last <= LAST_STRING_TYPE) ||
1504 (FIRST_STRING_TYPE <= first && last < LAST_STRING_TYPE)) {
1505 // A particular string instance type can change because of GC or
1506 // externalization, but the value still remains a string.
1507 SetFlag(kDependsOnMaps);
1508 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001509 }
1510
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001511 virtual bool IsCheckInstruction() const { return true; }
1512
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001513 virtual Representation RequiredInputRepresentation(int index) const {
1514 return Representation::Tagged();
1515 }
1516
1517#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001518 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001519#endif
1520
1521 static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
1522
1523 InstanceType first() const { return first_; }
1524 InstanceType last() const { return last_; }
1525
1526 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")
1527
1528 protected:
1529 // TODO(ager): It could be nice to allow the ommision of instance
1530 // type checks if we have already performed an instance type check
1531 // with a larger range.
1532 virtual bool DataEquals(HValue* other) const {
1533 HCheckInstanceType* b = HCheckInstanceType::cast(other);
1534 return (first_ == b->first()) && (last_ == b->last());
1535 }
1536
1537 private:
1538 InstanceType first_;
1539 InstanceType last_;
1540};
1541
1542
1543class HCheckNonSmi: public HUnaryOperation {
1544 public:
1545 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
1546 set_representation(Representation::Tagged());
1547 SetFlag(kUseGVN);
1548 }
1549
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001550 virtual bool IsCheckInstruction() const { return true; }
1551
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001552 virtual Representation RequiredInputRepresentation(int index) const {
1553 return Representation::Tagged();
1554 }
1555
1556 virtual HType CalculateInferredType() const;
1557
1558#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001559 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001560#endif
1561
1562 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001563
1564 protected:
1565 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001566};
1567
1568
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001569class HCheckPrototypeMaps: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001570 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001571 HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
1572 : prototype_(prototype), holder_(holder) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001573 SetFlag(kUseGVN);
1574 SetFlag(kDependsOnMaps);
1575 }
1576
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001577 virtual bool IsCheckInstruction() const { return true; }
1578
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001579#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001580 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001581#endif
1582
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001583 Handle<JSObject> prototype() const { return prototype_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001584 Handle<JSObject> holder() const { return holder_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001585
1586 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
1587
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001588 virtual intptr_t Hashcode() const {
1589 ASSERT(!Heap::IsAllocationAllowed());
1590 intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
1591 hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
1592 return hash;
1593 }
1594
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001595 protected:
1596 virtual bool DataEquals(HValue* other) const {
1597 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001598 return prototype_.is_identical_to(b->prototype()) &&
1599 holder_.is_identical_to(b->holder());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001600 }
1601
1602 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001603 Handle<JSObject> prototype_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001604 Handle<JSObject> holder_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001605};
1606
1607
1608class HCheckSmi: public HUnaryOperation {
1609 public:
1610 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
1611 set_representation(Representation::Tagged());
1612 SetFlag(kUseGVN);
1613 }
1614
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001615 virtual bool IsCheckInstruction() const { return true; }
1616
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001617 virtual Representation RequiredInputRepresentation(int index) const {
1618 return Representation::Tagged();
1619 }
1620 virtual HType CalculateInferredType() const;
1621
1622#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001623 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001624#endif
1625
1626 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001627
1628 protected:
1629 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001630};
1631
1632
1633class HPhi: public HValue {
1634 public:
1635 explicit HPhi(int merged_index)
1636 : inputs_(2),
1637 merged_index_(merged_index),
1638 phi_id_(-1) {
1639 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1640 non_phi_uses_[i] = 0;
1641 indirect_uses_[i] = 0;
1642 }
1643 ASSERT(merged_index >= 0);
1644 set_representation(Representation::Tagged());
1645 SetFlag(kFlexibleRepresentation);
1646 }
1647
1648 virtual Representation InferredRepresentation() const {
1649 bool double_occurred = false;
1650 bool int32_occurred = false;
1651 for (int i = 0; i < OperandCount(); ++i) {
1652 HValue* value = OperandAt(i);
1653 if (value->representation().IsDouble()) double_occurred = true;
1654 if (value->representation().IsInteger32()) int32_occurred = true;
1655 if (value->representation().IsTagged()) return Representation::Tagged();
1656 }
1657
1658 if (double_occurred) return Representation::Double();
1659 if (int32_occurred) return Representation::Integer32();
1660 return Representation::None();
1661 }
1662
1663 virtual Range* InferRange();
1664 virtual Representation RequiredInputRepresentation(int index) const {
1665 return representation();
1666 }
1667 virtual HType CalculateInferredType() const;
1668 virtual int OperandCount() const { return inputs_.length(); }
1669 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
1670 HValue* GetRedundantReplacement() const;
1671 void AddInput(HValue* value);
1672
1673 bool HasReceiverOperand();
1674
1675 int merged_index() const { return merged_index_; }
1676
1677 virtual const char* Mnemonic() const { return "phi"; }
1678
1679 virtual void PrintTo(StringStream* stream) const;
1680
1681#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001682 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001683#endif
1684
1685 DECLARE_INSTRUCTION(Phi)
1686
1687 void InitRealUses(int id);
1688 void AddNonPhiUsesFrom(HPhi* other);
1689 void AddIndirectUsesTo(int* use_count);
1690
1691 int tagged_non_phi_uses() const {
1692 return non_phi_uses_[Representation::kTagged];
1693 }
1694 int int32_non_phi_uses() const {
1695 return non_phi_uses_[Representation::kInteger32];
1696 }
1697 int double_non_phi_uses() const {
1698 return non_phi_uses_[Representation::kDouble];
1699 }
1700 int tagged_indirect_uses() const {
1701 return indirect_uses_[Representation::kTagged];
1702 }
1703 int int32_indirect_uses() const {
1704 return indirect_uses_[Representation::kInteger32];
1705 }
1706 int double_indirect_uses() const {
1707 return indirect_uses_[Representation::kDouble];
1708 }
1709 int phi_id() { return phi_id_; }
1710
1711 protected:
1712 virtual void DeleteFromGraph();
1713 virtual void InternalSetOperandAt(int index, HValue* value) {
1714 inputs_[index] = value;
1715 }
1716
1717 private:
1718 ZoneList<HValue*> inputs_;
1719 int merged_index_;
1720
1721 int non_phi_uses_[Representation::kNumRepresentations];
1722 int indirect_uses_[Representation::kNumRepresentations];
1723 int phi_id_;
1724};
1725
1726
1727class HArgumentsObject: public HInstruction {
1728 public:
1729 HArgumentsObject() {
1730 set_representation(Representation::Tagged());
1731 SetFlag(kIsArguments);
1732 }
1733
1734 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
1735};
1736
1737
1738class HConstant: public HInstruction {
1739 public:
1740 HConstant(Handle<Object> handle, Representation r);
1741
1742 Handle<Object> handle() const { return handle_; }
1743
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001744 bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
1745
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001746 virtual bool EmitAtUses() const { return !representation().IsDouble(); }
1747 virtual void PrintDataTo(StringStream* stream) const;
1748 virtual HType CalculateInferredType() const;
1749 bool IsInteger() const { return handle_->IsSmi(); }
1750 HConstant* CopyToRepresentation(Representation r) const;
1751 HConstant* CopyToTruncatedInt32() const;
1752 bool HasInteger32Value() const { return has_int32_value_; }
1753 int32_t Integer32Value() const {
1754 ASSERT(HasInteger32Value());
1755 return int32_value_;
1756 }
1757 bool HasDoubleValue() const { return has_double_value_; }
1758 double DoubleValue() const {
1759 ASSERT(HasDoubleValue());
1760 return double_value_;
1761 }
1762 bool HasStringValue() const { return handle_->IsString(); }
1763
1764 virtual intptr_t Hashcode() const {
1765 ASSERT(!Heap::allow_allocation(false));
1766 return reinterpret_cast<intptr_t>(*handle());
1767 }
1768
1769#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001770 virtual void Verify() { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001771#endif
1772
1773 DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
1774
1775 protected:
1776 virtual Range* InferRange();
1777
1778 virtual bool DataEquals(HValue* other) const {
1779 HConstant* other_constant = HConstant::cast(other);
1780 return handle().is_identical_to(other_constant->handle());
1781 }
1782
1783 private:
1784 Handle<Object> handle_;
1785 HType constant_type_;
1786
1787 // The following two values represent the int32 and the double value of the
1788 // given constant if there is a lossless conversion between the constant
1789 // and the specific representation.
1790 bool has_int32_value_;
1791 int32_t int32_value_;
1792 bool has_double_value_;
1793 double double_value_;
1794};
1795
1796
1797class HBinaryOperation: public HInstruction {
1798 public:
1799 HBinaryOperation(HValue* left, HValue* right) {
1800 ASSERT(left != NULL && right != NULL);
1801 SetOperandAt(0, left);
1802 SetOperandAt(1, right);
1803 }
1804
1805 HValue* left() const { return OperandAt(0); }
1806 HValue* right() const { return OperandAt(1); }
1807
1808 // TODO(kasperl): Move these helpers to the IA-32 Lithium
1809 // instruction sequence builder.
1810 HValue* LeastConstantOperand() const {
1811 if (IsCommutative() && left()->IsConstant()) return right();
1812 return left();
1813 }
1814 HValue* MostConstantOperand() const {
1815 if (IsCommutative() && left()->IsConstant()) return left();
1816 return right();
1817 }
1818
1819 virtual bool IsCommutative() const { return false; }
1820
1821 virtual void PrintDataTo(StringStream* stream) const;
1822 virtual int OperandCount() const { return operands_.length(); }
1823 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1824
1825 DECLARE_INSTRUCTION(BinaryOperation)
1826
1827 protected:
1828 virtual void InternalSetOperandAt(int index, HValue* value) {
1829 operands_[index] = value;
1830 }
1831
1832 private:
1833 HOperandVector<2> operands_;
1834};
1835
1836
1837class HApplyArguments: public HInstruction {
1838 public:
1839 HApplyArguments(HValue* function,
1840 HValue* receiver,
1841 HValue* length,
1842 HValue* elements) {
1843 set_representation(Representation::Tagged());
1844 SetOperandAt(0, function);
1845 SetOperandAt(1, receiver);
1846 SetOperandAt(2, length);
1847 SetOperandAt(3, elements);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001848 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001849 }
1850
1851 virtual Representation RequiredInputRepresentation(int index) const {
1852 // The length is untagged, all other inputs are tagged.
1853 return (index == 2)
1854 ? Representation::Integer32()
1855 : Representation::Tagged();
1856 }
1857
1858 HValue* function() const { return OperandAt(0); }
1859 HValue* receiver() const { return OperandAt(1); }
1860 HValue* length() const { return OperandAt(2); }
1861 HValue* elements() const { return OperandAt(3); }
1862
1863 virtual int OperandCount() const { return operands_.length(); }
1864 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1865
1866 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
1867
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001868 protected:
1869 virtual void InternalSetOperandAt(int index, HValue* value) {
1870 operands_[index] = value;
1871 }
1872
1873 private:
1874 HOperandVector<4> operands_;
1875};
1876
1877
1878class HArgumentsElements: public HInstruction {
1879 public:
1880 HArgumentsElements() {
1881 // The value produced by this instruction is a pointer into the stack
1882 // that looks as if it was a smi because of alignment.
1883 set_representation(Representation::Tagged());
1884 SetFlag(kUseGVN);
1885 }
1886
1887 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001888
1889 protected:
1890 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001891};
1892
1893
1894class HArgumentsLength: public HUnaryOperation {
1895 public:
1896 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
1897 set_representation(Representation::Integer32());
1898 SetFlag(kUseGVN);
1899 }
1900
1901 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001902
1903 protected:
1904 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001905};
1906
1907
1908class HAccessArgumentsAt: public HInstruction {
1909 public:
1910 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
1911 set_representation(Representation::Tagged());
1912 SetFlag(kUseGVN);
1913 SetOperandAt(0, arguments);
1914 SetOperandAt(1, length);
1915 SetOperandAt(2, index);
1916 }
1917
1918 virtual void PrintDataTo(StringStream* stream) const;
1919
1920 virtual Representation RequiredInputRepresentation(int index) const {
1921 // The arguments elements is considered tagged.
1922 return index == 0
1923 ? Representation::Tagged()
1924 : Representation::Integer32();
1925 }
1926
1927 HValue* arguments() const { return operands_[0]; }
1928 HValue* length() const { return operands_[1]; }
1929 HValue* index() const { return operands_[2]; }
1930
1931 virtual int OperandCount() const { return operands_.length(); }
1932 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1933
1934 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
1935
1936 protected:
1937 virtual void InternalSetOperandAt(int index, HValue* value) {
1938 operands_[index] = value;
1939 }
1940
ager@chromium.org378b34e2011-01-28 08:04:38 +00001941 virtual bool DataEquals(HValue* other) const { return true; }
1942
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001943 private:
1944 HOperandVector<3> operands_;
1945};
1946
1947
1948class HBoundsCheck: public HBinaryOperation {
1949 public:
1950 HBoundsCheck(HValue* index, HValue* length)
1951 : HBinaryOperation(index, length) {
1952 SetFlag(kUseGVN);
1953 }
1954
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001955 virtual bool IsCheckInstruction() const { return true; }
1956
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001957 virtual Representation RequiredInputRepresentation(int index) const {
1958 return Representation::Integer32();
1959 }
1960
1961#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001962 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001963#endif
1964
1965 HValue* index() const { return left(); }
1966 HValue* length() const { return right(); }
1967
1968 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001969
1970 protected:
1971 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001972};
1973
1974
1975class HBitwiseBinaryOperation: public HBinaryOperation {
1976 public:
1977 HBitwiseBinaryOperation(HValue* left, HValue* right)
1978 : HBinaryOperation(left, right) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001979 set_representation(Representation::Tagged());
1980 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00001981 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001982 }
1983
1984 virtual Representation RequiredInputRepresentation(int index) const {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001985 return representation();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001986 }
1987
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001988 virtual void RepresentationChanged(Representation to) {
1989 if (!to.IsTagged()) {
1990 ASSERT(to.IsInteger32());
ager@chromium.org378b34e2011-01-28 08:04:38 +00001991 ClearAllSideEffects();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001992 SetFlag(kTruncatingToInt32);
1993 SetFlag(kUseGVN);
1994 }
1995 }
1996
1997 HType CalculateInferredType() const;
1998
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001999 DECLARE_INSTRUCTION(BitwiseBinaryOperation)
2000};
2001
2002
2003class HArithmeticBinaryOperation: public HBinaryOperation {
2004 public:
2005 HArithmeticBinaryOperation(HValue* left, HValue* right)
2006 : HBinaryOperation(left, right) {
2007 set_representation(Representation::Tagged());
2008 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002009 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002010 }
2011
2012 virtual void RepresentationChanged(Representation to) {
2013 if (!to.IsTagged()) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002014 ClearAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002015 SetFlag(kUseGVN);
2016 }
2017 }
2018
2019 virtual HType CalculateInferredType() const;
2020 virtual Representation RequiredInputRepresentation(int index) const {
2021 return representation();
2022 }
2023 virtual Representation InferredRepresentation() const {
2024 if (left()->representation().Equals(right()->representation())) {
2025 return left()->representation();
2026 }
2027 return HValue::InferredRepresentation();
2028 }
2029
2030 DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
2031};
2032
2033
2034class HCompare: public HBinaryOperation {
2035 public:
2036 HCompare(HValue* left, HValue* right, Token::Value token)
2037 : HBinaryOperation(left, right), token_(token) {
2038 ASSERT(Token::IsCompareOp(token));
2039 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002040 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002041 }
2042
2043 void SetInputRepresentation(Representation r);
2044 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2045 virtual Representation RequiredInputRepresentation(int index) const {
2046 return input_representation_;
2047 }
2048 Representation GetInputRepresentation() const {
2049 return input_representation_;
2050 }
2051 Token::Value token() const { return token_; }
2052 virtual void PrintDataTo(StringStream* stream) const;
2053
2054 virtual HType CalculateInferredType() const;
2055
2056 virtual intptr_t Hashcode() const {
2057 return HValue::Hashcode() * 7 + token_;
2058 }
2059
2060 DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
2061
2062 protected:
2063 virtual bool DataEquals(HValue* other) const {
2064 HCompare* comp = HCompare::cast(other);
2065 return token_ == comp->token();
2066 }
2067
2068 private:
2069 Representation input_representation_;
2070 Token::Value token_;
2071};
2072
2073
2074class HCompareJSObjectEq: public HBinaryOperation {
2075 public:
2076 HCompareJSObjectEq(HValue* left, HValue* right)
2077 : HBinaryOperation(left, right) {
2078 set_representation(Representation::Tagged());
2079 SetFlag(kUseGVN);
2080 }
2081
2082 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2083 virtual Representation RequiredInputRepresentation(int index) const {
2084 return Representation::Tagged();
2085 }
2086 virtual HType CalculateInferredType() const;
2087
2088 DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002089
2090 protected:
2091 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002092};
2093
2094
2095class HUnaryPredicate: public HUnaryOperation {
2096 public:
2097 explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
2098 set_representation(Representation::Tagged());
2099 SetFlag(kUseGVN);
2100 }
2101 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2102 virtual Representation RequiredInputRepresentation(int index) const {
2103 return Representation::Tagged();
2104 }
2105 virtual HType CalculateInferredType() const;
2106};
2107
2108
2109class HIsNull: public HUnaryPredicate {
2110 public:
2111 HIsNull(HValue* value, bool is_strict)
2112 : HUnaryPredicate(value), is_strict_(is_strict) { }
2113
2114 bool is_strict() const { return is_strict_; }
2115
2116 DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
2117
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002118 protected:
2119 virtual bool DataEquals(HValue* other) const {
2120 HIsNull* b = HIsNull::cast(other);
2121 return is_strict_ == b->is_strict();
2122 }
2123
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002124 private:
2125 bool is_strict_;
2126};
2127
2128
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002129class HIsObject: public HUnaryPredicate {
2130 public:
2131 explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }
2132
2133 DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002134
2135 protected:
2136 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002137};
2138
2139
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002140class HIsSmi: public HUnaryPredicate {
2141 public:
2142 explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
2143
2144 DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002145
2146 protected:
2147 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002148};
2149
2150
2151class HHasInstanceType: public HUnaryPredicate {
2152 public:
2153 HHasInstanceType(HValue* value, InstanceType type)
2154 : HUnaryPredicate(value), from_(type), to_(type) { }
2155 HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
2156 : HUnaryPredicate(value), from_(from), to_(to) {
2157 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
2158 }
2159
2160 InstanceType from() { return from_; }
2161 InstanceType to() { return to_; }
2162
2163 virtual void PrintDataTo(StringStream* stream) const;
2164
2165 DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
2166
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002167 protected:
2168 virtual bool DataEquals(HValue* other) const {
2169 HHasInstanceType* b = HHasInstanceType::cast(other);
2170 return (from_ == b->from()) && (to_ == b->to());
2171 }
2172
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002173 private:
2174 InstanceType from_;
2175 InstanceType to_; // Inclusive range, not all combinations work.
2176};
2177
2178
2179class HHasCachedArrayIndex: public HUnaryPredicate {
2180 public:
2181 explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
2182
2183 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002184
2185 protected:
2186 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002187};
2188
2189
2190class HClassOfTest: public HUnaryPredicate {
2191 public:
2192 HClassOfTest(HValue* value, Handle<String> class_name)
2193 : HUnaryPredicate(value), class_name_(class_name) { }
2194
2195 DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
2196
2197 virtual void PrintDataTo(StringStream* stream) const;
2198
2199 Handle<String> class_name() const { return class_name_; }
2200
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002201 protected:
2202 virtual bool DataEquals(HValue* other) const {
2203 HClassOfTest* b = HClassOfTest::cast(other);
2204 return class_name_.is_identical_to(b->class_name_);
2205 }
2206
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002207 private:
2208 Handle<String> class_name_;
2209};
2210
2211
2212class HTypeofIs: public HUnaryPredicate {
2213 public:
2214 HTypeofIs(HValue* value, Handle<String> type_literal)
2215 : HUnaryPredicate(value), type_literal_(type_literal) { }
2216
2217 Handle<String> type_literal() { return type_literal_; }
2218 virtual void PrintDataTo(StringStream* stream) const;
2219
2220 DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
2221
2222 protected:
2223 virtual bool DataEquals(HValue* other) const {
2224 HTypeofIs* b = HTypeofIs::cast(other);
2225 return type_literal_.is_identical_to(b->type_literal_);
2226 }
2227
2228 private:
2229 Handle<String> type_literal_;
2230};
2231
2232
2233class HInstanceOf: public HBinaryOperation {
2234 public:
2235 HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
2236 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002237 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002238 }
2239
2240 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2241
2242 virtual Representation RequiredInputRepresentation(int index) const {
2243 return Representation::Tagged();
2244 }
2245
2246 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
2247};
2248
2249
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002250class HInstanceOfKnownGlobal: public HUnaryOperation {
2251 public:
2252 HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right)
2253 : HUnaryOperation(left), function_(right) {
2254 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002255 SetAllSideEffects();
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002256 }
2257
2258 Handle<JSFunction> function() { return function_; }
2259
2260 virtual Representation RequiredInputRepresentation(int index) const {
2261 return Representation::Tagged();
2262 }
2263
2264 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
2265 "instance_of_known_global")
2266
2267 private:
2268 Handle<JSFunction> function_;
2269};
2270
2271
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002272class HPower: public HBinaryOperation {
2273 public:
2274 HPower(HValue* left, HValue* right)
2275 : HBinaryOperation(left, right) {
2276 set_representation(Representation::Double());
2277 SetFlag(kUseGVN);
2278 }
2279
2280 virtual Representation RequiredInputRepresentation(int index) const {
2281 return (index == 1) ? Representation::None() : Representation::Double();
2282 }
2283
2284 DECLARE_CONCRETE_INSTRUCTION(Power, "power")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002285
2286 protected:
2287 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002288};
2289
2290
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002291class HAdd: public HArithmeticBinaryOperation {
2292 public:
2293 HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2294 SetFlag(kCanOverflow);
2295 }
2296
2297 // Add is only commutative if two integer values are added and not if two
2298 // tagged values are added (because it might be a String concatenation).
2299 virtual bool IsCommutative() const {
2300 return !representation().IsTagged();
2301 }
2302
2303 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2304
2305 virtual HType CalculateInferredType() const;
2306
2307 DECLARE_CONCRETE_INSTRUCTION(Add, "add")
2308
2309 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002310 virtual bool DataEquals(HValue* other) const { return true; }
2311
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002312 virtual Range* InferRange();
2313};
2314
2315
2316class HSub: public HArithmeticBinaryOperation {
2317 public:
2318 HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2319 SetFlag(kCanOverflow);
2320 }
2321
2322 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2323
2324 DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
2325
2326 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002327 virtual bool DataEquals(HValue* other) const { return true; }
2328
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002329 virtual Range* InferRange();
2330};
2331
2332
2333class HMul: public HArithmeticBinaryOperation {
2334 public:
2335 HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2336 SetFlag(kCanOverflow);
2337 }
2338
2339 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2340
2341 // Only commutative if it is certain that not two objects are multiplicated.
2342 virtual bool IsCommutative() const {
2343 return !representation().IsTagged();
2344 }
2345
2346 DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
2347
2348 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002349 virtual bool DataEquals(HValue* other) const { return true; }
2350
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002351 virtual Range* InferRange();
2352};
2353
2354
2355class HMod: public HArithmeticBinaryOperation {
2356 public:
2357 HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2358 SetFlag(kCanBeDivByZero);
2359 }
2360
2361 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2362
2363 DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
2364
2365 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002366 virtual bool DataEquals(HValue* other) const { return true; }
2367
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002368 virtual Range* InferRange();
2369};
2370
2371
2372class HDiv: public HArithmeticBinaryOperation {
2373 public:
2374 HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2375 SetFlag(kCanBeDivByZero);
2376 SetFlag(kCanOverflow);
2377 }
2378
2379 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2380
2381 DECLARE_CONCRETE_INSTRUCTION(Div, "div")
2382
2383 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002384 virtual bool DataEquals(HValue* other) const { return true; }
2385
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002386 virtual Range* InferRange();
2387};
2388
2389
2390class HBitAnd: public HBitwiseBinaryOperation {
2391 public:
2392 HBitAnd(HValue* left, HValue* right)
2393 : HBitwiseBinaryOperation(left, right) { }
2394
2395 virtual bool IsCommutative() const { return true; }
2396 virtual HType CalculateInferredType() const;
2397
2398 DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
2399
2400 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002401 virtual bool DataEquals(HValue* other) const { return true; }
2402
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002403 virtual Range* InferRange();
2404};
2405
2406
2407class HBitXor: public HBitwiseBinaryOperation {
2408 public:
2409 HBitXor(HValue* left, HValue* right)
2410 : HBitwiseBinaryOperation(left, right) { }
2411
2412 virtual bool IsCommutative() const { return true; }
2413 virtual HType CalculateInferredType() const;
2414
2415 DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002416
2417 protected:
2418 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002419};
2420
2421
2422class HBitOr: public HBitwiseBinaryOperation {
2423 public:
2424 HBitOr(HValue* left, HValue* right)
2425 : HBitwiseBinaryOperation(left, right) { }
2426
2427 virtual bool IsCommutative() const { return true; }
2428 virtual HType CalculateInferredType() const;
2429
2430 DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
2431
2432 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002433 virtual bool DataEquals(HValue* other) const { return true; }
2434
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002435 virtual Range* InferRange();
2436};
2437
2438
2439class HShl: public HBitwiseBinaryOperation {
2440 public:
2441 HShl(HValue* left, HValue* right)
2442 : HBitwiseBinaryOperation(left, right) { }
2443
2444 virtual Range* InferRange();
2445 virtual HType CalculateInferredType() const;
2446
2447 DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002448
2449 protected:
2450 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002451};
2452
2453
2454class HShr: public HBitwiseBinaryOperation {
2455 public:
2456 HShr(HValue* left, HValue* right)
2457 : HBitwiseBinaryOperation(left, right) { }
2458
2459 virtual HType CalculateInferredType() const;
2460
2461 DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002462
2463 protected:
2464 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002465};
2466
2467
2468class HSar: public HBitwiseBinaryOperation {
2469 public:
2470 HSar(HValue* left, HValue* right)
2471 : HBitwiseBinaryOperation(left, right) { }
2472
2473 virtual Range* InferRange();
2474 virtual HType CalculateInferredType() const;
2475
2476 DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002477
2478 protected:
2479 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002480};
2481
2482
2483class HOsrEntry: public HInstruction {
2484 public:
2485 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
2486 SetFlag(kChangesOsrEntries);
2487 }
2488
2489 int ast_id() const { return ast_id_; }
2490
2491 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
2492
2493 private:
2494 int ast_id_;
2495};
2496
2497
2498class HParameter: public HInstruction {
2499 public:
2500 explicit HParameter(unsigned index) : index_(index) {
2501 set_representation(Representation::Tagged());
2502 }
2503
2504 unsigned index() const { return index_; }
2505
2506 virtual void PrintDataTo(StringStream* stream) const;
2507
2508 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2509
2510 private:
2511 unsigned index_;
2512};
2513
2514
2515class HCallStub: public HInstruction {
2516 public:
2517 HCallStub(CodeStub::Major major_key, int argument_count)
2518 : major_key_(major_key),
2519 argument_count_(argument_count),
2520 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
2521 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002522 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002523 }
2524
2525 CodeStub::Major major_key() { return major_key_; }
2526 int argument_count() { return argument_count_; }
2527
2528 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
2529 transcendental_type_ = transcendental_type;
2530 }
2531 TranscendentalCache::Type transcendental_type() {
2532 return transcendental_type_;
2533 }
2534 virtual void PrintDataTo(StringStream* stream) const;
2535
2536 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
2537
2538 private:
2539 CodeStub::Major major_key_;
2540 int argument_count_;
2541 TranscendentalCache::Type transcendental_type_;
2542};
2543
2544
2545class HUnknownOSRValue: public HInstruction {
2546 public:
2547 HUnknownOSRValue() { set_representation(Representation::Tagged()); }
2548
2549 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
2550};
2551
2552
2553class HLoadGlobal: public HInstruction {
2554 public:
2555 HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
2556 : cell_(cell), check_hole_value_(check_hole_value) {
2557 set_representation(Representation::Tagged());
2558 SetFlag(kUseGVN);
2559 SetFlag(kDependsOnGlobalVars);
2560 }
2561
2562 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2563 bool check_hole_value() const { return check_hole_value_; }
2564
2565 virtual Representation RequiredInputRepresentation(int index) const {
2566 return Representation::Tagged();
2567 }
2568 virtual void PrintDataTo(StringStream* stream) const;
2569
2570 virtual intptr_t Hashcode() const {
2571 ASSERT(!Heap::allow_allocation(false));
2572 return reinterpret_cast<intptr_t>(*cell_);
2573 }
2574
2575 DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
2576
2577 protected:
2578 virtual bool DataEquals(HValue* other) const {
2579 HLoadGlobal* b = HLoadGlobal::cast(other);
2580 return cell_.is_identical_to(b->cell());
2581 }
2582
2583 private:
2584 Handle<JSGlobalPropertyCell> cell_;
2585 bool check_hole_value_;
2586};
2587
2588
2589class HStoreGlobal: public HUnaryOperation {
2590 public:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002591 HStoreGlobal(HValue* value,
2592 Handle<JSGlobalPropertyCell> cell,
2593 bool check_hole_value)
2594 : HUnaryOperation(value),
2595 cell_(cell),
2596 check_hole_value_(check_hole_value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002597 SetFlag(kChangesGlobalVars);
2598 }
2599
2600 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002601 bool check_hole_value() const { return check_hole_value_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002602
2603 virtual Representation RequiredInputRepresentation(int index) const {
2604 return Representation::Tagged();
2605 }
2606 virtual void PrintDataTo(StringStream* stream) const;
2607
2608 DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
2609
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002610 private:
2611 Handle<JSGlobalPropertyCell> cell_;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002612 bool check_hole_value_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002613};
2614
2615
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002616class HLoadContextSlot: public HInstruction {
2617 public:
2618 HLoadContextSlot(int context_chain_length , int slot_index)
2619 : context_chain_length_(context_chain_length), slot_index_(slot_index) {
2620 set_representation(Representation::Tagged());
2621 SetFlag(kUseGVN);
2622 SetFlag(kDependsOnCalls);
2623 }
2624
2625 int context_chain_length() const { return context_chain_length_; }
2626 int slot_index() const { return slot_index_; }
2627
2628 virtual void PrintDataTo(StringStream* stream) const;
2629
2630 virtual intptr_t Hashcode() const {
2631 return context_chain_length() * 29 + slot_index();
2632 }
2633
2634 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
2635
2636 protected:
2637 virtual bool DataEquals(HValue* other) const {
2638 HLoadContextSlot* b = HLoadContextSlot::cast(other);
2639 return (context_chain_length() == b->context_chain_length())
2640 && (slot_index() == b->slot_index());
2641 }
2642
2643 private:
2644 int context_chain_length_;
2645 int slot_index_;
2646};
2647
2648
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002649class HLoadNamedField: public HUnaryOperation {
2650 public:
2651 HLoadNamedField(HValue* object, bool is_in_object, int offset)
2652 : HUnaryOperation(object),
2653 is_in_object_(is_in_object),
2654 offset_(offset) {
2655 set_representation(Representation::Tagged());
2656 SetFlag(kUseGVN);
2657 if (is_in_object) {
2658 SetFlag(kDependsOnInobjectFields);
2659 } else {
2660 SetFlag(kDependsOnBackingStoreFields);
2661 }
2662 }
2663
2664 HValue* object() const { return OperandAt(0); }
2665 bool is_in_object() const { return is_in_object_; }
2666 int offset() const { return offset_; }
2667
2668 virtual Representation RequiredInputRepresentation(int index) const {
2669 return Representation::Tagged();
2670 }
2671 virtual void PrintDataTo(StringStream* stream) const;
2672
2673 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
2674
2675 protected:
2676 virtual bool DataEquals(HValue* other) const {
2677 HLoadNamedField* b = HLoadNamedField::cast(other);
2678 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
2679 }
2680
2681 private:
2682 bool is_in_object_;
2683 int offset_;
2684};
2685
2686
2687class HLoadNamedGeneric: public HUnaryOperation {
2688 public:
2689 HLoadNamedGeneric(HValue* object, Handle<Object> name)
2690 : HUnaryOperation(object), name_(name) {
2691 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002692 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002693 }
2694
2695 HValue* object() const { return OperandAt(0); }
2696 Handle<Object> name() const { return name_; }
2697
2698 virtual Representation RequiredInputRepresentation(int index) const {
2699 return Representation::Tagged();
2700 }
2701
2702 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
2703
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002704 private:
2705 Handle<Object> name_;
2706};
2707
2708
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002709class HLoadFunctionPrototype: public HUnaryOperation {
2710 public:
2711 explicit HLoadFunctionPrototype(HValue* function)
2712 : HUnaryOperation(function) {
2713 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002714 SetFlag(kUseGVN);
2715 SetFlag(kDependsOnCalls);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002716 }
2717
2718 HValue* function() const { return OperandAt(0); }
2719
2720 virtual Representation RequiredInputRepresentation(int index) const {
2721 return Representation::Tagged();
2722 }
2723
2724 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
2725
2726 protected:
2727 virtual bool DataEquals(HValue* other) const { return true; }
2728};
2729
2730
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002731class HLoadKeyed: public HBinaryOperation {
2732 public:
2733 HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
2734 set_representation(Representation::Tagged());
2735 }
2736
2737 virtual void PrintDataTo(StringStream* stream) const;
2738
2739 virtual Representation RequiredInputRepresentation(int index) const {
2740 return Representation::Tagged();
2741 }
2742 HValue* object() const { return OperandAt(0); }
2743 HValue* key() const { return OperandAt(1); }
2744
2745 DECLARE_INSTRUCTION(LoadKeyed)
2746};
2747
2748
2749class HLoadKeyedFastElement: public HLoadKeyed {
2750 public:
2751 HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2752 SetFlag(kDependsOnArrayElements);
2753 SetFlag(kUseGVN);
2754 }
2755
2756 virtual Representation RequiredInputRepresentation(int index) const {
2757 // The key is supposed to be Integer32.
2758 return (index == 1) ? Representation::Integer32()
2759 : Representation::Tagged();
2760 }
2761
2762 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
2763 "load_keyed_fast_element")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002764
2765 protected:
2766 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002767};
2768
2769
2770class HLoadKeyedGeneric: public HLoadKeyed {
2771 public:
2772 HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002773 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002774 }
2775
2776 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
2777};
2778
2779
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002780static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
2781 return !value->type().IsSmi() &&
2782 !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
2783}
2784
2785
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002786class HStoreNamed: public HBinaryOperation {
2787 public:
2788 HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
2789 : HBinaryOperation(obj, val), name_(name) {
2790 }
2791
2792 virtual Representation RequiredInputRepresentation(int index) const {
2793 return Representation::Tagged();
2794 }
2795
2796 virtual void PrintDataTo(StringStream* stream) const;
2797
2798 HValue* object() const { return OperandAt(0); }
2799 Handle<Object> name() const { return name_; }
2800 HValue* value() const { return OperandAt(1); }
2801 void set_value(HValue* value) { SetOperandAt(1, value); }
2802
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002803 bool NeedsWriteBarrier() const {
2804 return StoringValueNeedsWriteBarrier(value());
2805 }
2806
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002807 DECLARE_INSTRUCTION(StoreNamed)
2808
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002809 private:
2810 Handle<Object> name_;
2811};
2812
2813
2814class HStoreNamedField: public HStoreNamed {
2815 public:
2816 HStoreNamedField(HValue* obj,
2817 Handle<Object> name,
2818 HValue* val,
2819 bool in_object,
2820 int offset)
2821 : HStoreNamed(obj, name, val),
2822 is_in_object_(in_object),
2823 offset_(offset) {
2824 if (is_in_object_) {
2825 SetFlag(kChangesInobjectFields);
2826 } else {
2827 SetFlag(kChangesBackingStoreFields);
2828 }
2829 }
2830
2831 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
2832
2833 virtual Representation RequiredInputRepresentation(int index) const {
2834 return Representation::Tagged();
2835 }
2836 virtual void PrintDataTo(StringStream* stream) const;
2837
2838 bool is_in_object() const { return is_in_object_; }
2839 int offset() const { return offset_; }
2840 Handle<Map> transition() const { return transition_; }
2841 void set_transition(Handle<Map> map) { transition_ = map; }
2842
2843 private:
2844 bool is_in_object_;
2845 int offset_;
2846 Handle<Map> transition_;
2847};
2848
2849
2850class HStoreNamedGeneric: public HStoreNamed {
2851 public:
2852 HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
2853 : HStoreNamed(obj, name, val) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002854 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002855 }
2856
2857 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
2858};
2859
2860
2861class HStoreKeyed: public HInstruction {
2862 public:
2863 HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
2864 SetOperandAt(0, obj);
2865 SetOperandAt(1, key);
2866 SetOperandAt(2, val);
2867 }
2868
2869 virtual void PrintDataTo(StringStream* stream) const;
2870 virtual int OperandCount() const { return operands_.length(); }
2871 virtual HValue* OperandAt(int index) const { return operands_[index]; }
2872
2873 virtual Representation RequiredInputRepresentation(int index) const {
2874 return Representation::Tagged();
2875 }
2876
2877 HValue* object() const { return OperandAt(0); }
2878 HValue* key() const { return OperandAt(1); }
2879 HValue* value() const { return OperandAt(2); }
2880
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002881 bool NeedsWriteBarrier() const {
2882 return StoringValueNeedsWriteBarrier(value());
2883 }
2884
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002885 DECLARE_INSTRUCTION(StoreKeyed)
2886
2887 protected:
2888 virtual void InternalSetOperandAt(int index, HValue* value) {
2889 operands_[index] = value;
2890 }
2891
2892 private:
2893 HOperandVector<3> operands_;
2894};
2895
2896
2897class HStoreKeyedFastElement: public HStoreKeyed {
2898 public:
2899 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
2900 : HStoreKeyed(obj, key, val) {
2901 SetFlag(kChangesArrayElements);
2902 }
2903
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002904 virtual Representation RequiredInputRepresentation(int index) const {
2905 // The key is supposed to be Integer32.
2906 return (index == 1) ? Representation::Integer32()
2907 : Representation::Tagged();
2908 }
2909
2910 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
2911 "store_keyed_fast_element")
2912};
2913
2914
2915class HStoreKeyedGeneric: public HStoreKeyed {
2916 public:
2917 HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
2918 : HStoreKeyed(obj, key, val) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002919 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002920 }
2921
2922 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
2923};
2924
2925
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002926class HStringCharCodeAt: public HBinaryOperation {
2927 public:
2928 HStringCharCodeAt(HValue* string, HValue* index)
2929 : HBinaryOperation(string, index) {
2930 set_representation(Representation::Integer32());
2931 SetFlag(kUseGVN);
2932 }
2933
2934 virtual Representation RequiredInputRepresentation(int index) const {
2935 // The index is supposed to be Integer32.
2936 return (index == 1) ? Representation::Integer32()
2937 : Representation::Tagged();
2938 }
2939
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002940 HValue* string() const { return OperandAt(0); }
2941 HValue* index() const { return OperandAt(1); }
2942
2943 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string_char_code_at")
2944
2945 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002946 virtual bool DataEquals(HValue* other) const { return true; }
2947
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002948 virtual Range* InferRange() {
2949 return new Range(0, String::kMaxUC16CharCode);
2950 }
2951};
2952
2953
2954class HStringLength: public HUnaryOperation {
2955 public:
2956 explicit HStringLength(HValue* string) : HUnaryOperation(string) {
2957 set_representation(Representation::Tagged());
2958 SetFlag(kUseGVN);
2959 }
2960
2961 virtual Representation RequiredInputRepresentation(int index) const {
2962 return Representation::Tagged();
2963 }
2964
2965 virtual HType CalculateInferredType() const {
2966 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
2967 return HType::Smi();
2968 }
2969
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002970 DECLARE_CONCRETE_INSTRUCTION(StringLength, "string_length")
2971
2972 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002973 virtual bool DataEquals(HValue* other) const { return true; }
2974
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002975 virtual Range* InferRange() {
2976 return new Range(0, String::kMaxLength);
2977 }
2978};
2979
2980
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002981class HMaterializedLiteral: public HInstruction {
2982 public:
2983 HMaterializedLiteral(int index, int depth)
2984 : literal_index_(index), depth_(depth) {
2985 set_representation(Representation::Tagged());
2986 }
2987
2988 int literal_index() const { return literal_index_; }
2989 int depth() const { return depth_; }
2990
2991 DECLARE_INSTRUCTION(MaterializedLiteral)
2992
2993 private:
2994 int literal_index_;
2995 int depth_;
2996};
2997
2998
2999class HArrayLiteral: public HMaterializedLiteral {
3000 public:
3001 HArrayLiteral(Handle<FixedArray> constant_elements,
3002 int length,
3003 int literal_index,
3004 int depth)
3005 : HMaterializedLiteral(literal_index, depth),
3006 length_(length),
3007 constant_elements_(constant_elements) {}
3008
3009 Handle<FixedArray> constant_elements() const { return constant_elements_; }
3010 int length() const { return length_; }
3011
3012 bool IsCopyOnWrite() const;
3013
3014 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
3015
3016 private:
3017 int length_;
3018 Handle<FixedArray> constant_elements_;
3019};
3020
3021
3022class HObjectLiteral: public HMaterializedLiteral {
3023 public:
3024 HObjectLiteral(Handle<FixedArray> constant_properties,
3025 bool fast_elements,
3026 int literal_index,
3027 int depth)
3028 : HMaterializedLiteral(literal_index, depth),
3029 constant_properties_(constant_properties),
3030 fast_elements_(fast_elements) {}
3031
3032 Handle<FixedArray> constant_properties() const {
3033 return constant_properties_;
3034 }
3035 bool fast_elements() const { return fast_elements_; }
3036
3037 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
3038
3039 private:
3040 Handle<FixedArray> constant_properties_;
3041 bool fast_elements_;
3042};
3043
3044
3045class HRegExpLiteral: public HMaterializedLiteral {
3046 public:
3047 HRegExpLiteral(Handle<String> pattern,
3048 Handle<String> flags,
3049 int literal_index)
3050 : HMaterializedLiteral(literal_index, 0),
3051 pattern_(pattern),
3052 flags_(flags) { }
3053
3054 Handle<String> pattern() { return pattern_; }
3055 Handle<String> flags() { return flags_; }
3056
3057 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
3058
3059 private:
3060 Handle<String> pattern_;
3061 Handle<String> flags_;
3062};
3063
3064
3065class HFunctionLiteral: public HInstruction {
3066 public:
3067 HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
3068 : shared_info_(shared), pretenure_(pretenure) {
3069 set_representation(Representation::Tagged());
3070 }
3071
3072 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
3073
3074 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
3075 bool pretenure() const { return pretenure_; }
3076
3077 private:
3078 Handle<SharedFunctionInfo> shared_info_;
3079 bool pretenure_;
3080};
3081
3082
3083class HTypeof: public HUnaryOperation {
3084 public:
3085 explicit HTypeof(HValue* value) : HUnaryOperation(value) {
3086 set_representation(Representation::Tagged());
3087 }
3088
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003089 virtual Representation RequiredInputRepresentation(int index) const {
3090 return Representation::Tagged();
3091 }
3092
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003093 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
3094};
3095
3096
3097class HValueOf: public HUnaryOperation {
3098 public:
3099 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
3100 set_representation(Representation::Tagged());
3101 }
3102
3103 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
3104};
3105
3106
3107class HDeleteProperty: public HBinaryOperation {
3108 public:
3109 HDeleteProperty(HValue* obj, HValue* key)
3110 : HBinaryOperation(obj, key) {
3111 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00003112 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003113 }
3114
3115 virtual Representation RequiredInputRepresentation(int index) const {
3116 return Representation::Tagged();
3117 }
3118
3119 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
3120
3121 HValue* object() const { return left(); }
3122 HValue* key() const { return right(); }
3123};
3124
3125#undef DECLARE_INSTRUCTION
3126#undef DECLARE_CONCRETE_INSTRUCTION
3127
3128} } // namespace v8::internal
3129
3130#endif // V8_HYDROGEN_INSTRUCTIONS_H_