blob: ff8170012e6b025e0a0d7b6ded6652e6075beb6c [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) \
67 V(AccessArgumentsAt) \
68 V(Add) \
69 V(ApplyArguments) \
70 V(ArgumentsElements) \
71 V(ArgumentsLength) \
72 V(ArgumentsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000073 V(ArrayLiteral) \
74 V(BitAnd) \
75 V(BitNot) \
76 V(BitOr) \
77 V(BitXor) \
78 V(BlockEntry) \
79 V(BoundsCheck) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000080 V(CallConstantFunction) \
81 V(CallFunction) \
82 V(CallGlobal) \
83 V(CallKeyed) \
84 V(CallKnownGlobal) \
85 V(CallNamed) \
86 V(CallNew) \
87 V(CallRuntime) \
88 V(CallStub) \
89 V(Change) \
90 V(CheckFunction) \
91 V(CheckInstanceType) \
92 V(CheckMap) \
93 V(CheckNonSmi) \
94 V(CheckPrototypeMaps) \
95 V(CheckSmi) \
96 V(Compare) \
97 V(CompareJSObjectEq) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000098 V(CompareMap) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000099 V(Constant) \
100 V(DeleteProperty) \
101 V(Deoptimize) \
102 V(Div) \
103 V(EnterInlined) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000104 V(FixedArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000105 V(FunctionLiteral) \
106 V(GlobalObject) \
107 V(GlobalReceiver) \
108 V(Goto) \
109 V(InstanceOf) \
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000110 V(InstanceOfKnownGlobal) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000111 V(IsNull) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000112 V(IsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000113 V(IsSmi) \
114 V(HasInstanceType) \
115 V(HasCachedArrayIndex) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000116 V(JSArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117 V(ClassOfTest) \
118 V(LeaveInlined) \
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000119 V(LoadContextSlot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000120 V(LoadElements) \
ager@chromium.org378b34e2011-01-28 08:04:38 +0000121 V(LoadFunctionPrototype) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000122 V(LoadGlobal) \
123 V(LoadKeyedFastElement) \
124 V(LoadKeyedGeneric) \
125 V(LoadNamedField) \
126 V(LoadNamedGeneric) \
127 V(Mod) \
128 V(Mul) \
129 V(ObjectLiteral) \
130 V(OsrEntry) \
131 V(Parameter) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000132 V(Power) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000133 V(PushArgument) \
134 V(RegExpLiteral) \
135 V(Return) \
136 V(Sar) \
137 V(Shl) \
138 V(Shr) \
139 V(Simulate) \
140 V(StackCheck) \
141 V(StoreGlobal) \
142 V(StoreKeyedFastElement) \
143 V(StoreKeyedGeneric) \
144 V(StoreNamedField) \
145 V(StoreNamedGeneric) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000146 V(StringCharCodeAt) \
147 V(StringLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000148 V(Sub) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000149 V(Test) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000150 V(Throw) \
151 V(Typeof) \
152 V(TypeofIs) \
153 V(UnaryMathOperation) \
154 V(UnknownOSRValue) \
155 V(ValueOf)
156
157#define GVN_FLAG_LIST(V) \
158 V(Calls) \
159 V(InobjectFields) \
160 V(BackingStoreFields) \
161 V(ArrayElements) \
162 V(GlobalVars) \
163 V(Maps) \
164 V(ArrayLengths) \
165 V(OsrEntries)
166
167#define DECLARE_INSTRUCTION(type) \
168 virtual bool Is##type() const { return true; } \
169 static H##type* cast(HValue* value) { \
170 ASSERT(value->Is##type()); \
171 return reinterpret_cast<H##type*>(value); \
172 } \
173 Opcode opcode() const { return HValue::k##type; }
174
175
176#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
177 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
178 virtual const char* Mnemonic() const { return mnemonic; } \
179 DECLARE_INSTRUCTION(type)
180
181
182
183template<int kSize>
184class HOperandVector : public EmbeddedVector<HValue*, kSize> {
185 public:
186 HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
187};
188
189
190class Range: public ZoneObject {
191 public:
192 Range() : lower_(kMinInt),
193 upper_(kMaxInt),
194 next_(NULL),
195 can_be_minus_zero_(false) { }
196
197 Range(int32_t lower, int32_t upper)
198 : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
199
200 bool IsInSmiRange() const {
201 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
202 }
203 void KeepOrder();
204 void Verify() const;
205 int32_t upper() const { return upper_; }
206 int32_t lower() const { return lower_; }
207 Range* next() const { return next_; }
208 Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
209 Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
210 void ClearLower() { lower_ = kMinInt; }
211 void ClearUpper() { upper_ = kMaxInt; }
212 Range* Copy() const { return new Range(lower_, upper_); }
213 bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
214 int32_t Mask() const;
215 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
216 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
217 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
218 bool CanBeNegative() const { return lower_ < 0; }
219 bool Includes(int value) const {
220 return lower_ <= value && upper_ >= value;
221 }
222
223 void Sar(int32_t value) {
224 int32_t bits = value & 0x1F;
225 lower_ = lower_ >> bits;
226 upper_ = upper_ >> bits;
227 set_can_be_minus_zero(false);
228 }
229
230 void Shl(int32_t value) {
231 int32_t bits = value & 0x1F;
232 int old_lower = lower_;
233 int old_upper = upper_;
234 lower_ = lower_ << bits;
235 upper_ = upper_ << bits;
236 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
237 upper_ = kMaxInt;
238 lower_ = kMinInt;
239 }
240 set_can_be_minus_zero(false);
241 }
242
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000243 // Adds a constant to the lower and upper bound of the range.
244 void AddConstant(int32_t value);
245
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000246 void StackUpon(Range* other) {
247 Intersect(other);
248 next_ = other;
249 }
250
251 void Intersect(Range* other) {
252 upper_ = Min(upper_, other->upper_);
253 lower_ = Max(lower_, other->lower_);
254 bool b = CanBeMinusZero() && other->CanBeMinusZero();
255 set_can_be_minus_zero(b);
256 }
257
258 void Union(Range* other) {
259 upper_ = Max(upper_, other->upper_);
260 lower_ = Min(lower_, other->lower_);
261 bool b = CanBeMinusZero() || other->CanBeMinusZero();
262 set_can_be_minus_zero(b);
263 }
264
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000265 // Compute a new result range and return true, if the operation
266 // can overflow.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000267 bool AddAndCheckOverflow(Range* other);
268 bool SubAndCheckOverflow(Range* other);
269 bool MulAndCheckOverflow(Range* other);
270
271 private:
272 int32_t lower_;
273 int32_t upper_;
274 Range* next_;
275 bool can_be_minus_zero_;
276};
277
278
279class Representation {
280 public:
281 enum Kind {
282 kNone,
283 kTagged,
284 kDouble,
285 kInteger32,
286 kNumRepresentations
287 };
288
289 Representation() : kind_(kNone) { }
290
291 static Representation None() { return Representation(kNone); }
292 static Representation Tagged() { return Representation(kTagged); }
293 static Representation Integer32() { return Representation(kInteger32); }
294 static Representation Double() { return Representation(kDouble); }
295
296 bool Equals(const Representation& other) const {
297 return kind_ == other.kind_;
298 }
299
300 Kind kind() const { return kind_; }
301 bool IsNone() const { return kind_ == kNone; }
302 bool IsTagged() const { return kind_ == kTagged; }
303 bool IsInteger32() const { return kind_ == kInteger32; }
304 bool IsDouble() const { return kind_ == kDouble; }
305 bool IsSpecialization() const {
306 return kind_ == kInteger32 || kind_ == kDouble;
307 }
308 const char* Mnemonic() const;
309
310 private:
311 explicit Representation(Kind k) : kind_(k) { }
312
313 Kind kind_;
314};
315
316
317class HType {
318 public:
319 HType() : type_(kUninitialized) { }
320
321 static HType Tagged() { return HType(kTagged); }
322 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
323 static HType TaggedNumber() { return HType(kTaggedNumber); }
324 static HType Smi() { return HType(kSmi); }
325 static HType HeapNumber() { return HType(kHeapNumber); }
326 static HType String() { return HType(kString); }
327 static HType Boolean() { return HType(kBoolean); }
328 static HType NonPrimitive() { return HType(kNonPrimitive); }
329 static HType JSArray() { return HType(kJSArray); }
330 static HType JSObject() { return HType(kJSObject); }
331 static HType Uninitialized() { return HType(kUninitialized); }
332
333 // Return the weakest (least precise) common type.
334 HType Combine(HType other) {
335 return HType(static_cast<Type>(type_ & other.type_));
336 }
337
338 bool Equals(const HType& other) {
339 return type_ == other.type_;
340 }
341
342 bool IsSubtypeOf(const HType& other) {
343 return Combine(other).Equals(other);
344 }
345
346 bool IsTagged() {
347 ASSERT(type_ != kUninitialized);
348 return ((type_ & kTagged) == kTagged);
349 }
350
351 bool IsTaggedPrimitive() {
352 ASSERT(type_ != kUninitialized);
353 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
354 }
355
356 bool IsTaggedNumber() {
357 ASSERT(type_ != kUninitialized);
358 return ((type_ & kTaggedNumber) == kTaggedNumber);
359 }
360
361 bool IsSmi() {
362 ASSERT(type_ != kUninitialized);
363 return ((type_ & kSmi) == kSmi);
364 }
365
366 bool IsHeapNumber() {
367 ASSERT(type_ != kUninitialized);
368 return ((type_ & kHeapNumber) == kHeapNumber);
369 }
370
371 bool IsString() {
372 ASSERT(type_ != kUninitialized);
373 return ((type_ & kString) == kString);
374 }
375
376 bool IsBoolean() {
377 ASSERT(type_ != kUninitialized);
378 return ((type_ & kBoolean) == kBoolean);
379 }
380
381 bool IsNonPrimitive() {
382 ASSERT(type_ != kUninitialized);
383 return ((type_ & kNonPrimitive) == kNonPrimitive);
384 }
385
386 bool IsJSArray() {
387 ASSERT(type_ != kUninitialized);
388 return ((type_ & kJSArray) == kJSArray);
389 }
390
391 bool IsJSObject() {
392 ASSERT(type_ != kUninitialized);
393 return ((type_ & kJSObject) == kJSObject);
394 }
395
396 bool IsUninitialized() {
397 return type_ == kUninitialized;
398 }
399
400 static HType TypeFromValue(Handle<Object> value);
401
402 const char* ToString();
403 const char* ToShortString();
404
405 private:
406 enum Type {
407 kTagged = 0x1, // 0000 0000 0000 0001
408 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
409 kTaggedNumber = 0xd, // 0000 0000 0000 1101
410 kSmi = 0x1d, // 0000 0000 0001 1101
411 kHeapNumber = 0x2d, // 0000 0000 0010 1101
412 kString = 0x45, // 0000 0000 0100 0101
413 kBoolean = 0x85, // 0000 0000 1000 0101
414 kNonPrimitive = 0x101, // 0000 0001 0000 0001
415 kJSObject = 0x301, // 0000 0011 0000 0001
416 kJSArray = 0x701, // 0000 0111 1000 0001
417 kUninitialized = 0x1fff // 0001 1111 1111 1111
418 };
419
420 explicit HType(Type t) : type_(t) { }
421
422 Type type_;
423};
424
425
426class HValue: public ZoneObject {
427 public:
428 static const int kNoNumber = -1;
429
430 // There must be one corresponding kDepends flag for every kChanges flag and
431 // the order of the kChanges flags must be exactly the same as of the kDepends
432 // flags.
433 enum Flag {
434 // Declare global value numbering flags.
435 #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
436 GVN_FLAG_LIST(DECLARE_DO)
437 #undef DECLARE_DO
438 kFlexibleRepresentation,
439 kUseGVN,
440 kCanOverflow,
441 kBailoutOnMinusZero,
442 kCanBeDivByZero,
443 kIsArguments,
444 kTruncatingToInt32,
445 kLastFlag = kTruncatingToInt32
446 };
447
448 STATIC_ASSERT(kLastFlag < kBitsPerInt);
449
450 static const int kChangesToDependsFlagsLeftShift = 1;
451
452 static int ChangesFlagsMask() {
453 int result = 0;
454 // Create changes mask.
455#define DECLARE_DO(type) result |= (1 << kChanges##type);
456 GVN_FLAG_LIST(DECLARE_DO)
457#undef DECLARE_DO
458 return result;
459 }
460
461 static int DependsFlagsMask() {
462 return ConvertChangesToDependsFlags(ChangesFlagsMask());
463 }
464
465 static int ConvertChangesToDependsFlags(int flags) {
466 return flags << kChangesToDependsFlagsLeftShift;
467 }
468
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000469 static HValue* cast(HValue* value) { return value; }
470
471 enum Opcode {
472 // Declare a unique enum value for each hydrogen instruction.
473 #define DECLARE_DO(type) k##type,
474 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
475 #undef DECLARE_DO
476 kMaxInstructionClass
477 };
478
479 HValue() : block_(NULL),
480 id_(kNoNumber),
481 uses_(2),
482 type_(HType::Tagged()),
483 range_(NULL),
484 flags_(0) {}
485 virtual ~HValue() {}
486
487 HBasicBlock* block() const { return block_; }
488 void SetBlock(HBasicBlock* block);
489
490 int id() const { return id_; }
491 void set_id(int id) { id_ = id; }
492
493 const ZoneList<HValue*>* uses() const { return &uses_; }
494
495 virtual bool EmitAtUses() const { return false; }
496 Representation representation() const { return representation_; }
497 void ChangeRepresentation(Representation r) {
498 // Representation was already set and is allowed to be changed.
499 ASSERT(!representation_.IsNone());
500 ASSERT(!r.IsNone());
501 ASSERT(CheckFlag(kFlexibleRepresentation));
502 RepresentationChanged(r);
503 representation_ = r;
504 }
505
506 HType type() const { return type_; }
507 void set_type(HType type) {
508 ASSERT(uses_.length() == 0);
509 type_ = type;
510 }
511
512 // An operation needs to override this function iff:
513 // 1) it can produce an int32 output.
514 // 2) the true value of its output can potentially be minus zero.
515 // The implementation must set a flag so that it bails out in the case where
516 // it would otherwise output what should be a minus zero as an int32 zero.
517 // If the operation also exists in a form that takes int32 and outputs int32
518 // then the operation should return its input value so that we can propagate
519 // back. There are two operations that need to propagate back to more than
520 // one input. They are phi and binary add. They always return NULL and
521 // expect the caller to take care of things.
522 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
523 visited->Add(id());
524 return NULL;
525 }
526
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000527 bool IsDefinedAfter(HBasicBlock* other) const;
528
529 // Operands.
530 virtual int OperandCount() const { return 0; }
531 virtual HValue* OperandAt(int index) const {
532 UNREACHABLE();
533 return NULL;
534 }
535 void SetOperandAt(int index, HValue* value);
536
537 int LookupOperandIndex(int occurrence_index, HValue* op) const;
538 bool UsesMultipleTimes(HValue* op) const;
539
540 void ReplaceAndDelete(HValue* other);
541 void ReplaceValue(HValue* other);
542 void ReplaceAtUse(HValue* use, HValue* other);
543 void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
544 bool HasNoUses() const { return uses_.is_empty(); }
545 void ClearOperands();
546 void Delete();
547
548 int flags() const { return flags_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000549 void SetFlag(Flag f) { flags_ |= (1 << f); }
550 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
551 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
552
553 void SetAllSideEffects() { flags_ |= AllSideEffects(); }
554 void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
555 bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000556
557 Range* range() const { return range_; }
558 bool HasRange() const { return range_ != NULL; }
559 void AddNewRange(Range* r);
560 void RemoveLastAddedRange();
561 void ComputeInitialRange();
562
563 // Representation helpers.
564 virtual Representation RequiredInputRepresentation(int index) const {
565 return Representation::None();
566 }
567 virtual Representation InferredRepresentation() const {
568 return representation();
569 }
570
571 // This gives the instruction an opportunity to replace itself with an
572 // instruction that does the same in some better way. To replace an
573 // instruction with a new one, first add the new instruction to the graph,
574 // then return it. Return NULL to have the instruction deleted.
575 virtual HValue* Canonicalize() { return this; }
576
577 // Declare virtual type testers.
578#define DECLARE_DO(type) virtual bool Is##type() const { return false; }
579 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
580#undef DECLARE_DO
581
582 bool Equals(HValue* other) const;
583 virtual intptr_t Hashcode() const;
584
585 // Printing support.
586 virtual void PrintTo(StringStream* stream) const = 0;
587 void PrintNameTo(StringStream* stream);
588 static void PrintTypeTo(HType type, StringStream* stream);
589
590 virtual const char* Mnemonic() const = 0;
591 virtual Opcode opcode() const = 0;
592
593 // Updated the inferred type of this instruction and returns true if
594 // it has changed.
595 bool UpdateInferredType();
596
597 virtual HType CalculateInferredType() const;
598
599 // Helper for type conversions used by normal and phi instructions.
600 void InsertInputConversion(HInstruction* previous, int index, HType type);
601
602#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000603 virtual void Verify() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000604#endif
605
606 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000607 // This function must be overridden for instructions with flag kUseGVN, to
608 // compare the non-Operand parts of the instruction.
609 virtual bool DataEquals(HValue* other) const {
610 UNREACHABLE();
611 return false;
612 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000613 virtual void RepresentationChanged(Representation to) { }
614 virtual Range* InferRange();
615 virtual void DeleteFromGraph() = 0;
616 virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
617 void clear_block() {
618 ASSERT(block_ != NULL);
619 block_ = NULL;
620 }
621
622 void set_representation(Representation r) {
623 // Representation is set-once.
624 ASSERT(representation_.IsNone() && !r.IsNone());
625 representation_ = r;
626 }
627
628 private:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000629 // A flag mask to mark an instruction as having arbitrary side effects.
630 static int AllSideEffects() {
631 return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
632 }
633
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000634 void InternalReplaceAtUse(HValue* use, HValue* other);
635 void RegisterUse(int index, HValue* new_value);
636
637 HBasicBlock* block_;
638
639 // The id of this instruction in the hydrogen graph, assigned when first
640 // added to the graph. Reflects creation order.
641 int id_;
642
643 Representation representation_;
644 ZoneList<HValue*> uses_;
645 HType type_;
646 Range* range_;
647 int flags_;
648
649 DISALLOW_COPY_AND_ASSIGN(HValue);
650};
651
652
653class HInstruction: public HValue {
654 public:
655 HInstruction* next() const { return next_; }
656 HInstruction* previous() const { return previous_; }
657
658 void PrintTo(StringStream* stream) const;
659 virtual void PrintDataTo(StringStream* stream) const {}
660
661 bool IsLinked() const { return block() != NULL; }
662 void Unlink();
663 void InsertBefore(HInstruction* next);
664 void InsertAfter(HInstruction* previous);
665
666 int position() const { return position_; }
667 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
668 void set_position(int position) { position_ = position; }
669
670 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
671
672#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000673 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000674#endif
675
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000676 // Returns whether this is some kind of deoptimizing check
677 // instruction.
678 virtual bool IsCheckInstruction() const { return false; }
679
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000680 DECLARE_INSTRUCTION(Instruction)
681
682 protected:
683 HInstruction()
684 : next_(NULL),
685 previous_(NULL),
686 position_(RelocInfo::kNoPosition) {
687 SetFlag(kDependsOnOsrEntries);
688 }
689
690 virtual void DeleteFromGraph() { Unlink(); }
691
692 private:
693 void InitializeAsFirst(HBasicBlock* block) {
694 ASSERT(!IsLinked());
695 SetBlock(block);
696 }
697
698 HInstruction* next_;
699 HInstruction* previous_;
700 int position_;
701
702 friend class HBasicBlock;
703};
704
705
706class HBlockEntry: public HInstruction {
707 public:
708 DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
709};
710
711
712class HControlInstruction: public HInstruction {
713 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000714 HControlInstruction(HBasicBlock* first, HBasicBlock* second)
715 : first_successor_(first), second_successor_(second) {
716 }
717
718 HBasicBlock* FirstSuccessor() const { return first_successor_; }
719 HBasicBlock* SecondSuccessor() const { return second_successor_; }
720
721 virtual void PrintDataTo(StringStream* stream) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000722
723 DECLARE_INSTRUCTION(ControlInstruction)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000724
725 private:
726 HBasicBlock* first_successor_;
727 HBasicBlock* second_successor_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000728};
729
730
731class HDeoptimize: public HControlInstruction {
732 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000733 HDeoptimize() : HControlInstruction(NULL, NULL) { }
734
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000735 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
736};
737
738
739class HGoto: public HControlInstruction {
740 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000741 explicit HGoto(HBasicBlock* target)
742 : HControlInstruction(target, NULL), include_stack_check_(false) {
743 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000744
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000745 void set_include_stack_check(bool include_stack_check) {
746 include_stack_check_ = include_stack_check;
747 }
748 bool include_stack_check() const { return include_stack_check_; }
749
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000750 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
751
752 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000753 bool include_stack_check_;
754};
755
756
757class HUnaryControlInstruction: public HControlInstruction {
758 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000759 explicit HUnaryControlInstruction(HValue* value,
760 HBasicBlock* true_target,
761 HBasicBlock* false_target)
762 : HControlInstruction(true_target, false_target) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000763 SetOperandAt(0, value);
764 }
765
766 virtual Representation RequiredInputRepresentation(int index) const {
767 return Representation::Tagged();
768 }
769
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000770 virtual void PrintDataTo(StringStream* stream) const;
771
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000772 HValue* value() const { return OperandAt(0); }
773 virtual int OperandCount() const { return 1; }
774 virtual HValue* OperandAt(int index) const { return operands_[index]; }
775
776 DECLARE_INSTRUCTION(UnaryControlInstruction)
777
778 protected:
779 virtual void InternalSetOperandAt(int index, HValue* value) {
780 operands_[index] = value;
781 }
782
783 private:
784 HOperandVector<1> operands_;
785};
786
787
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000788class HTest: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000789 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000790 HTest(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target)
791 : HUnaryControlInstruction(value, true_target, false_target) {
792 ASSERT(true_target != NULL && false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000793 }
794
795 virtual Representation RequiredInputRepresentation(int index) const {
796 return Representation::None();
797 }
798
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000799 DECLARE_CONCRETE_INSTRUCTION(Test, "test")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000800};
801
802
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000803class HCompareMap: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000804 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000805 HCompareMap(HValue* value,
806 Handle<Map> map,
807 HBasicBlock* true_target,
808 HBasicBlock* false_target)
809 : HUnaryControlInstruction(value, true_target, false_target),
810 map_(map) {
811 ASSERT(true_target != NULL);
812 ASSERT(false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000813 ASSERT(!map.is_null());
814 }
815
whesse@chromium.org023421e2010-12-21 12:19:12 +0000816 virtual void PrintDataTo(StringStream* stream) const;
817
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000818 Handle<Map> map() const { return map_; }
819
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000820 DECLARE_CONCRETE_INSTRUCTION(CompareMap, "compare_map")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000821
822 private:
823 Handle<Map> map_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000824};
825
826
827class HReturn: public HUnaryControlInstruction {
828 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000829 explicit HReturn(HValue* value)
830 : HUnaryControlInstruction(value, NULL, NULL) {
831 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000832
833 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
834};
835
836
837class HThrow: public HUnaryControlInstruction {
838 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000839 explicit HThrow(HValue* value)
840 : HUnaryControlInstruction(value, NULL, NULL) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000841
842 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
843};
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
869class HChange: public HUnaryOperation {
870 public:
871 HChange(HValue* value,
872 Representation from,
873 Representation to)
874 : HUnaryOperation(value), from_(from), to_(to) {
875 ASSERT(!from.IsNone() && !to.IsNone());
876 ASSERT(!from.Equals(to));
877 set_representation(to);
878 SetFlag(kUseGVN);
879
880 if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
881 value->range()->IsInSmiRange()) {
882 set_type(HType::Smi());
883 }
884 }
885
886 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
887
888 Representation from() const { return from_; }
889 Representation to() const { return to_; }
890 virtual Representation RequiredInputRepresentation(int index) const {
891 return from_;
892 }
893
894 bool CanTruncateToInt32() const {
895 for (int i = 0; i < uses()->length(); ++i) {
896 if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
897 }
898 return true;
899 }
900
901 virtual void PrintDataTo(StringStream* stream) const;
902
903 DECLARE_CONCRETE_INSTRUCTION(Change,
904 CanTruncateToInt32() ? "truncate" : "change")
905
906 protected:
907 virtual bool DataEquals(HValue* other) const {
908 if (!other->IsChange()) return false;
909 HChange* change = HChange::cast(other);
910 return value() == change->value()
911 && to().Equals(change->to())
912 && CanTruncateToInt32() == change->CanTruncateToInt32();
913 }
914
915 private:
916 Representation from_;
917 Representation to_;
918};
919
920
921class HSimulate: public HInstruction {
922 public:
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000923 HSimulate(int ast_id, int pop_count, int environment_length)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000924 : ast_id_(ast_id),
925 pop_count_(pop_count),
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000926 environment_length_(environment_length),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000927 values_(2),
928 assigned_indexes_(2) {}
929 virtual ~HSimulate() {}
930
931 virtual void PrintDataTo(StringStream* stream) const;
932
933 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
934 int ast_id() const { return ast_id_; }
935 void set_ast_id(int id) {
936 ASSERT(!HasAstId());
937 ast_id_ = id;
938 }
939
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000940 int environment_length() const { return environment_length_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000941 int pop_count() const { return pop_count_; }
942 const ZoneList<HValue*>* values() const { return &values_; }
943 int GetAssignedIndexAt(int index) const {
944 ASSERT(HasAssignedIndexAt(index));
945 return assigned_indexes_[index];
946 }
947 bool HasAssignedIndexAt(int index) const {
948 return assigned_indexes_[index] != kNoIndex;
949 }
950 void AddAssignedValue(int index, HValue* value) {
951 AddValue(index, value);
952 }
953 void AddPushedValue(HValue* value) {
954 AddValue(kNoIndex, value);
955 }
956 virtual int OperandCount() const { return values_.length(); }
957 virtual HValue* OperandAt(int index) const { return values_[index]; }
958
959 DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
960
961#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000962 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000963#endif
964
965 protected:
966 virtual void InternalSetOperandAt(int index, HValue* value) {
967 values_[index] = value;
968 }
969
970 private:
971 static const int kNoIndex = -1;
972 void AddValue(int index, HValue* value) {
973 assigned_indexes_.Add(index);
974 // Resize the list of pushed values.
975 values_.Add(NULL);
976 // Set the operand through the base method in HValue to make sure that the
977 // use lists are correctly updated.
978 SetOperandAt(values_.length() - 1, value);
979 }
980 int ast_id_;
981 int pop_count_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000982 int environment_length_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000983 ZoneList<HValue*> values_;
984 ZoneList<int> assigned_indexes_;
985};
986
987
988class HStackCheck: public HInstruction {
989 public:
990 HStackCheck() { }
991
992 DECLARE_CONCRETE_INSTRUCTION(Throw, "stack_check")
993};
994
995
996class HEnterInlined: public HInstruction {
997 public:
998 HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
999 : closure_(closure), function_(function) {
1000 }
1001
1002 virtual void PrintDataTo(StringStream* stream) const;
1003
1004 Handle<JSFunction> closure() const { return closure_; }
1005 FunctionLiteral* function() const { return function_; }
1006
1007 DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
1008
1009 private:
1010 Handle<JSFunction> closure_;
1011 FunctionLiteral* function_;
1012};
1013
1014
1015class HLeaveInlined: public HInstruction {
1016 public:
1017 HLeaveInlined() {}
1018
1019 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
1020};
1021
1022
1023class HPushArgument: public HUnaryOperation {
1024 public:
1025 explicit HPushArgument(HValue* value)
1026 : HUnaryOperation(value), argument_index_(-1) {
1027 set_representation(Representation::Tagged());
1028 }
1029
1030 virtual Representation RequiredInputRepresentation(int index) const {
1031 return Representation::Tagged();
1032 }
1033
1034 virtual void PrintDataTo(StringStream* stream) const;
1035 HValue* argument() const { return OperandAt(0); }
1036 int argument_index() const { return argument_index_; }
1037 void set_argument_index(int index) {
1038 ASSERT(argument_index_ == -1 || index == argument_index_);
1039 argument_index_ = index;
1040 }
1041
1042 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
1043
1044 private:
1045 int argument_index_;
1046};
1047
1048
1049class HGlobalObject: public HInstruction {
1050 public:
1051 HGlobalObject() {
1052 set_representation(Representation::Tagged());
1053 SetFlag(kUseGVN);
1054 SetFlag(kDependsOnCalls);
1055 }
1056
1057 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001058
1059 protected:
1060 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001061};
1062
1063
1064class HGlobalReceiver: public HInstruction {
1065 public:
1066 HGlobalReceiver() {
1067 set_representation(Representation::Tagged());
1068 SetFlag(kUseGVN);
1069 SetFlag(kDependsOnCalls);
1070 }
1071
1072 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001073
1074 protected:
1075 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001076};
1077
1078
1079class HCall: public HInstruction {
1080 public:
1081 // Construct a call with uninitialized arguments. The argument count
1082 // includes the receiver.
1083 explicit HCall(int count);
1084
1085 virtual HType CalculateInferredType() const { return HType::Tagged(); }
1086
1087 // TODO(3190496): This needs a cleanup. We don't want the arguments
1088 // be operands of the call instruction. This results in bad code quality.
1089 virtual int argument_count() const { return arguments_.length(); }
1090 virtual int OperandCount() const { return argument_count(); }
1091 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1092 virtual HPushArgument* PushArgumentAt(int index) const {
1093 return HPushArgument::cast(OperandAt(index));
1094 }
1095 virtual HValue* ArgumentAt(int index) const {
1096 return PushArgumentAt(index)->argument();
1097 }
1098 virtual void SetArgumentAt(int index, HPushArgument* push_argument);
1099
1100 virtual void PrintDataTo(StringStream* stream) const;
1101
1102 DECLARE_INSTRUCTION(Call)
1103
1104 protected:
1105 virtual void InternalSetOperandAt(int index, HValue* value) {
1106 arguments_[index] = value;
1107 }
1108
1109 int argument_count_;
1110 Vector<HValue*> arguments_;
1111};
1112
1113
1114class HCallConstantFunction: public HCall {
1115 public:
1116 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1117 : HCall(argument_count), function_(function) { }
1118
1119 Handle<JSFunction> function() const { return function_; }
1120 bool IsApplyFunction() const {
1121 return function_->code() == Builtins::builtin(Builtins::FunctionApply);
1122 }
1123
1124 virtual void PrintDataTo(StringStream* stream) const;
1125
1126 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
1127
1128 private:
1129 Handle<JSFunction> function_;
1130};
1131
1132
1133class HCallKeyed: public HCall {
1134 public:
1135 HCallKeyed(HValue* key, int argument_count)
1136 : HCall(argument_count + 1) {
1137 SetOperandAt(0, key);
1138 }
1139
1140 virtual Representation RequiredInputRepresentation(int index) const {
1141 return Representation::Tagged();
1142 }
1143
1144 // TODO(3190496): This is a hack to get an additional operand that
1145 // is not an argument to work with the current setup. This _needs_ a cleanup.
1146 // (see HCall)
1147 virtual void PrintDataTo(StringStream* stream) const;
1148 HValue* key() const { return OperandAt(0); }
1149 virtual int argument_count() const { return arguments_.length() - 1; }
1150 virtual int OperandCount() const { return arguments_.length(); }
1151 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1152 virtual HPushArgument* PushArgumentAt(int index) const {
1153 return HPushArgument::cast(OperandAt(index + 1));
1154 }
1155 virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
1156 HCall::SetArgumentAt(index + 1, push_argument);
1157 }
1158
1159 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
1160};
1161
1162
1163class HCallNamed: public HCall {
1164 public:
1165 HCallNamed(Handle<String> name, int argument_count)
1166 : HCall(argument_count), name_(name) { }
1167 virtual void PrintDataTo(StringStream* stream) const;
1168
1169 Handle<String> name() const { return name_; }
1170
1171 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
1172
1173 private:
1174 Handle<String> name_;
1175};
1176
1177
1178class HCallFunction: public HCall {
1179 public:
1180 explicit HCallFunction(int argument_count) : HCall(argument_count) { }
1181
1182 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
1183};
1184
1185
1186class HCallGlobal: public HCall {
1187 public:
1188 HCallGlobal(Handle<String> name, int argument_count)
1189 : HCall(argument_count), name_(name) { }
1190
1191 virtual void PrintDataTo(StringStream* stream) const;
1192
1193 Handle<String> name() const { return name_; }
1194
1195 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
1196
1197 private:
1198 Handle<String> name_;
1199};
1200
1201
1202class HCallKnownGlobal: public HCall {
1203 public:
1204 HCallKnownGlobal(Handle<JSFunction> target,
1205 int argument_count)
1206 : HCall(argument_count), target_(target) { }
1207
1208 Handle<JSFunction> target() const { return target_; }
1209
1210 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
1211
1212 private:
1213 Handle<JSFunction> target_;
1214};
1215
1216
1217class HCallNew: public HCall {
1218 public:
1219 explicit HCallNew(int argument_count) : HCall(argument_count) { }
1220
1221 virtual Representation RequiredInputRepresentation(int index) const {
1222 return Representation::Tagged();
1223 }
1224
1225 HValue* constructor() const { return ArgumentAt(0); }
1226
1227 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
1228};
1229
1230
1231class HCallRuntime: public HCall {
1232 public:
1233 HCallRuntime(Handle<String> name,
1234 Runtime::Function* c_function,
1235 int argument_count)
1236 : HCall(argument_count), c_function_(c_function), name_(name) { }
1237 virtual void PrintDataTo(StringStream* stream) const;
1238
1239 Runtime::Function* function() const { return c_function_; }
1240 Handle<String> name() const { return name_; }
1241
1242 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
1243
1244 private:
1245 Runtime::Function* c_function_;
1246 Handle<String> name_;
1247};
1248
1249
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001250class HJSArrayLength: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001251 public:
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001252 explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001253 // The length of an array is stored as a tagged value in the array
1254 // object. It is guaranteed to be 32 bit integer, but it can be
1255 // represented as either a smi or heap number.
1256 set_representation(Representation::Tagged());
1257 SetFlag(kDependsOnArrayLengths);
1258 SetFlag(kUseGVN);
1259 }
1260
1261 virtual Representation RequiredInputRepresentation(int index) const {
1262 return Representation::Tagged();
1263 }
1264
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001265 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001266
1267 protected:
1268 virtual bool DataEquals(HValue* other) const { return true; }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001269};
1270
1271
1272class HFixedArrayLength: public HUnaryOperation {
1273 public:
1274 explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
1275 set_representation(Representation::Tagged());
1276 SetFlag(kDependsOnArrayLengths);
1277 SetFlag(kUseGVN);
1278 }
1279
1280 virtual Representation RequiredInputRepresentation(int index) const {
1281 return Representation::Tagged();
1282 }
1283
1284 DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001285
1286 protected:
1287 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001288};
1289
1290
1291class HBitNot: public HUnaryOperation {
1292 public:
1293 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1294 set_representation(Representation::Integer32());
1295 SetFlag(kUseGVN);
1296 SetFlag(kTruncatingToInt32);
1297 }
1298
1299 virtual Representation RequiredInputRepresentation(int index) const {
1300 return Representation::Integer32();
1301 }
1302 virtual HType CalculateInferredType() const;
1303
1304 DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001305
1306 protected:
1307 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001308};
1309
1310
1311class HUnaryMathOperation: public HUnaryOperation {
1312 public:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001313 HUnaryMathOperation(HValue* value, BuiltinFunctionId op)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001314 : HUnaryOperation(value), op_(op) {
1315 switch (op) {
1316 case kMathFloor:
1317 case kMathRound:
1318 case kMathCeil:
1319 set_representation(Representation::Integer32());
1320 break;
1321 case kMathAbs:
1322 set_representation(Representation::Tagged());
1323 SetFlag(kFlexibleRepresentation);
1324 break;
1325 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001326 case kMathPowHalf:
1327 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001328 case kMathSin:
1329 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001330 set_representation(Representation::Double());
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001331 break;
1332 default:
1333 UNREACHABLE();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001334 }
1335 SetFlag(kUseGVN);
1336 }
1337
1338 virtual void PrintDataTo(StringStream* stream) const;
1339
1340 virtual HType CalculateInferredType() const;
1341
1342 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1343
1344 virtual Representation RequiredInputRepresentation(int index) const {
1345 switch (op_) {
1346 case kMathFloor:
1347 case kMathRound:
1348 case kMathCeil:
1349 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001350 case kMathPowHalf:
1351 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001352 case kMathSin:
1353 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001354 return Representation::Double();
1355 break;
1356 case kMathAbs:
1357 return representation();
1358 break;
1359 default:
1360 return Representation::None();
1361 }
1362 }
1363
1364 virtual HValue* Canonicalize() {
1365 // If the input is integer32 then we replace the floor instruction
1366 // with its inputs. This happens before the representation changes are
1367 // introduced.
1368 if (op() == kMathFloor) {
1369 if (value()->representation().IsInteger32()) return value();
1370 }
1371 return this;
1372 }
1373
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001374 BuiltinFunctionId op() const { return op_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001375 const char* OpName() const;
1376
1377 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
1378
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001379 protected:
1380 virtual bool DataEquals(HValue* other) const {
1381 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
1382 return op_ == b->op();
1383 }
1384
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001385 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001386 BuiltinFunctionId op_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001387};
1388
1389
1390class HLoadElements: public HUnaryOperation {
1391 public:
1392 explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1393 set_representation(Representation::Tagged());
1394 SetFlag(kUseGVN);
1395 SetFlag(kDependsOnMaps);
1396 }
1397
1398 virtual Representation RequiredInputRepresentation(int index) const {
1399 return Representation::Tagged();
1400 }
1401
1402 DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001403
1404 protected:
1405 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001406};
1407
1408
1409class HCheckMap: public HUnaryOperation {
1410 public:
1411 HCheckMap(HValue* value, Handle<Map> map)
1412 : HUnaryOperation(value), map_(map) {
1413 set_representation(Representation::Tagged());
1414 SetFlag(kUseGVN);
1415 SetFlag(kDependsOnMaps);
1416 }
1417
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001418 virtual bool IsCheckInstruction() const { return true; }
1419
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001420 virtual Representation RequiredInputRepresentation(int index) const {
1421 return Representation::Tagged();
1422 }
1423 virtual void PrintDataTo(StringStream* stream) const;
1424 virtual HType CalculateInferredType() const;
1425
1426#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001427 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001428#endif
1429
1430 Handle<Map> map() const { return map_; }
1431
1432 DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
1433
1434 protected:
1435 virtual bool DataEquals(HValue* other) const {
1436 HCheckMap* b = HCheckMap::cast(other);
1437 return map_.is_identical_to(b->map());
1438 }
1439
1440 private:
1441 Handle<Map> map_;
1442};
1443
1444
1445class HCheckFunction: public HUnaryOperation {
1446 public:
1447 HCheckFunction(HValue* value, Handle<JSFunction> function)
1448 : HUnaryOperation(value), target_(function) {
1449 set_representation(Representation::Tagged());
1450 SetFlag(kUseGVN);
1451 }
1452
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001453 virtual bool IsCheckInstruction() const { return true; }
1454
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001455 virtual Representation RequiredInputRepresentation(int index) const {
1456 return Representation::Tagged();
1457 }
1458 virtual void PrintDataTo(StringStream* stream) const;
1459 virtual HType CalculateInferredType() const;
1460
1461#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001462 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001463#endif
1464
1465 Handle<JSFunction> target() const { return target_; }
1466
1467 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
1468
1469 protected:
1470 virtual bool DataEquals(HValue* other) const {
1471 HCheckFunction* b = HCheckFunction::cast(other);
1472 return target_.is_identical_to(b->target());
1473 }
1474
1475 private:
1476 Handle<JSFunction> target_;
1477};
1478
1479
1480class HCheckInstanceType: public HUnaryOperation {
1481 public:
1482 // Check that the instance type is in the range [first, last] where
1483 // both first and last are included.
1484 HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
1485 : HUnaryOperation(value), first_(first), last_(last) {
1486 ASSERT(first <= last);
1487 set_representation(Representation::Tagged());
1488 SetFlag(kUseGVN);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001489 if ((FIRST_STRING_TYPE < first && last <= LAST_STRING_TYPE) ||
1490 (FIRST_STRING_TYPE <= first && last < LAST_STRING_TYPE)) {
1491 // A particular string instance type can change because of GC or
1492 // externalization, but the value still remains a string.
1493 SetFlag(kDependsOnMaps);
1494 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001495 }
1496
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001497 virtual bool IsCheckInstruction() const { return true; }
1498
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001499 virtual Representation RequiredInputRepresentation(int index) const {
1500 return Representation::Tagged();
1501 }
1502
1503#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001504 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001505#endif
1506
1507 static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
1508
1509 InstanceType first() const { return first_; }
1510 InstanceType last() const { return last_; }
1511
1512 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")
1513
1514 protected:
1515 // TODO(ager): It could be nice to allow the ommision of instance
1516 // type checks if we have already performed an instance type check
1517 // with a larger range.
1518 virtual bool DataEquals(HValue* other) const {
1519 HCheckInstanceType* b = HCheckInstanceType::cast(other);
1520 return (first_ == b->first()) && (last_ == b->last());
1521 }
1522
1523 private:
1524 InstanceType first_;
1525 InstanceType last_;
1526};
1527
1528
1529class HCheckNonSmi: public HUnaryOperation {
1530 public:
1531 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
1532 set_representation(Representation::Tagged());
1533 SetFlag(kUseGVN);
1534 }
1535
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001536 virtual bool IsCheckInstruction() const { return true; }
1537
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001538 virtual Representation RequiredInputRepresentation(int index) const {
1539 return Representation::Tagged();
1540 }
1541
1542 virtual HType CalculateInferredType() const;
1543
1544#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001545 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001546#endif
1547
1548 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001549
1550 protected:
1551 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001552};
1553
1554
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001555class HCheckPrototypeMaps: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001556 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001557 HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
1558 : prototype_(prototype), holder_(holder) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001559 SetFlag(kUseGVN);
1560 SetFlag(kDependsOnMaps);
1561 }
1562
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001563 virtual bool IsCheckInstruction() const { return true; }
1564
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001565#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001566 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001567#endif
1568
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001569 Handle<JSObject> prototype() const { return prototype_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001570 Handle<JSObject> holder() const { return holder_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001571
1572 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
1573
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001574 virtual intptr_t Hashcode() const {
1575 ASSERT(!Heap::IsAllocationAllowed());
1576 intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
1577 hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
1578 return hash;
1579 }
1580
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001581 protected:
1582 virtual bool DataEquals(HValue* other) const {
1583 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001584 return prototype_.is_identical_to(b->prototype()) &&
1585 holder_.is_identical_to(b->holder());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001586 }
1587
1588 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001589 Handle<JSObject> prototype_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001590 Handle<JSObject> holder_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001591};
1592
1593
1594class HCheckSmi: public HUnaryOperation {
1595 public:
1596 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
1597 set_representation(Representation::Tagged());
1598 SetFlag(kUseGVN);
1599 }
1600
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001601 virtual bool IsCheckInstruction() const { return true; }
1602
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001603 virtual Representation RequiredInputRepresentation(int index) const {
1604 return Representation::Tagged();
1605 }
1606 virtual HType CalculateInferredType() const;
1607
1608#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001609 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001610#endif
1611
1612 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001613
1614 protected:
1615 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001616};
1617
1618
1619class HPhi: public HValue {
1620 public:
1621 explicit HPhi(int merged_index)
1622 : inputs_(2),
1623 merged_index_(merged_index),
1624 phi_id_(-1) {
1625 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1626 non_phi_uses_[i] = 0;
1627 indirect_uses_[i] = 0;
1628 }
1629 ASSERT(merged_index >= 0);
1630 set_representation(Representation::Tagged());
1631 SetFlag(kFlexibleRepresentation);
1632 }
1633
1634 virtual Representation InferredRepresentation() const {
1635 bool double_occurred = false;
1636 bool int32_occurred = false;
1637 for (int i = 0; i < OperandCount(); ++i) {
1638 HValue* value = OperandAt(i);
1639 if (value->representation().IsDouble()) double_occurred = true;
1640 if (value->representation().IsInteger32()) int32_occurred = true;
1641 if (value->representation().IsTagged()) return Representation::Tagged();
1642 }
1643
1644 if (double_occurred) return Representation::Double();
1645 if (int32_occurred) return Representation::Integer32();
1646 return Representation::None();
1647 }
1648
1649 virtual Range* InferRange();
1650 virtual Representation RequiredInputRepresentation(int index) const {
1651 return representation();
1652 }
1653 virtual HType CalculateInferredType() const;
1654 virtual int OperandCount() const { return inputs_.length(); }
1655 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
1656 HValue* GetRedundantReplacement() const;
1657 void AddInput(HValue* value);
1658
1659 bool HasReceiverOperand();
1660
1661 int merged_index() const { return merged_index_; }
1662
1663 virtual const char* Mnemonic() const { return "phi"; }
1664
1665 virtual void PrintTo(StringStream* stream) const;
1666
1667#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001668 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001669#endif
1670
1671 DECLARE_INSTRUCTION(Phi)
1672
1673 void InitRealUses(int id);
1674 void AddNonPhiUsesFrom(HPhi* other);
1675 void AddIndirectUsesTo(int* use_count);
1676
1677 int tagged_non_phi_uses() const {
1678 return non_phi_uses_[Representation::kTagged];
1679 }
1680 int int32_non_phi_uses() const {
1681 return non_phi_uses_[Representation::kInteger32];
1682 }
1683 int double_non_phi_uses() const {
1684 return non_phi_uses_[Representation::kDouble];
1685 }
1686 int tagged_indirect_uses() const {
1687 return indirect_uses_[Representation::kTagged];
1688 }
1689 int int32_indirect_uses() const {
1690 return indirect_uses_[Representation::kInteger32];
1691 }
1692 int double_indirect_uses() const {
1693 return indirect_uses_[Representation::kDouble];
1694 }
1695 int phi_id() { return phi_id_; }
1696
1697 protected:
1698 virtual void DeleteFromGraph();
1699 virtual void InternalSetOperandAt(int index, HValue* value) {
1700 inputs_[index] = value;
1701 }
1702
1703 private:
1704 ZoneList<HValue*> inputs_;
1705 int merged_index_;
1706
1707 int non_phi_uses_[Representation::kNumRepresentations];
1708 int indirect_uses_[Representation::kNumRepresentations];
1709 int phi_id_;
1710};
1711
1712
1713class HArgumentsObject: public HInstruction {
1714 public:
1715 HArgumentsObject() {
1716 set_representation(Representation::Tagged());
1717 SetFlag(kIsArguments);
1718 }
1719
1720 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
1721};
1722
1723
1724class HConstant: public HInstruction {
1725 public:
1726 HConstant(Handle<Object> handle, Representation r);
1727
1728 Handle<Object> handle() const { return handle_; }
1729
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001730 bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
1731
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001732 virtual bool EmitAtUses() const { return !representation().IsDouble(); }
1733 virtual void PrintDataTo(StringStream* stream) const;
1734 virtual HType CalculateInferredType() const;
1735 bool IsInteger() const { return handle_->IsSmi(); }
1736 HConstant* CopyToRepresentation(Representation r) const;
1737 HConstant* CopyToTruncatedInt32() const;
1738 bool HasInteger32Value() const { return has_int32_value_; }
1739 int32_t Integer32Value() const {
1740 ASSERT(HasInteger32Value());
1741 return int32_value_;
1742 }
1743 bool HasDoubleValue() const { return has_double_value_; }
1744 double DoubleValue() const {
1745 ASSERT(HasDoubleValue());
1746 return double_value_;
1747 }
1748 bool HasStringValue() const { return handle_->IsString(); }
1749
1750 virtual intptr_t Hashcode() const {
1751 ASSERT(!Heap::allow_allocation(false));
1752 return reinterpret_cast<intptr_t>(*handle());
1753 }
1754
1755#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001756 virtual void Verify() { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001757#endif
1758
1759 DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
1760
1761 protected:
1762 virtual Range* InferRange();
1763
1764 virtual bool DataEquals(HValue* other) const {
1765 HConstant* other_constant = HConstant::cast(other);
1766 return handle().is_identical_to(other_constant->handle());
1767 }
1768
1769 private:
1770 Handle<Object> handle_;
1771 HType constant_type_;
1772
1773 // The following two values represent the int32 and the double value of the
1774 // given constant if there is a lossless conversion between the constant
1775 // and the specific representation.
1776 bool has_int32_value_;
1777 int32_t int32_value_;
1778 bool has_double_value_;
1779 double double_value_;
1780};
1781
1782
1783class HBinaryOperation: public HInstruction {
1784 public:
1785 HBinaryOperation(HValue* left, HValue* right) {
1786 ASSERT(left != NULL && right != NULL);
1787 SetOperandAt(0, left);
1788 SetOperandAt(1, right);
1789 }
1790
1791 HValue* left() const { return OperandAt(0); }
1792 HValue* right() const { return OperandAt(1); }
1793
1794 // TODO(kasperl): Move these helpers to the IA-32 Lithium
1795 // instruction sequence builder.
1796 HValue* LeastConstantOperand() const {
1797 if (IsCommutative() && left()->IsConstant()) return right();
1798 return left();
1799 }
1800 HValue* MostConstantOperand() const {
1801 if (IsCommutative() && left()->IsConstant()) return left();
1802 return right();
1803 }
1804
1805 virtual bool IsCommutative() const { return false; }
1806
1807 virtual void PrintDataTo(StringStream* stream) const;
1808 virtual int OperandCount() const { return operands_.length(); }
1809 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1810
1811 DECLARE_INSTRUCTION(BinaryOperation)
1812
1813 protected:
1814 virtual void InternalSetOperandAt(int index, HValue* value) {
1815 operands_[index] = value;
1816 }
1817
1818 private:
1819 HOperandVector<2> operands_;
1820};
1821
1822
1823class HApplyArguments: public HInstruction {
1824 public:
1825 HApplyArguments(HValue* function,
1826 HValue* receiver,
1827 HValue* length,
1828 HValue* elements) {
1829 set_representation(Representation::Tagged());
1830 SetOperandAt(0, function);
1831 SetOperandAt(1, receiver);
1832 SetOperandAt(2, length);
1833 SetOperandAt(3, elements);
1834 }
1835
1836 virtual Representation RequiredInputRepresentation(int index) const {
1837 // The length is untagged, all other inputs are tagged.
1838 return (index == 2)
1839 ? Representation::Integer32()
1840 : Representation::Tagged();
1841 }
1842
1843 HValue* function() const { return OperandAt(0); }
1844 HValue* receiver() const { return OperandAt(1); }
1845 HValue* length() const { return OperandAt(2); }
1846 HValue* elements() const { return OperandAt(3); }
1847
1848 virtual int OperandCount() const { return operands_.length(); }
1849 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1850
1851 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
1852
1853
1854
1855 protected:
1856 virtual void InternalSetOperandAt(int index, HValue* value) {
1857 operands_[index] = value;
1858 }
1859
1860 private:
1861 HOperandVector<4> operands_;
1862};
1863
1864
1865class HArgumentsElements: public HInstruction {
1866 public:
1867 HArgumentsElements() {
1868 // The value produced by this instruction is a pointer into the stack
1869 // that looks as if it was a smi because of alignment.
1870 set_representation(Representation::Tagged());
1871 SetFlag(kUseGVN);
1872 }
1873
1874 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001875
1876 protected:
1877 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001878};
1879
1880
1881class HArgumentsLength: public HUnaryOperation {
1882 public:
1883 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
1884 set_representation(Representation::Integer32());
1885 SetFlag(kUseGVN);
1886 }
1887
1888 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001889
1890 protected:
1891 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001892};
1893
1894
1895class HAccessArgumentsAt: public HInstruction {
1896 public:
1897 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
1898 set_representation(Representation::Tagged());
1899 SetFlag(kUseGVN);
1900 SetOperandAt(0, arguments);
1901 SetOperandAt(1, length);
1902 SetOperandAt(2, index);
1903 }
1904
1905 virtual void PrintDataTo(StringStream* stream) const;
1906
1907 virtual Representation RequiredInputRepresentation(int index) const {
1908 // The arguments elements is considered tagged.
1909 return index == 0
1910 ? Representation::Tagged()
1911 : Representation::Integer32();
1912 }
1913
1914 HValue* arguments() const { return operands_[0]; }
1915 HValue* length() const { return operands_[1]; }
1916 HValue* index() const { return operands_[2]; }
1917
1918 virtual int OperandCount() const { return operands_.length(); }
1919 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1920
1921 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
1922
1923 protected:
1924 virtual void InternalSetOperandAt(int index, HValue* value) {
1925 operands_[index] = value;
1926 }
1927
ager@chromium.org378b34e2011-01-28 08:04:38 +00001928 virtual bool DataEquals(HValue* other) const { return true; }
1929
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001930 private:
1931 HOperandVector<3> operands_;
1932};
1933
1934
1935class HBoundsCheck: public HBinaryOperation {
1936 public:
1937 HBoundsCheck(HValue* index, HValue* length)
1938 : HBinaryOperation(index, length) {
1939 SetFlag(kUseGVN);
1940 }
1941
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001942 virtual bool IsCheckInstruction() const { return true; }
1943
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001944 virtual Representation RequiredInputRepresentation(int index) const {
1945 return Representation::Integer32();
1946 }
1947
1948#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001949 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001950#endif
1951
1952 HValue* index() const { return left(); }
1953 HValue* length() const { return right(); }
1954
1955 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001956
1957 protected:
1958 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001959};
1960
1961
1962class HBitwiseBinaryOperation: public HBinaryOperation {
1963 public:
1964 HBitwiseBinaryOperation(HValue* left, HValue* right)
1965 : HBinaryOperation(left, right) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001966 set_representation(Representation::Tagged());
1967 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00001968 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001969 }
1970
1971 virtual Representation RequiredInputRepresentation(int index) const {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001972 return representation();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001973 }
1974
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001975 virtual void RepresentationChanged(Representation to) {
1976 if (!to.IsTagged()) {
1977 ASSERT(to.IsInteger32());
ager@chromium.org378b34e2011-01-28 08:04:38 +00001978 ClearAllSideEffects();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001979 SetFlag(kTruncatingToInt32);
1980 SetFlag(kUseGVN);
1981 }
1982 }
1983
1984 HType CalculateInferredType() const;
1985
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001986 DECLARE_INSTRUCTION(BitwiseBinaryOperation)
1987};
1988
1989
1990class HArithmeticBinaryOperation: public HBinaryOperation {
1991 public:
1992 HArithmeticBinaryOperation(HValue* left, HValue* right)
1993 : HBinaryOperation(left, right) {
1994 set_representation(Representation::Tagged());
1995 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00001996 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001997 }
1998
1999 virtual void RepresentationChanged(Representation to) {
2000 if (!to.IsTagged()) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002001 ClearAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002002 SetFlag(kUseGVN);
2003 }
2004 }
2005
2006 virtual HType CalculateInferredType() const;
2007 virtual Representation RequiredInputRepresentation(int index) const {
2008 return representation();
2009 }
2010 virtual Representation InferredRepresentation() const {
2011 if (left()->representation().Equals(right()->representation())) {
2012 return left()->representation();
2013 }
2014 return HValue::InferredRepresentation();
2015 }
2016
2017 DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
2018};
2019
2020
2021class HCompare: public HBinaryOperation {
2022 public:
2023 HCompare(HValue* left, HValue* right, Token::Value token)
2024 : HBinaryOperation(left, right), token_(token) {
2025 ASSERT(Token::IsCompareOp(token));
2026 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002027 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002028 }
2029
2030 void SetInputRepresentation(Representation r);
2031 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2032 virtual Representation RequiredInputRepresentation(int index) const {
2033 return input_representation_;
2034 }
2035 Representation GetInputRepresentation() const {
2036 return input_representation_;
2037 }
2038 Token::Value token() const { return token_; }
2039 virtual void PrintDataTo(StringStream* stream) const;
2040
2041 virtual HType CalculateInferredType() const;
2042
2043 virtual intptr_t Hashcode() const {
2044 return HValue::Hashcode() * 7 + token_;
2045 }
2046
2047 DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
2048
2049 protected:
2050 virtual bool DataEquals(HValue* other) const {
2051 HCompare* comp = HCompare::cast(other);
2052 return token_ == comp->token();
2053 }
2054
2055 private:
2056 Representation input_representation_;
2057 Token::Value token_;
2058};
2059
2060
2061class HCompareJSObjectEq: public HBinaryOperation {
2062 public:
2063 HCompareJSObjectEq(HValue* left, HValue* right)
2064 : HBinaryOperation(left, right) {
2065 set_representation(Representation::Tagged());
2066 SetFlag(kUseGVN);
2067 }
2068
2069 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2070 virtual Representation RequiredInputRepresentation(int index) const {
2071 return Representation::Tagged();
2072 }
2073 virtual HType CalculateInferredType() const;
2074
2075 DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002076
2077 protected:
2078 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002079};
2080
2081
2082class HUnaryPredicate: public HUnaryOperation {
2083 public:
2084 explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
2085 set_representation(Representation::Tagged());
2086 SetFlag(kUseGVN);
2087 }
2088 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2089 virtual Representation RequiredInputRepresentation(int index) const {
2090 return Representation::Tagged();
2091 }
2092 virtual HType CalculateInferredType() const;
2093};
2094
2095
2096class HIsNull: public HUnaryPredicate {
2097 public:
2098 HIsNull(HValue* value, bool is_strict)
2099 : HUnaryPredicate(value), is_strict_(is_strict) { }
2100
2101 bool is_strict() const { return is_strict_; }
2102
2103 DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
2104
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002105 protected:
2106 virtual bool DataEquals(HValue* other) const {
2107 HIsNull* b = HIsNull::cast(other);
2108 return is_strict_ == b->is_strict();
2109 }
2110
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002111 private:
2112 bool is_strict_;
2113};
2114
2115
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002116class HIsObject: public HUnaryPredicate {
2117 public:
2118 explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }
2119
2120 DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002121
2122 protected:
2123 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002124};
2125
2126
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002127class HIsSmi: public HUnaryPredicate {
2128 public:
2129 explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
2130
2131 DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002132
2133 protected:
2134 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002135};
2136
2137
2138class HHasInstanceType: public HUnaryPredicate {
2139 public:
2140 HHasInstanceType(HValue* value, InstanceType type)
2141 : HUnaryPredicate(value), from_(type), to_(type) { }
2142 HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
2143 : HUnaryPredicate(value), from_(from), to_(to) {
2144 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
2145 }
2146
2147 InstanceType from() { return from_; }
2148 InstanceType to() { return to_; }
2149
2150 virtual void PrintDataTo(StringStream* stream) const;
2151
2152 DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
2153
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002154 protected:
2155 virtual bool DataEquals(HValue* other) const {
2156 HHasInstanceType* b = HHasInstanceType::cast(other);
2157 return (from_ == b->from()) && (to_ == b->to());
2158 }
2159
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002160 private:
2161 InstanceType from_;
2162 InstanceType to_; // Inclusive range, not all combinations work.
2163};
2164
2165
2166class HHasCachedArrayIndex: public HUnaryPredicate {
2167 public:
2168 explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
2169
2170 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002171
2172 protected:
2173 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002174};
2175
2176
2177class HClassOfTest: public HUnaryPredicate {
2178 public:
2179 HClassOfTest(HValue* value, Handle<String> class_name)
2180 : HUnaryPredicate(value), class_name_(class_name) { }
2181
2182 DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
2183
2184 virtual void PrintDataTo(StringStream* stream) const;
2185
2186 Handle<String> class_name() const { return class_name_; }
2187
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002188 protected:
2189 virtual bool DataEquals(HValue* other) const {
2190 HClassOfTest* b = HClassOfTest::cast(other);
2191 return class_name_.is_identical_to(b->class_name_);
2192 }
2193
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002194 private:
2195 Handle<String> class_name_;
2196};
2197
2198
2199class HTypeofIs: public HUnaryPredicate {
2200 public:
2201 HTypeofIs(HValue* value, Handle<String> type_literal)
2202 : HUnaryPredicate(value), type_literal_(type_literal) { }
2203
2204 Handle<String> type_literal() { return type_literal_; }
2205 virtual void PrintDataTo(StringStream* stream) const;
2206
2207 DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
2208
2209 protected:
2210 virtual bool DataEquals(HValue* other) const {
2211 HTypeofIs* b = HTypeofIs::cast(other);
2212 return type_literal_.is_identical_to(b->type_literal_);
2213 }
2214
2215 private:
2216 Handle<String> type_literal_;
2217};
2218
2219
2220class HInstanceOf: public HBinaryOperation {
2221 public:
2222 HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
2223 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002224 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002225 }
2226
2227 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2228
2229 virtual Representation RequiredInputRepresentation(int index) const {
2230 return Representation::Tagged();
2231 }
2232
2233 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
2234};
2235
2236
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002237class HInstanceOfKnownGlobal: public HUnaryOperation {
2238 public:
2239 HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right)
2240 : HUnaryOperation(left), function_(right) {
2241 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002242 SetAllSideEffects();
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002243 }
2244
2245 Handle<JSFunction> function() { return function_; }
2246
2247 virtual Representation RequiredInputRepresentation(int index) const {
2248 return Representation::Tagged();
2249 }
2250
2251 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
2252 "instance_of_known_global")
2253
2254 private:
2255 Handle<JSFunction> function_;
2256};
2257
2258
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002259class HPower: public HBinaryOperation {
2260 public:
2261 HPower(HValue* left, HValue* right)
2262 : HBinaryOperation(left, right) {
2263 set_representation(Representation::Double());
2264 SetFlag(kUseGVN);
2265 }
2266
2267 virtual Representation RequiredInputRepresentation(int index) const {
2268 return (index == 1) ? Representation::None() : Representation::Double();
2269 }
2270
2271 DECLARE_CONCRETE_INSTRUCTION(Power, "power")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002272
2273 protected:
2274 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002275};
2276
2277
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002278class HAdd: public HArithmeticBinaryOperation {
2279 public:
2280 HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2281 SetFlag(kCanOverflow);
2282 }
2283
2284 // Add is only commutative if two integer values are added and not if two
2285 // tagged values are added (because it might be a String concatenation).
2286 virtual bool IsCommutative() const {
2287 return !representation().IsTagged();
2288 }
2289
2290 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2291
2292 virtual HType CalculateInferredType() const;
2293
2294 DECLARE_CONCRETE_INSTRUCTION(Add, "add")
2295
2296 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002297 virtual bool DataEquals(HValue* other) const { return true; }
2298
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002299 virtual Range* InferRange();
2300};
2301
2302
2303class HSub: public HArithmeticBinaryOperation {
2304 public:
2305 HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2306 SetFlag(kCanOverflow);
2307 }
2308
2309 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2310
2311 DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
2312
2313 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002314 virtual bool DataEquals(HValue* other) const { return true; }
2315
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002316 virtual Range* InferRange();
2317};
2318
2319
2320class HMul: public HArithmeticBinaryOperation {
2321 public:
2322 HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2323 SetFlag(kCanOverflow);
2324 }
2325
2326 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2327
2328 // Only commutative if it is certain that not two objects are multiplicated.
2329 virtual bool IsCommutative() const {
2330 return !representation().IsTagged();
2331 }
2332
2333 DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
2334
2335 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002336 virtual bool DataEquals(HValue* other) const { return true; }
2337
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002338 virtual Range* InferRange();
2339};
2340
2341
2342class HMod: public HArithmeticBinaryOperation {
2343 public:
2344 HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2345 SetFlag(kCanBeDivByZero);
2346 }
2347
2348 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2349
2350 DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
2351
2352 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002353 virtual bool DataEquals(HValue* other) const { return true; }
2354
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002355 virtual Range* InferRange();
2356};
2357
2358
2359class HDiv: public HArithmeticBinaryOperation {
2360 public:
2361 HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2362 SetFlag(kCanBeDivByZero);
2363 SetFlag(kCanOverflow);
2364 }
2365
2366 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2367
2368 DECLARE_CONCRETE_INSTRUCTION(Div, "div")
2369
2370 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002371 virtual bool DataEquals(HValue* other) const { return true; }
2372
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002373 virtual Range* InferRange();
2374};
2375
2376
2377class HBitAnd: public HBitwiseBinaryOperation {
2378 public:
2379 HBitAnd(HValue* left, HValue* right)
2380 : HBitwiseBinaryOperation(left, right) { }
2381
2382 virtual bool IsCommutative() const { return true; }
2383 virtual HType CalculateInferredType() const;
2384
2385 DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
2386
2387 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002388 virtual bool DataEquals(HValue* other) const { return true; }
2389
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002390 virtual Range* InferRange();
2391};
2392
2393
2394class HBitXor: public HBitwiseBinaryOperation {
2395 public:
2396 HBitXor(HValue* left, HValue* right)
2397 : HBitwiseBinaryOperation(left, right) { }
2398
2399 virtual bool IsCommutative() const { return true; }
2400 virtual HType CalculateInferredType() const;
2401
2402 DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002403
2404 protected:
2405 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002406};
2407
2408
2409class HBitOr: public HBitwiseBinaryOperation {
2410 public:
2411 HBitOr(HValue* left, HValue* right)
2412 : HBitwiseBinaryOperation(left, right) { }
2413
2414 virtual bool IsCommutative() const { return true; }
2415 virtual HType CalculateInferredType() const;
2416
2417 DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
2418
2419 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002420 virtual bool DataEquals(HValue* other) const { return true; }
2421
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002422 virtual Range* InferRange();
2423};
2424
2425
2426class HShl: public HBitwiseBinaryOperation {
2427 public:
2428 HShl(HValue* left, HValue* right)
2429 : HBitwiseBinaryOperation(left, right) { }
2430
2431 virtual Range* InferRange();
2432 virtual HType CalculateInferredType() const;
2433
2434 DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002435
2436 protected:
2437 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002438};
2439
2440
2441class HShr: public HBitwiseBinaryOperation {
2442 public:
2443 HShr(HValue* left, HValue* right)
2444 : HBitwiseBinaryOperation(left, right) { }
2445
2446 virtual HType CalculateInferredType() const;
2447
2448 DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002449
2450 protected:
2451 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002452};
2453
2454
2455class HSar: public HBitwiseBinaryOperation {
2456 public:
2457 HSar(HValue* left, HValue* right)
2458 : HBitwiseBinaryOperation(left, right) { }
2459
2460 virtual Range* InferRange();
2461 virtual HType CalculateInferredType() const;
2462
2463 DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002464
2465 protected:
2466 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002467};
2468
2469
2470class HOsrEntry: public HInstruction {
2471 public:
2472 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
2473 SetFlag(kChangesOsrEntries);
2474 }
2475
2476 int ast_id() const { return ast_id_; }
2477
2478 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
2479
2480 private:
2481 int ast_id_;
2482};
2483
2484
2485class HParameter: public HInstruction {
2486 public:
2487 explicit HParameter(unsigned index) : index_(index) {
2488 set_representation(Representation::Tagged());
2489 }
2490
2491 unsigned index() const { return index_; }
2492
2493 virtual void PrintDataTo(StringStream* stream) const;
2494
2495 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2496
2497 private:
2498 unsigned index_;
2499};
2500
2501
2502class HCallStub: public HInstruction {
2503 public:
2504 HCallStub(CodeStub::Major major_key, int argument_count)
2505 : major_key_(major_key),
2506 argument_count_(argument_count),
2507 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
2508 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002509 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002510 }
2511
2512 CodeStub::Major major_key() { return major_key_; }
2513 int argument_count() { return argument_count_; }
2514
2515 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
2516 transcendental_type_ = transcendental_type;
2517 }
2518 TranscendentalCache::Type transcendental_type() {
2519 return transcendental_type_;
2520 }
2521 virtual void PrintDataTo(StringStream* stream) const;
2522
2523 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
2524
2525 private:
2526 CodeStub::Major major_key_;
2527 int argument_count_;
2528 TranscendentalCache::Type transcendental_type_;
2529};
2530
2531
2532class HUnknownOSRValue: public HInstruction {
2533 public:
2534 HUnknownOSRValue() { set_representation(Representation::Tagged()); }
2535
2536 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
2537};
2538
2539
2540class HLoadGlobal: public HInstruction {
2541 public:
2542 HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
2543 : cell_(cell), check_hole_value_(check_hole_value) {
2544 set_representation(Representation::Tagged());
2545 SetFlag(kUseGVN);
2546 SetFlag(kDependsOnGlobalVars);
2547 }
2548
2549 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2550 bool check_hole_value() const { return check_hole_value_; }
2551
2552 virtual Representation RequiredInputRepresentation(int index) const {
2553 return Representation::Tagged();
2554 }
2555 virtual void PrintDataTo(StringStream* stream) const;
2556
2557 virtual intptr_t Hashcode() const {
2558 ASSERT(!Heap::allow_allocation(false));
2559 return reinterpret_cast<intptr_t>(*cell_);
2560 }
2561
2562 DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
2563
2564 protected:
2565 virtual bool DataEquals(HValue* other) const {
2566 HLoadGlobal* b = HLoadGlobal::cast(other);
2567 return cell_.is_identical_to(b->cell());
2568 }
2569
2570 private:
2571 Handle<JSGlobalPropertyCell> cell_;
2572 bool check_hole_value_;
2573};
2574
2575
2576class HStoreGlobal: public HUnaryOperation {
2577 public:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002578 HStoreGlobal(HValue* value,
2579 Handle<JSGlobalPropertyCell> cell,
2580 bool check_hole_value)
2581 : HUnaryOperation(value),
2582 cell_(cell),
2583 check_hole_value_(check_hole_value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002584 SetFlag(kChangesGlobalVars);
2585 }
2586
2587 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002588 bool check_hole_value() const { return check_hole_value_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002589
2590 virtual Representation RequiredInputRepresentation(int index) const {
2591 return Representation::Tagged();
2592 }
2593 virtual void PrintDataTo(StringStream* stream) const;
2594
2595 DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
2596
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002597 private:
2598 Handle<JSGlobalPropertyCell> cell_;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002599 bool check_hole_value_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002600};
2601
2602
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002603class HLoadContextSlot: public HInstruction {
2604 public:
2605 HLoadContextSlot(int context_chain_length , int slot_index)
2606 : context_chain_length_(context_chain_length), slot_index_(slot_index) {
2607 set_representation(Representation::Tagged());
2608 SetFlag(kUseGVN);
2609 SetFlag(kDependsOnCalls);
2610 }
2611
2612 int context_chain_length() const { return context_chain_length_; }
2613 int slot_index() const { return slot_index_; }
2614
2615 virtual void PrintDataTo(StringStream* stream) const;
2616
2617 virtual intptr_t Hashcode() const {
2618 return context_chain_length() * 29 + slot_index();
2619 }
2620
2621 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
2622
2623 protected:
2624 virtual bool DataEquals(HValue* other) const {
2625 HLoadContextSlot* b = HLoadContextSlot::cast(other);
2626 return (context_chain_length() == b->context_chain_length())
2627 && (slot_index() == b->slot_index());
2628 }
2629
2630 private:
2631 int context_chain_length_;
2632 int slot_index_;
2633};
2634
2635
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002636class HLoadNamedField: public HUnaryOperation {
2637 public:
2638 HLoadNamedField(HValue* object, bool is_in_object, int offset)
2639 : HUnaryOperation(object),
2640 is_in_object_(is_in_object),
2641 offset_(offset) {
2642 set_representation(Representation::Tagged());
2643 SetFlag(kUseGVN);
2644 if (is_in_object) {
2645 SetFlag(kDependsOnInobjectFields);
2646 } else {
2647 SetFlag(kDependsOnBackingStoreFields);
2648 }
2649 }
2650
2651 HValue* object() const { return OperandAt(0); }
2652 bool is_in_object() const { return is_in_object_; }
2653 int offset() const { return offset_; }
2654
2655 virtual Representation RequiredInputRepresentation(int index) const {
2656 return Representation::Tagged();
2657 }
2658 virtual void PrintDataTo(StringStream* stream) const;
2659
2660 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
2661
2662 protected:
2663 virtual bool DataEquals(HValue* other) const {
2664 HLoadNamedField* b = HLoadNamedField::cast(other);
2665 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
2666 }
2667
2668 private:
2669 bool is_in_object_;
2670 int offset_;
2671};
2672
2673
2674class HLoadNamedGeneric: public HUnaryOperation {
2675 public:
2676 HLoadNamedGeneric(HValue* object, Handle<Object> name)
2677 : HUnaryOperation(object), name_(name) {
2678 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002679 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002680 }
2681
2682 HValue* object() const { return OperandAt(0); }
2683 Handle<Object> name() const { return name_; }
2684
2685 virtual Representation RequiredInputRepresentation(int index) const {
2686 return Representation::Tagged();
2687 }
2688
2689 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
2690
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002691 private:
2692 Handle<Object> name_;
2693};
2694
2695
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002696class HLoadFunctionPrototype: public HUnaryOperation {
2697 public:
2698 explicit HLoadFunctionPrototype(HValue* function)
2699 : HUnaryOperation(function) {
2700 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002701 SetFlag(kUseGVN);
2702 SetFlag(kDependsOnCalls);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002703 }
2704
2705 HValue* function() const { return OperandAt(0); }
2706
2707 virtual Representation RequiredInputRepresentation(int index) const {
2708 return Representation::Tagged();
2709 }
2710
2711 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
2712
2713 protected:
2714 virtual bool DataEquals(HValue* other) const { return true; }
2715};
2716
2717
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002718class HLoadKeyed: public HBinaryOperation {
2719 public:
2720 HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
2721 set_representation(Representation::Tagged());
2722 }
2723
2724 virtual void PrintDataTo(StringStream* stream) const;
2725
2726 virtual Representation RequiredInputRepresentation(int index) const {
2727 return Representation::Tagged();
2728 }
2729 HValue* object() const { return OperandAt(0); }
2730 HValue* key() const { return OperandAt(1); }
2731
2732 DECLARE_INSTRUCTION(LoadKeyed)
2733};
2734
2735
2736class HLoadKeyedFastElement: public HLoadKeyed {
2737 public:
2738 HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2739 SetFlag(kDependsOnArrayElements);
2740 SetFlag(kUseGVN);
2741 }
2742
2743 virtual Representation RequiredInputRepresentation(int index) const {
2744 // The key is supposed to be Integer32.
2745 return (index == 1) ? Representation::Integer32()
2746 : Representation::Tagged();
2747 }
2748
2749 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
2750 "load_keyed_fast_element")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002751
2752 protected:
2753 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002754};
2755
2756
2757class HLoadKeyedGeneric: public HLoadKeyed {
2758 public:
2759 HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002760 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002761 }
2762
2763 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
2764};
2765
2766
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002767static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
2768 return !value->type().IsSmi() &&
2769 !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
2770}
2771
2772
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002773class HStoreNamed: public HBinaryOperation {
2774 public:
2775 HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
2776 : HBinaryOperation(obj, val), name_(name) {
2777 }
2778
2779 virtual Representation RequiredInputRepresentation(int index) const {
2780 return Representation::Tagged();
2781 }
2782
2783 virtual void PrintDataTo(StringStream* stream) const;
2784
2785 HValue* object() const { return OperandAt(0); }
2786 Handle<Object> name() const { return name_; }
2787 HValue* value() const { return OperandAt(1); }
2788 void set_value(HValue* value) { SetOperandAt(1, value); }
2789
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002790 bool NeedsWriteBarrier() const {
2791 return StoringValueNeedsWriteBarrier(value());
2792 }
2793
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002794 DECLARE_INSTRUCTION(StoreNamed)
2795
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002796 private:
2797 Handle<Object> name_;
2798};
2799
2800
2801class HStoreNamedField: public HStoreNamed {
2802 public:
2803 HStoreNamedField(HValue* obj,
2804 Handle<Object> name,
2805 HValue* val,
2806 bool in_object,
2807 int offset)
2808 : HStoreNamed(obj, name, val),
2809 is_in_object_(in_object),
2810 offset_(offset) {
2811 if (is_in_object_) {
2812 SetFlag(kChangesInobjectFields);
2813 } else {
2814 SetFlag(kChangesBackingStoreFields);
2815 }
2816 }
2817
2818 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
2819
2820 virtual Representation RequiredInputRepresentation(int index) const {
2821 return Representation::Tagged();
2822 }
2823 virtual void PrintDataTo(StringStream* stream) const;
2824
2825 bool is_in_object() const { return is_in_object_; }
2826 int offset() const { return offset_; }
2827 Handle<Map> transition() const { return transition_; }
2828 void set_transition(Handle<Map> map) { transition_ = map; }
2829
2830 private:
2831 bool is_in_object_;
2832 int offset_;
2833 Handle<Map> transition_;
2834};
2835
2836
2837class HStoreNamedGeneric: public HStoreNamed {
2838 public:
2839 HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
2840 : HStoreNamed(obj, name, val) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002841 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002842 }
2843
2844 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
2845};
2846
2847
2848class HStoreKeyed: public HInstruction {
2849 public:
2850 HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
2851 SetOperandAt(0, obj);
2852 SetOperandAt(1, key);
2853 SetOperandAt(2, val);
2854 }
2855
2856 virtual void PrintDataTo(StringStream* stream) const;
2857 virtual int OperandCount() const { return operands_.length(); }
2858 virtual HValue* OperandAt(int index) const { return operands_[index]; }
2859
2860 virtual Representation RequiredInputRepresentation(int index) const {
2861 return Representation::Tagged();
2862 }
2863
2864 HValue* object() const { return OperandAt(0); }
2865 HValue* key() const { return OperandAt(1); }
2866 HValue* value() const { return OperandAt(2); }
2867
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002868 bool NeedsWriteBarrier() const {
2869 return StoringValueNeedsWriteBarrier(value());
2870 }
2871
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002872 DECLARE_INSTRUCTION(StoreKeyed)
2873
2874 protected:
2875 virtual void InternalSetOperandAt(int index, HValue* value) {
2876 operands_[index] = value;
2877 }
2878
2879 private:
2880 HOperandVector<3> operands_;
2881};
2882
2883
2884class HStoreKeyedFastElement: public HStoreKeyed {
2885 public:
2886 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
2887 : HStoreKeyed(obj, key, val) {
2888 SetFlag(kChangesArrayElements);
2889 }
2890
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002891 virtual Representation RequiredInputRepresentation(int index) const {
2892 // The key is supposed to be Integer32.
2893 return (index == 1) ? Representation::Integer32()
2894 : Representation::Tagged();
2895 }
2896
2897 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
2898 "store_keyed_fast_element")
2899};
2900
2901
2902class HStoreKeyedGeneric: public HStoreKeyed {
2903 public:
2904 HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
2905 : HStoreKeyed(obj, key, val) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002906 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002907 }
2908
2909 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
2910};
2911
2912
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002913class HStringCharCodeAt: public HBinaryOperation {
2914 public:
2915 HStringCharCodeAt(HValue* string, HValue* index)
2916 : HBinaryOperation(string, index) {
2917 set_representation(Representation::Integer32());
2918 SetFlag(kUseGVN);
2919 }
2920
2921 virtual Representation RequiredInputRepresentation(int index) const {
2922 // The index is supposed to be Integer32.
2923 return (index == 1) ? Representation::Integer32()
2924 : Representation::Tagged();
2925 }
2926
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002927 HValue* string() const { return OperandAt(0); }
2928 HValue* index() const { return OperandAt(1); }
2929
2930 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string_char_code_at")
2931
2932 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002933 virtual bool DataEquals(HValue* other) const { return true; }
2934
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002935 virtual Range* InferRange() {
2936 return new Range(0, String::kMaxUC16CharCode);
2937 }
2938};
2939
2940
2941class HStringLength: public HUnaryOperation {
2942 public:
2943 explicit HStringLength(HValue* string) : HUnaryOperation(string) {
2944 set_representation(Representation::Tagged());
2945 SetFlag(kUseGVN);
2946 }
2947
2948 virtual Representation RequiredInputRepresentation(int index) const {
2949 return Representation::Tagged();
2950 }
2951
2952 virtual HType CalculateInferredType() const {
2953 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
2954 return HType::Smi();
2955 }
2956
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002957 DECLARE_CONCRETE_INSTRUCTION(StringLength, "string_length")
2958
2959 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002960 virtual bool DataEquals(HValue* other) const { return true; }
2961
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002962 virtual Range* InferRange() {
2963 return new Range(0, String::kMaxLength);
2964 }
2965};
2966
2967
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002968class HMaterializedLiteral: public HInstruction {
2969 public:
2970 HMaterializedLiteral(int index, int depth)
2971 : literal_index_(index), depth_(depth) {
2972 set_representation(Representation::Tagged());
2973 }
2974
2975 int literal_index() const { return literal_index_; }
2976 int depth() const { return depth_; }
2977
2978 DECLARE_INSTRUCTION(MaterializedLiteral)
2979
2980 private:
2981 int literal_index_;
2982 int depth_;
2983};
2984
2985
2986class HArrayLiteral: public HMaterializedLiteral {
2987 public:
2988 HArrayLiteral(Handle<FixedArray> constant_elements,
2989 int length,
2990 int literal_index,
2991 int depth)
2992 : HMaterializedLiteral(literal_index, depth),
2993 length_(length),
2994 constant_elements_(constant_elements) {}
2995
2996 Handle<FixedArray> constant_elements() const { return constant_elements_; }
2997 int length() const { return length_; }
2998
2999 bool IsCopyOnWrite() const;
3000
3001 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
3002
3003 private:
3004 int length_;
3005 Handle<FixedArray> constant_elements_;
3006};
3007
3008
3009class HObjectLiteral: public HMaterializedLiteral {
3010 public:
3011 HObjectLiteral(Handle<FixedArray> constant_properties,
3012 bool fast_elements,
3013 int literal_index,
3014 int depth)
3015 : HMaterializedLiteral(literal_index, depth),
3016 constant_properties_(constant_properties),
3017 fast_elements_(fast_elements) {}
3018
3019 Handle<FixedArray> constant_properties() const {
3020 return constant_properties_;
3021 }
3022 bool fast_elements() const { return fast_elements_; }
3023
3024 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
3025
3026 private:
3027 Handle<FixedArray> constant_properties_;
3028 bool fast_elements_;
3029};
3030
3031
3032class HRegExpLiteral: public HMaterializedLiteral {
3033 public:
3034 HRegExpLiteral(Handle<String> pattern,
3035 Handle<String> flags,
3036 int literal_index)
3037 : HMaterializedLiteral(literal_index, 0),
3038 pattern_(pattern),
3039 flags_(flags) { }
3040
3041 Handle<String> pattern() { return pattern_; }
3042 Handle<String> flags() { return flags_; }
3043
3044 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
3045
3046 private:
3047 Handle<String> pattern_;
3048 Handle<String> flags_;
3049};
3050
3051
3052class HFunctionLiteral: public HInstruction {
3053 public:
3054 HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
3055 : shared_info_(shared), pretenure_(pretenure) {
3056 set_representation(Representation::Tagged());
3057 }
3058
3059 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
3060
3061 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
3062 bool pretenure() const { return pretenure_; }
3063
3064 private:
3065 Handle<SharedFunctionInfo> shared_info_;
3066 bool pretenure_;
3067};
3068
3069
3070class HTypeof: public HUnaryOperation {
3071 public:
3072 explicit HTypeof(HValue* value) : HUnaryOperation(value) {
3073 set_representation(Representation::Tagged());
3074 }
3075
3076 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
3077};
3078
3079
3080class HValueOf: public HUnaryOperation {
3081 public:
3082 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
3083 set_representation(Representation::Tagged());
3084 }
3085
3086 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
3087};
3088
3089
3090class HDeleteProperty: public HBinaryOperation {
3091 public:
3092 HDeleteProperty(HValue* obj, HValue* key)
3093 : HBinaryOperation(obj, key) {
3094 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00003095 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003096 }
3097
3098 virtual Representation RequiredInputRepresentation(int index) const {
3099 return Representation::Tagged();
3100 }
3101
3102 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
3103
3104 HValue* object() const { return left(); }
3105 HValue* key() const { return right(); }
3106};
3107
3108#undef DECLARE_INSTRUCTION
3109#undef DECLARE_CONCRETE_INSTRUCTION
3110
3111} } // namespace v8::internal
3112
3113#endif // V8_HYDROGEN_INSTRUCTIONS_H_