blob: f1093a004c6c340131307d8fe18ed6baf868cef1 [file] [log] [blame]
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001// Copyright 2011 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_HYDROGEN_INSTRUCTIONS_H_
29#define V8_HYDROGEN_INSTRUCTIONS_H_
30
31#include "v8.h"
32#include "code-stubs.h"
33#include "string-stream.h"
34#include "zone.h"
35
36namespace v8 {
37namespace internal {
38
39// Forward declarations.
40class HBasicBlock;
41class HEnvironment;
42class HInstruction;
43class HLoopInformation;
44class HValue;
45class LInstruction;
46class LChunkBuilder;
47
48
kasperl@chromium.orga5551262010-12-07 12:49:48 +000049#define HYDROGEN_ALL_INSTRUCTION_LIST(V) \
50 V(ArithmeticBinaryOperation) \
51 V(BinaryOperation) \
52 V(BitwiseBinaryOperation) \
53 V(Call) \
54 V(ControlInstruction) \
55 V(Instruction) \
56 V(LoadKeyed) \
57 V(MaterializedLiteral) \
58 V(Phi) \
59 V(StoreKeyed) \
60 V(StoreNamed) \
61 V(UnaryControlInstruction) \
62 V(UnaryOperation) \
63 HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
64
65
66#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000067 V(AbnormalExit) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000068 V(AccessArgumentsAt) \
69 V(Add) \
70 V(ApplyArguments) \
71 V(ArgumentsElements) \
72 V(ArgumentsLength) \
73 V(ArgumentsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000074 V(ArrayLiteral) \
75 V(BitAnd) \
76 V(BitNot) \
77 V(BitOr) \
78 V(BitXor) \
79 V(BlockEntry) \
80 V(BoundsCheck) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000081 V(CallConstantFunction) \
82 V(CallFunction) \
83 V(CallGlobal) \
84 V(CallKeyed) \
85 V(CallKnownGlobal) \
86 V(CallNamed) \
87 V(CallNew) \
88 V(CallRuntime) \
89 V(CallStub) \
90 V(Change) \
91 V(CheckFunction) \
92 V(CheckInstanceType) \
93 V(CheckMap) \
94 V(CheckNonSmi) \
95 V(CheckPrototypeMaps) \
96 V(CheckSmi) \
97 V(Compare) \
98 V(CompareJSObjectEq) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000099 V(CompareMap) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000100 V(Constant) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000101 V(Context) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000102 V(DeleteProperty) \
103 V(Deoptimize) \
104 V(Div) \
105 V(EnterInlined) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000106 V(FixedArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000107 V(FunctionLiteral) \
108 V(GlobalObject) \
109 V(GlobalReceiver) \
110 V(Goto) \
111 V(InstanceOf) \
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000112 V(InstanceOfKnownGlobal) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000113 V(IsNull) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000114 V(IsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000115 V(IsSmi) \
116 V(HasInstanceType) \
117 V(HasCachedArrayIndex) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000118 V(JSArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000119 V(ClassOfTest) \
120 V(LeaveInlined) \
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000121 V(LoadContextSlot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000122 V(LoadElements) \
ager@chromium.org378b34e2011-01-28 08:04:38 +0000123 V(LoadFunctionPrototype) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000124 V(LoadGlobal) \
125 V(LoadKeyedFastElement) \
126 V(LoadKeyedGeneric) \
127 V(LoadNamedField) \
128 V(LoadNamedGeneric) \
129 V(Mod) \
130 V(Mul) \
131 V(ObjectLiteral) \
132 V(OsrEntry) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000133 V(OuterContext) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000134 V(Parameter) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000135 V(Power) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000136 V(PushArgument) \
137 V(RegExpLiteral) \
138 V(Return) \
139 V(Sar) \
140 V(Shl) \
141 V(Shr) \
142 V(Simulate) \
143 V(StackCheck) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000144 V(StoreContextSlot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000145 V(StoreGlobal) \
146 V(StoreKeyedFastElement) \
147 V(StoreKeyedGeneric) \
148 V(StoreNamedField) \
149 V(StoreNamedGeneric) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000150 V(StringCharCodeAt) \
151 V(StringLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000152 V(Sub) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000153 V(Test) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000154 V(Throw) \
155 V(Typeof) \
156 V(TypeofIs) \
157 V(UnaryMathOperation) \
158 V(UnknownOSRValue) \
159 V(ValueOf)
160
161#define GVN_FLAG_LIST(V) \
162 V(Calls) \
163 V(InobjectFields) \
164 V(BackingStoreFields) \
165 V(ArrayElements) \
166 V(GlobalVars) \
167 V(Maps) \
168 V(ArrayLengths) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000169 V(ContextSlots) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000170 V(OsrEntries)
171
172#define DECLARE_INSTRUCTION(type) \
173 virtual bool Is##type() const { return true; } \
174 static H##type* cast(HValue* value) { \
175 ASSERT(value->Is##type()); \
176 return reinterpret_cast<H##type*>(value); \
177 } \
178 Opcode opcode() const { return HValue::k##type; }
179
180
181#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
182 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
183 virtual const char* Mnemonic() const { return mnemonic; } \
184 DECLARE_INSTRUCTION(type)
185
186
187
188template<int kSize>
189class HOperandVector : public EmbeddedVector<HValue*, kSize> {
190 public:
191 HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
192};
193
194
195class Range: public ZoneObject {
196 public:
197 Range() : lower_(kMinInt),
198 upper_(kMaxInt),
199 next_(NULL),
200 can_be_minus_zero_(false) { }
201
202 Range(int32_t lower, int32_t upper)
203 : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
204
205 bool IsInSmiRange() const {
206 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
207 }
208 void KeepOrder();
209 void Verify() const;
210 int32_t upper() const { return upper_; }
211 int32_t lower() const { return lower_; }
212 Range* next() const { return next_; }
213 Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
214 Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
215 void ClearLower() { lower_ = kMinInt; }
216 void ClearUpper() { upper_ = kMaxInt; }
217 Range* Copy() const { return new Range(lower_, upper_); }
218 bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
219 int32_t Mask() const;
220 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
221 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
222 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
223 bool CanBeNegative() const { return lower_ < 0; }
224 bool Includes(int value) const {
225 return lower_ <= value && upper_ >= value;
226 }
227
228 void Sar(int32_t value) {
229 int32_t bits = value & 0x1F;
230 lower_ = lower_ >> bits;
231 upper_ = upper_ >> bits;
232 set_can_be_minus_zero(false);
233 }
234
235 void Shl(int32_t value) {
236 int32_t bits = value & 0x1F;
237 int old_lower = lower_;
238 int old_upper = upper_;
239 lower_ = lower_ << bits;
240 upper_ = upper_ << bits;
241 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
242 upper_ = kMaxInt;
243 lower_ = kMinInt;
244 }
245 set_can_be_minus_zero(false);
246 }
247
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000248 // Adds a constant to the lower and upper bound of the range.
249 void AddConstant(int32_t value);
250
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000251 void StackUpon(Range* other) {
252 Intersect(other);
253 next_ = other;
254 }
255
256 void Intersect(Range* other) {
257 upper_ = Min(upper_, other->upper_);
258 lower_ = Max(lower_, other->lower_);
259 bool b = CanBeMinusZero() && other->CanBeMinusZero();
260 set_can_be_minus_zero(b);
261 }
262
263 void Union(Range* other) {
264 upper_ = Max(upper_, other->upper_);
265 lower_ = Min(lower_, other->lower_);
266 bool b = CanBeMinusZero() || other->CanBeMinusZero();
267 set_can_be_minus_zero(b);
268 }
269
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000270 // Compute a new result range and return true, if the operation
271 // can overflow.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000272 bool AddAndCheckOverflow(Range* other);
273 bool SubAndCheckOverflow(Range* other);
274 bool MulAndCheckOverflow(Range* other);
275
276 private:
277 int32_t lower_;
278 int32_t upper_;
279 Range* next_;
280 bool can_be_minus_zero_;
281};
282
283
284class Representation {
285 public:
286 enum Kind {
287 kNone,
288 kTagged,
289 kDouble,
290 kInteger32,
291 kNumRepresentations
292 };
293
294 Representation() : kind_(kNone) { }
295
296 static Representation None() { return Representation(kNone); }
297 static Representation Tagged() { return Representation(kTagged); }
298 static Representation Integer32() { return Representation(kInteger32); }
299 static Representation Double() { return Representation(kDouble); }
300
301 bool Equals(const Representation& other) const {
302 return kind_ == other.kind_;
303 }
304
305 Kind kind() const { return kind_; }
306 bool IsNone() const { return kind_ == kNone; }
307 bool IsTagged() const { return kind_ == kTagged; }
308 bool IsInteger32() const { return kind_ == kInteger32; }
309 bool IsDouble() const { return kind_ == kDouble; }
310 bool IsSpecialization() const {
311 return kind_ == kInteger32 || kind_ == kDouble;
312 }
313 const char* Mnemonic() const;
314
315 private:
316 explicit Representation(Kind k) : kind_(k) { }
317
318 Kind kind_;
319};
320
321
322class HType {
323 public:
324 HType() : type_(kUninitialized) { }
325
326 static HType Tagged() { return HType(kTagged); }
327 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
328 static HType TaggedNumber() { return HType(kTaggedNumber); }
329 static HType Smi() { return HType(kSmi); }
330 static HType HeapNumber() { return HType(kHeapNumber); }
331 static HType String() { return HType(kString); }
332 static HType Boolean() { return HType(kBoolean); }
333 static HType NonPrimitive() { return HType(kNonPrimitive); }
334 static HType JSArray() { return HType(kJSArray); }
335 static HType JSObject() { return HType(kJSObject); }
336 static HType Uninitialized() { return HType(kUninitialized); }
337
338 // Return the weakest (least precise) common type.
339 HType Combine(HType other) {
340 return HType(static_cast<Type>(type_ & other.type_));
341 }
342
343 bool Equals(const HType& other) {
344 return type_ == other.type_;
345 }
346
347 bool IsSubtypeOf(const HType& other) {
348 return Combine(other).Equals(other);
349 }
350
351 bool IsTagged() {
352 ASSERT(type_ != kUninitialized);
353 return ((type_ & kTagged) == kTagged);
354 }
355
356 bool IsTaggedPrimitive() {
357 ASSERT(type_ != kUninitialized);
358 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
359 }
360
361 bool IsTaggedNumber() {
362 ASSERT(type_ != kUninitialized);
363 return ((type_ & kTaggedNumber) == kTaggedNumber);
364 }
365
366 bool IsSmi() {
367 ASSERT(type_ != kUninitialized);
368 return ((type_ & kSmi) == kSmi);
369 }
370
371 bool IsHeapNumber() {
372 ASSERT(type_ != kUninitialized);
373 return ((type_ & kHeapNumber) == kHeapNumber);
374 }
375
376 bool IsString() {
377 ASSERT(type_ != kUninitialized);
378 return ((type_ & kString) == kString);
379 }
380
381 bool IsBoolean() {
382 ASSERT(type_ != kUninitialized);
383 return ((type_ & kBoolean) == kBoolean);
384 }
385
386 bool IsNonPrimitive() {
387 ASSERT(type_ != kUninitialized);
388 return ((type_ & kNonPrimitive) == kNonPrimitive);
389 }
390
391 bool IsJSArray() {
392 ASSERT(type_ != kUninitialized);
393 return ((type_ & kJSArray) == kJSArray);
394 }
395
396 bool IsJSObject() {
397 ASSERT(type_ != kUninitialized);
398 return ((type_ & kJSObject) == kJSObject);
399 }
400
401 bool IsUninitialized() {
402 return type_ == kUninitialized;
403 }
404
405 static HType TypeFromValue(Handle<Object> value);
406
407 const char* ToString();
408 const char* ToShortString();
409
410 private:
411 enum Type {
412 kTagged = 0x1, // 0000 0000 0000 0001
413 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
414 kTaggedNumber = 0xd, // 0000 0000 0000 1101
415 kSmi = 0x1d, // 0000 0000 0001 1101
416 kHeapNumber = 0x2d, // 0000 0000 0010 1101
417 kString = 0x45, // 0000 0000 0100 0101
418 kBoolean = 0x85, // 0000 0000 1000 0101
419 kNonPrimitive = 0x101, // 0000 0001 0000 0001
420 kJSObject = 0x301, // 0000 0011 0000 0001
421 kJSArray = 0x701, // 0000 0111 1000 0001
422 kUninitialized = 0x1fff // 0001 1111 1111 1111
423 };
424
425 explicit HType(Type t) : type_(t) { }
426
427 Type type_;
428};
429
430
431class HValue: public ZoneObject {
432 public:
433 static const int kNoNumber = -1;
434
435 // There must be one corresponding kDepends flag for every kChanges flag and
436 // the order of the kChanges flags must be exactly the same as of the kDepends
437 // flags.
438 enum Flag {
439 // Declare global value numbering flags.
440 #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
441 GVN_FLAG_LIST(DECLARE_DO)
442 #undef DECLARE_DO
443 kFlexibleRepresentation,
444 kUseGVN,
445 kCanOverflow,
446 kBailoutOnMinusZero,
447 kCanBeDivByZero,
448 kIsArguments,
449 kTruncatingToInt32,
450 kLastFlag = kTruncatingToInt32
451 };
452
453 STATIC_ASSERT(kLastFlag < kBitsPerInt);
454
455 static const int kChangesToDependsFlagsLeftShift = 1;
456
457 static int ChangesFlagsMask() {
458 int result = 0;
459 // Create changes mask.
460#define DECLARE_DO(type) result |= (1 << kChanges##type);
461 GVN_FLAG_LIST(DECLARE_DO)
462#undef DECLARE_DO
463 return result;
464 }
465
466 static int DependsFlagsMask() {
467 return ConvertChangesToDependsFlags(ChangesFlagsMask());
468 }
469
470 static int ConvertChangesToDependsFlags(int flags) {
471 return flags << kChangesToDependsFlagsLeftShift;
472 }
473
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000474 static HValue* cast(HValue* value) { return value; }
475
476 enum Opcode {
477 // Declare a unique enum value for each hydrogen instruction.
478 #define DECLARE_DO(type) k##type,
479 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
480 #undef DECLARE_DO
481 kMaxInstructionClass
482 };
483
484 HValue() : block_(NULL),
485 id_(kNoNumber),
486 uses_(2),
487 type_(HType::Tagged()),
488 range_(NULL),
489 flags_(0) {}
490 virtual ~HValue() {}
491
492 HBasicBlock* block() const { return block_; }
493 void SetBlock(HBasicBlock* block);
494
495 int id() const { return id_; }
496 void set_id(int id) { id_ = id; }
497
498 const ZoneList<HValue*>* uses() const { return &uses_; }
499
500 virtual bool EmitAtUses() const { return false; }
501 Representation representation() const { return representation_; }
502 void ChangeRepresentation(Representation r) {
503 // Representation was already set and is allowed to be changed.
504 ASSERT(!representation_.IsNone());
505 ASSERT(!r.IsNone());
506 ASSERT(CheckFlag(kFlexibleRepresentation));
507 RepresentationChanged(r);
508 representation_ = r;
509 }
510
511 HType type() const { return type_; }
512 void set_type(HType type) {
513 ASSERT(uses_.length() == 0);
514 type_ = type;
515 }
516
517 // An operation needs to override this function iff:
518 // 1) it can produce an int32 output.
519 // 2) the true value of its output can potentially be minus zero.
520 // The implementation must set a flag so that it bails out in the case where
521 // it would otherwise output what should be a minus zero as an int32 zero.
522 // If the operation also exists in a form that takes int32 and outputs int32
523 // then the operation should return its input value so that we can propagate
524 // back. There are two operations that need to propagate back to more than
525 // one input. They are phi and binary add. They always return NULL and
526 // expect the caller to take care of things.
527 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
528 visited->Add(id());
529 return NULL;
530 }
531
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000532 bool IsDefinedAfter(HBasicBlock* other) const;
533
534 // Operands.
535 virtual int OperandCount() const { return 0; }
536 virtual HValue* OperandAt(int index) const {
537 UNREACHABLE();
538 return NULL;
539 }
540 void SetOperandAt(int index, HValue* value);
541
542 int LookupOperandIndex(int occurrence_index, HValue* op) const;
543 bool UsesMultipleTimes(HValue* op) const;
544
545 void ReplaceAndDelete(HValue* other);
546 void ReplaceValue(HValue* other);
547 void ReplaceAtUse(HValue* use, HValue* other);
548 void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
549 bool HasNoUses() const { return uses_.is_empty(); }
550 void ClearOperands();
551 void Delete();
552
553 int flags() const { return flags_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000554 void SetFlag(Flag f) { flags_ |= (1 << f); }
555 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
556 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
557
558 void SetAllSideEffects() { flags_ |= AllSideEffects(); }
559 void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
560 bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000561
562 Range* range() const { return range_; }
563 bool HasRange() const { return range_ != NULL; }
564 void AddNewRange(Range* r);
565 void RemoveLastAddedRange();
566 void ComputeInitialRange();
567
568 // Representation helpers.
569 virtual Representation RequiredInputRepresentation(int index) const {
570 return Representation::None();
571 }
572 virtual Representation InferredRepresentation() const {
573 return representation();
574 }
575
576 // This gives the instruction an opportunity to replace itself with an
577 // instruction that does the same in some better way. To replace an
578 // instruction with a new one, first add the new instruction to the graph,
579 // then return it. Return NULL to have the instruction deleted.
580 virtual HValue* Canonicalize() { return this; }
581
582 // Declare virtual type testers.
583#define DECLARE_DO(type) virtual bool Is##type() const { return false; }
584 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
585#undef DECLARE_DO
586
587 bool Equals(HValue* other) const;
588 virtual intptr_t Hashcode() const;
589
590 // Printing support.
591 virtual void PrintTo(StringStream* stream) const = 0;
592 void PrintNameTo(StringStream* stream);
593 static void PrintTypeTo(HType type, StringStream* stream);
594
595 virtual const char* Mnemonic() const = 0;
596 virtual Opcode opcode() const = 0;
597
598 // Updated the inferred type of this instruction and returns true if
599 // it has changed.
600 bool UpdateInferredType();
601
602 virtual HType CalculateInferredType() const;
603
604 // Helper for type conversions used by normal and phi instructions.
605 void InsertInputConversion(HInstruction* previous, int index, HType type);
606
607#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000608 virtual void Verify() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000609#endif
610
611 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000612 // This function must be overridden for instructions with flag kUseGVN, to
613 // compare the non-Operand parts of the instruction.
614 virtual bool DataEquals(HValue* other) const {
615 UNREACHABLE();
616 return false;
617 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000618 virtual void RepresentationChanged(Representation to) { }
619 virtual Range* InferRange();
620 virtual void DeleteFromGraph() = 0;
621 virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
622 void clear_block() {
623 ASSERT(block_ != NULL);
624 block_ = NULL;
625 }
626
627 void set_representation(Representation r) {
628 // Representation is set-once.
629 ASSERT(representation_.IsNone() && !r.IsNone());
630 representation_ = r;
631 }
632
633 private:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000634 // A flag mask to mark an instruction as having arbitrary side effects.
635 static int AllSideEffects() {
636 return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
637 }
638
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000639 void InternalReplaceAtUse(HValue* use, HValue* other);
640 void RegisterUse(int index, HValue* new_value);
641
642 HBasicBlock* block_;
643
644 // The id of this instruction in the hydrogen graph, assigned when first
645 // added to the graph. Reflects creation order.
646 int id_;
647
648 Representation representation_;
649 ZoneList<HValue*> uses_;
650 HType type_;
651 Range* range_;
652 int flags_;
653
654 DISALLOW_COPY_AND_ASSIGN(HValue);
655};
656
657
658class HInstruction: public HValue {
659 public:
660 HInstruction* next() const { return next_; }
661 HInstruction* previous() const { return previous_; }
662
663 void PrintTo(StringStream* stream) const;
664 virtual void PrintDataTo(StringStream* stream) const {}
665
666 bool IsLinked() const { return block() != NULL; }
667 void Unlink();
668 void InsertBefore(HInstruction* next);
669 void InsertAfter(HInstruction* previous);
670
671 int position() const { return position_; }
672 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
673 void set_position(int position) { position_ = position; }
674
675 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
676
677#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000678 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000679#endif
680
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000681 // Returns whether this is some kind of deoptimizing check
682 // instruction.
683 virtual bool IsCheckInstruction() const { return false; }
684
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000685 DECLARE_INSTRUCTION(Instruction)
686
687 protected:
688 HInstruction()
689 : next_(NULL),
690 previous_(NULL),
691 position_(RelocInfo::kNoPosition) {
692 SetFlag(kDependsOnOsrEntries);
693 }
694
695 virtual void DeleteFromGraph() { Unlink(); }
696
697 private:
698 void InitializeAsFirst(HBasicBlock* block) {
699 ASSERT(!IsLinked());
700 SetBlock(block);
701 }
702
703 HInstruction* next_;
704 HInstruction* previous_;
705 int position_;
706
707 friend class HBasicBlock;
708};
709
710
711class HBlockEntry: public HInstruction {
712 public:
713 DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
714};
715
716
717class HControlInstruction: public HInstruction {
718 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000719 HControlInstruction(HBasicBlock* first, HBasicBlock* second)
720 : first_successor_(first), second_successor_(second) {
721 }
722
723 HBasicBlock* FirstSuccessor() const { return first_successor_; }
724 HBasicBlock* SecondSuccessor() const { return second_successor_; }
725
726 virtual void PrintDataTo(StringStream* stream) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000727
728 DECLARE_INSTRUCTION(ControlInstruction)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000729
730 private:
731 HBasicBlock* first_successor_;
732 HBasicBlock* second_successor_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000733};
734
735
736class HDeoptimize: public HControlInstruction {
737 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000738 HDeoptimize() : HControlInstruction(NULL, NULL) { }
739
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000740 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
741};
742
743
744class HGoto: public HControlInstruction {
745 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000746 explicit HGoto(HBasicBlock* target)
747 : HControlInstruction(target, NULL), include_stack_check_(false) {
748 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000749
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000750 void set_include_stack_check(bool include_stack_check) {
751 include_stack_check_ = include_stack_check;
752 }
753 bool include_stack_check() const { return include_stack_check_; }
754
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000755 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
756
757 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000758 bool include_stack_check_;
759};
760
761
762class HUnaryControlInstruction: public HControlInstruction {
763 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000764 explicit HUnaryControlInstruction(HValue* value,
765 HBasicBlock* true_target,
766 HBasicBlock* false_target)
767 : HControlInstruction(true_target, false_target) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000768 SetOperandAt(0, value);
769 }
770
771 virtual Representation RequiredInputRepresentation(int index) const {
772 return Representation::Tagged();
773 }
774
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000775 virtual void PrintDataTo(StringStream* stream) const;
776
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000777 HValue* value() const { return OperandAt(0); }
778 virtual int OperandCount() const { return 1; }
779 virtual HValue* OperandAt(int index) const { return operands_[index]; }
780
781 DECLARE_INSTRUCTION(UnaryControlInstruction)
782
783 protected:
784 virtual void InternalSetOperandAt(int index, HValue* value) {
785 operands_[index] = value;
786 }
787
788 private:
789 HOperandVector<1> operands_;
790};
791
792
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000793class HTest: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000794 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000795 HTest(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target)
796 : HUnaryControlInstruction(value, true_target, false_target) {
797 ASSERT(true_target != NULL && false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000798 }
799
800 virtual Representation RequiredInputRepresentation(int index) const {
801 return Representation::None();
802 }
803
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000804 DECLARE_CONCRETE_INSTRUCTION(Test, "test")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000805};
806
807
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000808class HCompareMap: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000809 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000810 HCompareMap(HValue* value,
811 Handle<Map> map,
812 HBasicBlock* true_target,
813 HBasicBlock* false_target)
814 : HUnaryControlInstruction(value, true_target, false_target),
815 map_(map) {
816 ASSERT(true_target != NULL);
817 ASSERT(false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000818 ASSERT(!map.is_null());
819 }
820
whesse@chromium.org023421e2010-12-21 12:19:12 +0000821 virtual void PrintDataTo(StringStream* stream) const;
822
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000823 Handle<Map> map() const { return map_; }
824
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000825 DECLARE_CONCRETE_INSTRUCTION(CompareMap, "compare_map")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000826
827 private:
828 Handle<Map> map_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000829};
830
831
832class HReturn: public HUnaryControlInstruction {
833 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000834 explicit HReturn(HValue* value)
835 : HUnaryControlInstruction(value, NULL, NULL) {
836 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000837
838 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
839};
840
841
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000842class HAbnormalExit: public HControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000843 public:
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000844 HAbnormalExit() : HControlInstruction(NULL, NULL) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000845
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000846 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000847};
848
849
850class HUnaryOperation: public HInstruction {
851 public:
852 explicit HUnaryOperation(HValue* value) {
853 SetOperandAt(0, value);
854 }
855
856 HValue* value() const { return OperandAt(0); }
857 virtual void PrintDataTo(StringStream* stream) const;
858 virtual int OperandCount() const { return 1; }
859 virtual HValue* OperandAt(int index) const { return operands_[index]; }
860
861 DECLARE_INSTRUCTION(UnaryOperation)
862
863 protected:
864 virtual void InternalSetOperandAt(int index, HValue* value) {
865 operands_[index] = value;
866 }
867
868 private:
869 HOperandVector<1> operands_;
870};
871
872
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000873class HThrow: public HUnaryOperation {
874 public:
875 explicit HThrow(HValue* value) : HUnaryOperation(value) {
876 SetAllSideEffects();
877 }
878
879 virtual Representation RequiredInputRepresentation(int index) const {
880 return Representation::Tagged();
881 }
882
883 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
884};
885
886
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000887class HChange: public HUnaryOperation {
888 public:
889 HChange(HValue* value,
890 Representation from,
891 Representation to)
892 : HUnaryOperation(value), from_(from), to_(to) {
893 ASSERT(!from.IsNone() && !to.IsNone());
894 ASSERT(!from.Equals(to));
895 set_representation(to);
896 SetFlag(kUseGVN);
897
898 if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
899 value->range()->IsInSmiRange()) {
900 set_type(HType::Smi());
901 }
902 }
903
904 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
905
906 Representation from() const { return from_; }
907 Representation to() const { return to_; }
908 virtual Representation RequiredInputRepresentation(int index) const {
909 return from_;
910 }
911
912 bool CanTruncateToInt32() const {
913 for (int i = 0; i < uses()->length(); ++i) {
914 if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
915 }
916 return true;
917 }
918
919 virtual void PrintDataTo(StringStream* stream) const;
920
921 DECLARE_CONCRETE_INSTRUCTION(Change,
922 CanTruncateToInt32() ? "truncate" : "change")
923
924 protected:
925 virtual bool DataEquals(HValue* other) const {
926 if (!other->IsChange()) return false;
927 HChange* change = HChange::cast(other);
928 return value() == change->value()
929 && to().Equals(change->to())
930 && CanTruncateToInt32() == change->CanTruncateToInt32();
931 }
932
933 private:
934 Representation from_;
935 Representation to_;
936};
937
938
939class HSimulate: public HInstruction {
940 public:
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000941 HSimulate(int ast_id, int pop_count, int environment_length)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000942 : ast_id_(ast_id),
943 pop_count_(pop_count),
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000944 environment_length_(environment_length),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000945 values_(2),
946 assigned_indexes_(2) {}
947 virtual ~HSimulate() {}
948
949 virtual void PrintDataTo(StringStream* stream) const;
950
951 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
952 int ast_id() const { return ast_id_; }
953 void set_ast_id(int id) {
954 ASSERT(!HasAstId());
955 ast_id_ = id;
956 }
957
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000958 int environment_length() const { return environment_length_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000959 int pop_count() const { return pop_count_; }
960 const ZoneList<HValue*>* values() const { return &values_; }
961 int GetAssignedIndexAt(int index) const {
962 ASSERT(HasAssignedIndexAt(index));
963 return assigned_indexes_[index];
964 }
965 bool HasAssignedIndexAt(int index) const {
966 return assigned_indexes_[index] != kNoIndex;
967 }
968 void AddAssignedValue(int index, HValue* value) {
969 AddValue(index, value);
970 }
971 void AddPushedValue(HValue* value) {
972 AddValue(kNoIndex, value);
973 }
974 virtual int OperandCount() const { return values_.length(); }
975 virtual HValue* OperandAt(int index) const { return values_[index]; }
976
977 DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
978
979#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000980 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000981#endif
982
983 protected:
984 virtual void InternalSetOperandAt(int index, HValue* value) {
985 values_[index] = value;
986 }
987
988 private:
989 static const int kNoIndex = -1;
990 void AddValue(int index, HValue* value) {
991 assigned_indexes_.Add(index);
992 // Resize the list of pushed values.
993 values_.Add(NULL);
994 // Set the operand through the base method in HValue to make sure that the
995 // use lists are correctly updated.
996 SetOperandAt(values_.length() - 1, value);
997 }
998 int ast_id_;
999 int pop_count_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001000 int environment_length_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001001 ZoneList<HValue*> values_;
1002 ZoneList<int> assigned_indexes_;
1003};
1004
1005
1006class HStackCheck: public HInstruction {
1007 public:
1008 HStackCheck() { }
1009
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001010 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001011};
1012
1013
1014class HEnterInlined: public HInstruction {
1015 public:
1016 HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
1017 : closure_(closure), function_(function) {
1018 }
1019
1020 virtual void PrintDataTo(StringStream* stream) const;
1021
1022 Handle<JSFunction> closure() const { return closure_; }
1023 FunctionLiteral* function() const { return function_; }
1024
1025 DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
1026
1027 private:
1028 Handle<JSFunction> closure_;
1029 FunctionLiteral* function_;
1030};
1031
1032
1033class HLeaveInlined: public HInstruction {
1034 public:
1035 HLeaveInlined() {}
1036
1037 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
1038};
1039
1040
1041class HPushArgument: public HUnaryOperation {
1042 public:
1043 explicit HPushArgument(HValue* value)
1044 : HUnaryOperation(value), argument_index_(-1) {
1045 set_representation(Representation::Tagged());
1046 }
1047
1048 virtual Representation RequiredInputRepresentation(int index) const {
1049 return Representation::Tagged();
1050 }
1051
1052 virtual void PrintDataTo(StringStream* stream) const;
1053 HValue* argument() const { return OperandAt(0); }
1054 int argument_index() const { return argument_index_; }
1055 void set_argument_index(int index) {
1056 ASSERT(argument_index_ == -1 || index == argument_index_);
1057 argument_index_ = index;
1058 }
1059
1060 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
1061
1062 private:
1063 int argument_index_;
1064};
1065
1066
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001067class HContext: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001068 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001069 HContext() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001070 set_representation(Representation::Tagged());
1071 SetFlag(kUseGVN);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001072 }
1073
1074 DECLARE_CONCRETE_INSTRUCTION(Context, "context");
1075
1076 protected:
1077 virtual bool DataEquals(HValue* other) const { return true; }
1078};
1079
1080
1081class HOuterContext: public HUnaryOperation {
1082 public:
1083 explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
1084 set_representation(Representation::Tagged());
1085 SetFlag(kUseGVN);
1086 }
1087
1088 DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer_context");
1089
1090 protected:
1091 virtual bool DataEquals(HValue* other) const { return true; }
1092};
1093
1094
1095class HGlobalObject: public HUnaryOperation {
1096 public:
1097 explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
1098 set_representation(Representation::Tagged());
1099 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001100 }
1101
1102 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001103
1104 protected:
1105 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001106};
1107
1108
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001109class HGlobalReceiver: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001110 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001111 explicit HGlobalReceiver(HValue* global_object)
1112 : HUnaryOperation(global_object) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001113 set_representation(Representation::Tagged());
1114 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001115 }
1116
1117 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001118
1119 protected:
1120 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001121};
1122
1123
1124class HCall: public HInstruction {
1125 public:
1126 // Construct a call with uninitialized arguments. The argument count
1127 // includes the receiver.
1128 explicit HCall(int count);
1129
1130 virtual HType CalculateInferredType() const { return HType::Tagged(); }
1131
1132 // TODO(3190496): This needs a cleanup. We don't want the arguments
1133 // be operands of the call instruction. This results in bad code quality.
1134 virtual int argument_count() const { return arguments_.length(); }
1135 virtual int OperandCount() const { return argument_count(); }
1136 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1137 virtual HPushArgument* PushArgumentAt(int index) const {
1138 return HPushArgument::cast(OperandAt(index));
1139 }
1140 virtual HValue* ArgumentAt(int index) const {
1141 return PushArgumentAt(index)->argument();
1142 }
1143 virtual void SetArgumentAt(int index, HPushArgument* push_argument);
1144
1145 virtual void PrintDataTo(StringStream* stream) const;
1146
1147 DECLARE_INSTRUCTION(Call)
1148
1149 protected:
1150 virtual void InternalSetOperandAt(int index, HValue* value) {
1151 arguments_[index] = value;
1152 }
1153
1154 int argument_count_;
1155 Vector<HValue*> arguments_;
1156};
1157
1158
1159class HCallConstantFunction: public HCall {
1160 public:
1161 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1162 : HCall(argument_count), function_(function) { }
1163
1164 Handle<JSFunction> function() const { return function_; }
1165 bool IsApplyFunction() const {
1166 return function_->code() == Builtins::builtin(Builtins::FunctionApply);
1167 }
1168
1169 virtual void PrintDataTo(StringStream* stream) const;
1170
1171 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
1172
1173 private:
1174 Handle<JSFunction> function_;
1175};
1176
1177
1178class HCallKeyed: public HCall {
1179 public:
1180 HCallKeyed(HValue* key, int argument_count)
1181 : HCall(argument_count + 1) {
1182 SetOperandAt(0, key);
1183 }
1184
1185 virtual Representation RequiredInputRepresentation(int index) const {
1186 return Representation::Tagged();
1187 }
1188
1189 // TODO(3190496): This is a hack to get an additional operand that
1190 // is not an argument to work with the current setup. This _needs_ a cleanup.
1191 // (see HCall)
1192 virtual void PrintDataTo(StringStream* stream) const;
1193 HValue* key() const { return OperandAt(0); }
1194 virtual int argument_count() const { return arguments_.length() - 1; }
1195 virtual int OperandCount() const { return arguments_.length(); }
1196 virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1197 virtual HPushArgument* PushArgumentAt(int index) const {
1198 return HPushArgument::cast(OperandAt(index + 1));
1199 }
1200 virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
1201 HCall::SetArgumentAt(index + 1, push_argument);
1202 }
1203
1204 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
1205};
1206
1207
1208class HCallNamed: public HCall {
1209 public:
1210 HCallNamed(Handle<String> name, int argument_count)
1211 : HCall(argument_count), name_(name) { }
1212 virtual void PrintDataTo(StringStream* stream) const;
1213
1214 Handle<String> name() const { return name_; }
1215
1216 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
1217
1218 private:
1219 Handle<String> name_;
1220};
1221
1222
1223class HCallFunction: public HCall {
1224 public:
1225 explicit HCallFunction(int argument_count) : HCall(argument_count) { }
1226
1227 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
1228};
1229
1230
1231class HCallGlobal: public HCall {
1232 public:
1233 HCallGlobal(Handle<String> name, int argument_count)
1234 : HCall(argument_count), name_(name) { }
1235
1236 virtual void PrintDataTo(StringStream* stream) const;
1237
1238 Handle<String> name() const { return name_; }
1239
1240 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
1241
1242 private:
1243 Handle<String> name_;
1244};
1245
1246
1247class HCallKnownGlobal: public HCall {
1248 public:
1249 HCallKnownGlobal(Handle<JSFunction> target,
1250 int argument_count)
1251 : HCall(argument_count), target_(target) { }
1252
1253 Handle<JSFunction> target() const { return target_; }
1254
1255 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
1256
1257 private:
1258 Handle<JSFunction> target_;
1259};
1260
1261
1262class HCallNew: public HCall {
1263 public:
1264 explicit HCallNew(int argument_count) : HCall(argument_count) { }
1265
1266 virtual Representation RequiredInputRepresentation(int index) const {
1267 return Representation::Tagged();
1268 }
1269
1270 HValue* constructor() const { return ArgumentAt(0); }
1271
1272 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
1273};
1274
1275
1276class HCallRuntime: public HCall {
1277 public:
1278 HCallRuntime(Handle<String> name,
1279 Runtime::Function* c_function,
1280 int argument_count)
1281 : HCall(argument_count), c_function_(c_function), name_(name) { }
1282 virtual void PrintDataTo(StringStream* stream) const;
1283
1284 Runtime::Function* function() const { return c_function_; }
1285 Handle<String> name() const { return name_; }
1286
1287 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
1288
1289 private:
1290 Runtime::Function* c_function_;
1291 Handle<String> name_;
1292};
1293
1294
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001295class HJSArrayLength: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001296 public:
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001297 explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001298 // The length of an array is stored as a tagged value in the array
1299 // object. It is guaranteed to be 32 bit integer, but it can be
1300 // represented as either a smi or heap number.
1301 set_representation(Representation::Tagged());
1302 SetFlag(kDependsOnArrayLengths);
1303 SetFlag(kUseGVN);
1304 }
1305
1306 virtual Representation RequiredInputRepresentation(int index) const {
1307 return Representation::Tagged();
1308 }
1309
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001310 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001311
1312 protected:
1313 virtual bool DataEquals(HValue* other) const { return true; }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001314};
1315
1316
1317class HFixedArrayLength: public HUnaryOperation {
1318 public:
1319 explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
1320 set_representation(Representation::Tagged());
1321 SetFlag(kDependsOnArrayLengths);
1322 SetFlag(kUseGVN);
1323 }
1324
1325 virtual Representation RequiredInputRepresentation(int index) const {
1326 return Representation::Tagged();
1327 }
1328
1329 DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001330
1331 protected:
1332 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001333};
1334
1335
1336class HBitNot: public HUnaryOperation {
1337 public:
1338 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1339 set_representation(Representation::Integer32());
1340 SetFlag(kUseGVN);
1341 SetFlag(kTruncatingToInt32);
1342 }
1343
1344 virtual Representation RequiredInputRepresentation(int index) const {
1345 return Representation::Integer32();
1346 }
1347 virtual HType CalculateInferredType() const;
1348
1349 DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001350
1351 protected:
1352 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001353};
1354
1355
1356class HUnaryMathOperation: public HUnaryOperation {
1357 public:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001358 HUnaryMathOperation(HValue* value, BuiltinFunctionId op)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001359 : HUnaryOperation(value), op_(op) {
1360 switch (op) {
1361 case kMathFloor:
1362 case kMathRound:
1363 case kMathCeil:
1364 set_representation(Representation::Integer32());
1365 break;
1366 case kMathAbs:
1367 set_representation(Representation::Tagged());
1368 SetFlag(kFlexibleRepresentation);
1369 break;
1370 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001371 case kMathPowHalf:
1372 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001373 case kMathSin:
1374 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001375 set_representation(Representation::Double());
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001376 break;
1377 default:
1378 UNREACHABLE();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001379 }
1380 SetFlag(kUseGVN);
1381 }
1382
1383 virtual void PrintDataTo(StringStream* stream) const;
1384
1385 virtual HType CalculateInferredType() const;
1386
1387 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1388
1389 virtual Representation RequiredInputRepresentation(int index) const {
1390 switch (op_) {
1391 case kMathFloor:
1392 case kMathRound:
1393 case kMathCeil:
1394 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001395 case kMathPowHalf:
1396 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001397 case kMathSin:
1398 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001399 return Representation::Double();
1400 break;
1401 case kMathAbs:
1402 return representation();
1403 break;
1404 default:
1405 return Representation::None();
1406 }
1407 }
1408
1409 virtual HValue* Canonicalize() {
1410 // If the input is integer32 then we replace the floor instruction
1411 // with its inputs. This happens before the representation changes are
1412 // introduced.
1413 if (op() == kMathFloor) {
1414 if (value()->representation().IsInteger32()) return value();
1415 }
1416 return this;
1417 }
1418
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001419 BuiltinFunctionId op() const { return op_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001420 const char* OpName() const;
1421
1422 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
1423
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001424 protected:
1425 virtual bool DataEquals(HValue* other) const {
1426 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
1427 return op_ == b->op();
1428 }
1429
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001430 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001431 BuiltinFunctionId op_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001432};
1433
1434
1435class HLoadElements: public HUnaryOperation {
1436 public:
1437 explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1438 set_representation(Representation::Tagged());
1439 SetFlag(kUseGVN);
1440 SetFlag(kDependsOnMaps);
1441 }
1442
1443 virtual Representation RequiredInputRepresentation(int index) const {
1444 return Representation::Tagged();
1445 }
1446
1447 DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001448
1449 protected:
1450 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001451};
1452
1453
1454class HCheckMap: public HUnaryOperation {
1455 public:
1456 HCheckMap(HValue* value, Handle<Map> map)
1457 : HUnaryOperation(value), map_(map) {
1458 set_representation(Representation::Tagged());
1459 SetFlag(kUseGVN);
1460 SetFlag(kDependsOnMaps);
1461 }
1462
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001463 virtual bool IsCheckInstruction() const { return true; }
1464
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001465 virtual Representation RequiredInputRepresentation(int index) const {
1466 return Representation::Tagged();
1467 }
1468 virtual void PrintDataTo(StringStream* stream) const;
1469 virtual HType CalculateInferredType() const;
1470
1471#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001472 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001473#endif
1474
1475 Handle<Map> map() const { return map_; }
1476
1477 DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
1478
1479 protected:
1480 virtual bool DataEquals(HValue* other) const {
1481 HCheckMap* b = HCheckMap::cast(other);
1482 return map_.is_identical_to(b->map());
1483 }
1484
1485 private:
1486 Handle<Map> map_;
1487};
1488
1489
1490class HCheckFunction: public HUnaryOperation {
1491 public:
1492 HCheckFunction(HValue* value, Handle<JSFunction> function)
1493 : HUnaryOperation(value), target_(function) {
1494 set_representation(Representation::Tagged());
1495 SetFlag(kUseGVN);
1496 }
1497
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001498 virtual bool IsCheckInstruction() const { return true; }
1499
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001500 virtual Representation RequiredInputRepresentation(int index) const {
1501 return Representation::Tagged();
1502 }
1503 virtual void PrintDataTo(StringStream* stream) const;
1504 virtual HType CalculateInferredType() const;
1505
1506#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001507 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001508#endif
1509
1510 Handle<JSFunction> target() const { return target_; }
1511
1512 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
1513
1514 protected:
1515 virtual bool DataEquals(HValue* other) const {
1516 HCheckFunction* b = HCheckFunction::cast(other);
1517 return target_.is_identical_to(b->target());
1518 }
1519
1520 private:
1521 Handle<JSFunction> target_;
1522};
1523
1524
1525class HCheckInstanceType: public HUnaryOperation {
1526 public:
1527 // Check that the instance type is in the range [first, last] where
1528 // both first and last are included.
1529 HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
1530 : HUnaryOperation(value), first_(first), last_(last) {
1531 ASSERT(first <= last);
1532 set_representation(Representation::Tagged());
1533 SetFlag(kUseGVN);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001534 if ((FIRST_STRING_TYPE < first && last <= LAST_STRING_TYPE) ||
1535 (FIRST_STRING_TYPE <= first && last < LAST_STRING_TYPE)) {
1536 // A particular string instance type can change because of GC or
1537 // externalization, but the value still remains a string.
1538 SetFlag(kDependsOnMaps);
1539 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001540 }
1541
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001542 virtual bool IsCheckInstruction() const { return true; }
1543
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001544 virtual Representation RequiredInputRepresentation(int index) const {
1545 return Representation::Tagged();
1546 }
1547
1548#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001549 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001550#endif
1551
1552 static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
1553
1554 InstanceType first() const { return first_; }
1555 InstanceType last() const { return last_; }
1556
1557 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")
1558
1559 protected:
1560 // TODO(ager): It could be nice to allow the ommision of instance
1561 // type checks if we have already performed an instance type check
1562 // with a larger range.
1563 virtual bool DataEquals(HValue* other) const {
1564 HCheckInstanceType* b = HCheckInstanceType::cast(other);
1565 return (first_ == b->first()) && (last_ == b->last());
1566 }
1567
1568 private:
1569 InstanceType first_;
1570 InstanceType last_;
1571};
1572
1573
1574class HCheckNonSmi: public HUnaryOperation {
1575 public:
1576 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
1577 set_representation(Representation::Tagged());
1578 SetFlag(kUseGVN);
1579 }
1580
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001581 virtual bool IsCheckInstruction() const { return true; }
1582
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001583 virtual Representation RequiredInputRepresentation(int index) const {
1584 return Representation::Tagged();
1585 }
1586
1587 virtual HType CalculateInferredType() const;
1588
1589#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001590 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001591#endif
1592
1593 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001594
1595 protected:
1596 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001597};
1598
1599
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001600class HCheckPrototypeMaps: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001601 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001602 HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
1603 : prototype_(prototype), holder_(holder) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001604 SetFlag(kUseGVN);
1605 SetFlag(kDependsOnMaps);
1606 }
1607
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001608 virtual bool IsCheckInstruction() const { return true; }
1609
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001610#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001611 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001612#endif
1613
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001614 Handle<JSObject> prototype() const { return prototype_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001615 Handle<JSObject> holder() const { return holder_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001616
1617 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
1618
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001619 virtual intptr_t Hashcode() const {
1620 ASSERT(!Heap::IsAllocationAllowed());
1621 intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
1622 hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
1623 return hash;
1624 }
1625
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001626 protected:
1627 virtual bool DataEquals(HValue* other) const {
1628 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001629 return prototype_.is_identical_to(b->prototype()) &&
1630 holder_.is_identical_to(b->holder());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001631 }
1632
1633 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001634 Handle<JSObject> prototype_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001635 Handle<JSObject> holder_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001636};
1637
1638
1639class HCheckSmi: public HUnaryOperation {
1640 public:
1641 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
1642 set_representation(Representation::Tagged());
1643 SetFlag(kUseGVN);
1644 }
1645
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001646 virtual bool IsCheckInstruction() const { return true; }
1647
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001648 virtual Representation RequiredInputRepresentation(int index) const {
1649 return Representation::Tagged();
1650 }
1651 virtual HType CalculateInferredType() const;
1652
1653#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001654 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001655#endif
1656
1657 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001658
1659 protected:
1660 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001661};
1662
1663
1664class HPhi: public HValue {
1665 public:
1666 explicit HPhi(int merged_index)
1667 : inputs_(2),
1668 merged_index_(merged_index),
1669 phi_id_(-1) {
1670 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1671 non_phi_uses_[i] = 0;
1672 indirect_uses_[i] = 0;
1673 }
1674 ASSERT(merged_index >= 0);
1675 set_representation(Representation::Tagged());
1676 SetFlag(kFlexibleRepresentation);
1677 }
1678
1679 virtual Representation InferredRepresentation() const {
1680 bool double_occurred = false;
1681 bool int32_occurred = false;
1682 for (int i = 0; i < OperandCount(); ++i) {
1683 HValue* value = OperandAt(i);
1684 if (value->representation().IsDouble()) double_occurred = true;
1685 if (value->representation().IsInteger32()) int32_occurred = true;
1686 if (value->representation().IsTagged()) return Representation::Tagged();
1687 }
1688
1689 if (double_occurred) return Representation::Double();
1690 if (int32_occurred) return Representation::Integer32();
1691 return Representation::None();
1692 }
1693
1694 virtual Range* InferRange();
1695 virtual Representation RequiredInputRepresentation(int index) const {
1696 return representation();
1697 }
1698 virtual HType CalculateInferredType() const;
1699 virtual int OperandCount() const { return inputs_.length(); }
1700 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
1701 HValue* GetRedundantReplacement() const;
1702 void AddInput(HValue* value);
1703
1704 bool HasReceiverOperand();
1705
1706 int merged_index() const { return merged_index_; }
1707
1708 virtual const char* Mnemonic() const { return "phi"; }
1709
1710 virtual void PrintTo(StringStream* stream) const;
1711
1712#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001713 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001714#endif
1715
1716 DECLARE_INSTRUCTION(Phi)
1717
1718 void InitRealUses(int id);
1719 void AddNonPhiUsesFrom(HPhi* other);
1720 void AddIndirectUsesTo(int* use_count);
1721
1722 int tagged_non_phi_uses() const {
1723 return non_phi_uses_[Representation::kTagged];
1724 }
1725 int int32_non_phi_uses() const {
1726 return non_phi_uses_[Representation::kInteger32];
1727 }
1728 int double_non_phi_uses() const {
1729 return non_phi_uses_[Representation::kDouble];
1730 }
1731 int tagged_indirect_uses() const {
1732 return indirect_uses_[Representation::kTagged];
1733 }
1734 int int32_indirect_uses() const {
1735 return indirect_uses_[Representation::kInteger32];
1736 }
1737 int double_indirect_uses() const {
1738 return indirect_uses_[Representation::kDouble];
1739 }
1740 int phi_id() { return phi_id_; }
1741
1742 protected:
1743 virtual void DeleteFromGraph();
1744 virtual void InternalSetOperandAt(int index, HValue* value) {
1745 inputs_[index] = value;
1746 }
1747
1748 private:
1749 ZoneList<HValue*> inputs_;
1750 int merged_index_;
1751
1752 int non_phi_uses_[Representation::kNumRepresentations];
1753 int indirect_uses_[Representation::kNumRepresentations];
1754 int phi_id_;
1755};
1756
1757
1758class HArgumentsObject: public HInstruction {
1759 public:
1760 HArgumentsObject() {
1761 set_representation(Representation::Tagged());
1762 SetFlag(kIsArguments);
1763 }
1764
1765 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
1766};
1767
1768
1769class HConstant: public HInstruction {
1770 public:
1771 HConstant(Handle<Object> handle, Representation r);
1772
1773 Handle<Object> handle() const { return handle_; }
1774
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001775 bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
1776
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001777 virtual bool EmitAtUses() const { return !representation().IsDouble(); }
1778 virtual void PrintDataTo(StringStream* stream) const;
1779 virtual HType CalculateInferredType() const;
1780 bool IsInteger() const { return handle_->IsSmi(); }
1781 HConstant* CopyToRepresentation(Representation r) const;
1782 HConstant* CopyToTruncatedInt32() const;
1783 bool HasInteger32Value() const { return has_int32_value_; }
1784 int32_t Integer32Value() const {
1785 ASSERT(HasInteger32Value());
1786 return int32_value_;
1787 }
1788 bool HasDoubleValue() const { return has_double_value_; }
1789 double DoubleValue() const {
1790 ASSERT(HasDoubleValue());
1791 return double_value_;
1792 }
1793 bool HasStringValue() const { return handle_->IsString(); }
1794
1795 virtual intptr_t Hashcode() const {
1796 ASSERT(!Heap::allow_allocation(false));
1797 return reinterpret_cast<intptr_t>(*handle());
1798 }
1799
1800#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001801 virtual void Verify() { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001802#endif
1803
1804 DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
1805
1806 protected:
1807 virtual Range* InferRange();
1808
1809 virtual bool DataEquals(HValue* other) const {
1810 HConstant* other_constant = HConstant::cast(other);
1811 return handle().is_identical_to(other_constant->handle());
1812 }
1813
1814 private:
1815 Handle<Object> handle_;
1816 HType constant_type_;
1817
1818 // The following two values represent the int32 and the double value of the
1819 // given constant if there is a lossless conversion between the constant
1820 // and the specific representation.
1821 bool has_int32_value_;
1822 int32_t int32_value_;
1823 bool has_double_value_;
1824 double double_value_;
1825};
1826
1827
1828class HBinaryOperation: public HInstruction {
1829 public:
1830 HBinaryOperation(HValue* left, HValue* right) {
1831 ASSERT(left != NULL && right != NULL);
1832 SetOperandAt(0, left);
1833 SetOperandAt(1, right);
1834 }
1835
1836 HValue* left() const { return OperandAt(0); }
1837 HValue* right() const { return OperandAt(1); }
1838
1839 // TODO(kasperl): Move these helpers to the IA-32 Lithium
1840 // instruction sequence builder.
1841 HValue* LeastConstantOperand() const {
1842 if (IsCommutative() && left()->IsConstant()) return right();
1843 return left();
1844 }
1845 HValue* MostConstantOperand() const {
1846 if (IsCommutative() && left()->IsConstant()) return left();
1847 return right();
1848 }
1849
1850 virtual bool IsCommutative() const { return false; }
1851
1852 virtual void PrintDataTo(StringStream* stream) const;
1853 virtual int OperandCount() const { return operands_.length(); }
1854 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1855
1856 DECLARE_INSTRUCTION(BinaryOperation)
1857
1858 protected:
1859 virtual void InternalSetOperandAt(int index, HValue* value) {
1860 operands_[index] = value;
1861 }
1862
1863 private:
1864 HOperandVector<2> operands_;
1865};
1866
1867
1868class HApplyArguments: public HInstruction {
1869 public:
1870 HApplyArguments(HValue* function,
1871 HValue* receiver,
1872 HValue* length,
1873 HValue* elements) {
1874 set_representation(Representation::Tagged());
1875 SetOperandAt(0, function);
1876 SetOperandAt(1, receiver);
1877 SetOperandAt(2, length);
1878 SetOperandAt(3, elements);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001879 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001880 }
1881
1882 virtual Representation RequiredInputRepresentation(int index) const {
1883 // The length is untagged, all other inputs are tagged.
1884 return (index == 2)
1885 ? Representation::Integer32()
1886 : Representation::Tagged();
1887 }
1888
1889 HValue* function() const { return OperandAt(0); }
1890 HValue* receiver() const { return OperandAt(1); }
1891 HValue* length() const { return OperandAt(2); }
1892 HValue* elements() const { return OperandAt(3); }
1893
1894 virtual int OperandCount() const { return operands_.length(); }
1895 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1896
1897 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
1898
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001899 protected:
1900 virtual void InternalSetOperandAt(int index, HValue* value) {
1901 operands_[index] = value;
1902 }
1903
1904 private:
1905 HOperandVector<4> operands_;
1906};
1907
1908
1909class HArgumentsElements: public HInstruction {
1910 public:
1911 HArgumentsElements() {
1912 // The value produced by this instruction is a pointer into the stack
1913 // that looks as if it was a smi because of alignment.
1914 set_representation(Representation::Tagged());
1915 SetFlag(kUseGVN);
1916 }
1917
1918 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001919
1920 protected:
1921 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001922};
1923
1924
1925class HArgumentsLength: public HUnaryOperation {
1926 public:
1927 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
1928 set_representation(Representation::Integer32());
1929 SetFlag(kUseGVN);
1930 }
1931
1932 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001933
1934 protected:
1935 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001936};
1937
1938
1939class HAccessArgumentsAt: public HInstruction {
1940 public:
1941 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
1942 set_representation(Representation::Tagged());
1943 SetFlag(kUseGVN);
1944 SetOperandAt(0, arguments);
1945 SetOperandAt(1, length);
1946 SetOperandAt(2, index);
1947 }
1948
1949 virtual void PrintDataTo(StringStream* stream) const;
1950
1951 virtual Representation RequiredInputRepresentation(int index) const {
1952 // The arguments elements is considered tagged.
1953 return index == 0
1954 ? Representation::Tagged()
1955 : Representation::Integer32();
1956 }
1957
1958 HValue* arguments() const { return operands_[0]; }
1959 HValue* length() const { return operands_[1]; }
1960 HValue* index() const { return operands_[2]; }
1961
1962 virtual int OperandCount() const { return operands_.length(); }
1963 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1964
1965 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
1966
1967 protected:
1968 virtual void InternalSetOperandAt(int index, HValue* value) {
1969 operands_[index] = value;
1970 }
1971
ager@chromium.org378b34e2011-01-28 08:04:38 +00001972 virtual bool DataEquals(HValue* other) const { return true; }
1973
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001974 private:
1975 HOperandVector<3> operands_;
1976};
1977
1978
1979class HBoundsCheck: public HBinaryOperation {
1980 public:
1981 HBoundsCheck(HValue* index, HValue* length)
1982 : HBinaryOperation(index, length) {
1983 SetFlag(kUseGVN);
1984 }
1985
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001986 virtual bool IsCheckInstruction() const { return true; }
1987
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001988 virtual Representation RequiredInputRepresentation(int index) const {
1989 return Representation::Integer32();
1990 }
1991
1992#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001993 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001994#endif
1995
1996 HValue* index() const { return left(); }
1997 HValue* length() const { return right(); }
1998
1999 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002000
2001 protected:
2002 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002003};
2004
2005
2006class HBitwiseBinaryOperation: public HBinaryOperation {
2007 public:
2008 HBitwiseBinaryOperation(HValue* left, HValue* right)
2009 : HBinaryOperation(left, right) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002010 set_representation(Representation::Tagged());
2011 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002012 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002013 }
2014
2015 virtual Representation RequiredInputRepresentation(int index) const {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002016 return representation();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002017 }
2018
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002019 virtual void RepresentationChanged(Representation to) {
2020 if (!to.IsTagged()) {
2021 ASSERT(to.IsInteger32());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002022 ClearAllSideEffects();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002023 SetFlag(kTruncatingToInt32);
2024 SetFlag(kUseGVN);
2025 }
2026 }
2027
2028 HType CalculateInferredType() const;
2029
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002030 DECLARE_INSTRUCTION(BitwiseBinaryOperation)
2031};
2032
2033
2034class HArithmeticBinaryOperation: public HBinaryOperation {
2035 public:
2036 HArithmeticBinaryOperation(HValue* left, HValue* right)
2037 : HBinaryOperation(left, right) {
2038 set_representation(Representation::Tagged());
2039 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002040 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002041 }
2042
2043 virtual void RepresentationChanged(Representation to) {
2044 if (!to.IsTagged()) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002045 ClearAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002046 SetFlag(kUseGVN);
2047 }
2048 }
2049
2050 virtual HType CalculateInferredType() const;
2051 virtual Representation RequiredInputRepresentation(int index) const {
2052 return representation();
2053 }
2054 virtual Representation InferredRepresentation() const {
2055 if (left()->representation().Equals(right()->representation())) {
2056 return left()->representation();
2057 }
2058 return HValue::InferredRepresentation();
2059 }
2060
2061 DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
2062};
2063
2064
2065class HCompare: public HBinaryOperation {
2066 public:
2067 HCompare(HValue* left, HValue* right, Token::Value token)
2068 : HBinaryOperation(left, right), token_(token) {
2069 ASSERT(Token::IsCompareOp(token));
2070 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002071 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002072 }
2073
2074 void SetInputRepresentation(Representation r);
2075 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2076 virtual Representation RequiredInputRepresentation(int index) const {
2077 return input_representation_;
2078 }
2079 Representation GetInputRepresentation() const {
2080 return input_representation_;
2081 }
2082 Token::Value token() const { return token_; }
2083 virtual void PrintDataTo(StringStream* stream) const;
2084
2085 virtual HType CalculateInferredType() const;
2086
2087 virtual intptr_t Hashcode() const {
2088 return HValue::Hashcode() * 7 + token_;
2089 }
2090
2091 DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
2092
2093 protected:
2094 virtual bool DataEquals(HValue* other) const {
2095 HCompare* comp = HCompare::cast(other);
2096 return token_ == comp->token();
2097 }
2098
2099 private:
2100 Representation input_representation_;
2101 Token::Value token_;
2102};
2103
2104
2105class HCompareJSObjectEq: public HBinaryOperation {
2106 public:
2107 HCompareJSObjectEq(HValue* left, HValue* right)
2108 : HBinaryOperation(left, right) {
2109 set_representation(Representation::Tagged());
2110 SetFlag(kUseGVN);
2111 }
2112
2113 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2114 virtual Representation RequiredInputRepresentation(int index) const {
2115 return Representation::Tagged();
2116 }
2117 virtual HType CalculateInferredType() const;
2118
2119 DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002120
2121 protected:
2122 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002123};
2124
2125
2126class HUnaryPredicate: public HUnaryOperation {
2127 public:
2128 explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
2129 set_representation(Representation::Tagged());
2130 SetFlag(kUseGVN);
2131 }
2132 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2133 virtual Representation RequiredInputRepresentation(int index) const {
2134 return Representation::Tagged();
2135 }
2136 virtual HType CalculateInferredType() const;
2137};
2138
2139
2140class HIsNull: public HUnaryPredicate {
2141 public:
2142 HIsNull(HValue* value, bool is_strict)
2143 : HUnaryPredicate(value), is_strict_(is_strict) { }
2144
2145 bool is_strict() const { return is_strict_; }
2146
2147 DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
2148
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002149 protected:
2150 virtual bool DataEquals(HValue* other) const {
2151 HIsNull* b = HIsNull::cast(other);
2152 return is_strict_ == b->is_strict();
2153 }
2154
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002155 private:
2156 bool is_strict_;
2157};
2158
2159
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002160class HIsObject: public HUnaryPredicate {
2161 public:
2162 explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }
2163
2164 DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002165
2166 protected:
2167 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002168};
2169
2170
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002171class HIsSmi: public HUnaryPredicate {
2172 public:
2173 explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
2174
2175 DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002176
2177 protected:
2178 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002179};
2180
2181
2182class HHasInstanceType: public HUnaryPredicate {
2183 public:
2184 HHasInstanceType(HValue* value, InstanceType type)
2185 : HUnaryPredicate(value), from_(type), to_(type) { }
2186 HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
2187 : HUnaryPredicate(value), from_(from), to_(to) {
2188 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
2189 }
2190
2191 InstanceType from() { return from_; }
2192 InstanceType to() { return to_; }
2193
2194 virtual void PrintDataTo(StringStream* stream) const;
2195
2196 DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
2197
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002198 protected:
2199 virtual bool DataEquals(HValue* other) const {
2200 HHasInstanceType* b = HHasInstanceType::cast(other);
2201 return (from_ == b->from()) && (to_ == b->to());
2202 }
2203
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002204 private:
2205 InstanceType from_;
2206 InstanceType to_; // Inclusive range, not all combinations work.
2207};
2208
2209
2210class HHasCachedArrayIndex: public HUnaryPredicate {
2211 public:
2212 explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
2213
2214 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002215
2216 protected:
2217 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002218};
2219
2220
2221class HClassOfTest: public HUnaryPredicate {
2222 public:
2223 HClassOfTest(HValue* value, Handle<String> class_name)
2224 : HUnaryPredicate(value), class_name_(class_name) { }
2225
2226 DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
2227
2228 virtual void PrintDataTo(StringStream* stream) const;
2229
2230 Handle<String> class_name() const { return class_name_; }
2231
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002232 protected:
2233 virtual bool DataEquals(HValue* other) const {
2234 HClassOfTest* b = HClassOfTest::cast(other);
2235 return class_name_.is_identical_to(b->class_name_);
2236 }
2237
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002238 private:
2239 Handle<String> class_name_;
2240};
2241
2242
2243class HTypeofIs: public HUnaryPredicate {
2244 public:
2245 HTypeofIs(HValue* value, Handle<String> type_literal)
2246 : HUnaryPredicate(value), type_literal_(type_literal) { }
2247
2248 Handle<String> type_literal() { return type_literal_; }
2249 virtual void PrintDataTo(StringStream* stream) const;
2250
2251 DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
2252
2253 protected:
2254 virtual bool DataEquals(HValue* other) const {
2255 HTypeofIs* b = HTypeofIs::cast(other);
2256 return type_literal_.is_identical_to(b->type_literal_);
2257 }
2258
2259 private:
2260 Handle<String> type_literal_;
2261};
2262
2263
2264class HInstanceOf: public HBinaryOperation {
2265 public:
2266 HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
2267 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002268 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002269 }
2270
2271 virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2272
2273 virtual Representation RequiredInputRepresentation(int index) const {
2274 return Representation::Tagged();
2275 }
2276
2277 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
2278};
2279
2280
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002281class HInstanceOfKnownGlobal: public HUnaryOperation {
2282 public:
2283 HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right)
2284 : HUnaryOperation(left), function_(right) {
2285 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002286 SetAllSideEffects();
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002287 }
2288
2289 Handle<JSFunction> function() { return function_; }
2290
2291 virtual Representation RequiredInputRepresentation(int index) const {
2292 return Representation::Tagged();
2293 }
2294
2295 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
2296 "instance_of_known_global")
2297
2298 private:
2299 Handle<JSFunction> function_;
2300};
2301
2302
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002303class HPower: public HBinaryOperation {
2304 public:
2305 HPower(HValue* left, HValue* right)
2306 : HBinaryOperation(left, right) {
2307 set_representation(Representation::Double());
2308 SetFlag(kUseGVN);
2309 }
2310
2311 virtual Representation RequiredInputRepresentation(int index) const {
2312 return (index == 1) ? Representation::None() : Representation::Double();
2313 }
2314
2315 DECLARE_CONCRETE_INSTRUCTION(Power, "power")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002316
2317 protected:
2318 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002319};
2320
2321
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002322class HAdd: public HArithmeticBinaryOperation {
2323 public:
2324 HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2325 SetFlag(kCanOverflow);
2326 }
2327
2328 // Add is only commutative if two integer values are added and not if two
2329 // tagged values are added (because it might be a String concatenation).
2330 virtual bool IsCommutative() const {
2331 return !representation().IsTagged();
2332 }
2333
2334 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2335
2336 virtual HType CalculateInferredType() const;
2337
2338 DECLARE_CONCRETE_INSTRUCTION(Add, "add")
2339
2340 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002341 virtual bool DataEquals(HValue* other) const { return true; }
2342
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002343 virtual Range* InferRange();
2344};
2345
2346
2347class HSub: public HArithmeticBinaryOperation {
2348 public:
2349 HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2350 SetFlag(kCanOverflow);
2351 }
2352
2353 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2354
2355 DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
2356
2357 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002358 virtual bool DataEquals(HValue* other) const { return true; }
2359
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002360 virtual Range* InferRange();
2361};
2362
2363
2364class HMul: public HArithmeticBinaryOperation {
2365 public:
2366 HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2367 SetFlag(kCanOverflow);
2368 }
2369
2370 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2371
2372 // Only commutative if it is certain that not two objects are multiplicated.
2373 virtual bool IsCommutative() const {
2374 return !representation().IsTagged();
2375 }
2376
2377 DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
2378
2379 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002380 virtual bool DataEquals(HValue* other) const { return true; }
2381
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002382 virtual Range* InferRange();
2383};
2384
2385
2386class HMod: public HArithmeticBinaryOperation {
2387 public:
2388 HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2389 SetFlag(kCanBeDivByZero);
2390 }
2391
2392 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2393
2394 DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
2395
2396 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002397 virtual bool DataEquals(HValue* other) const { return true; }
2398
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002399 virtual Range* InferRange();
2400};
2401
2402
2403class HDiv: public HArithmeticBinaryOperation {
2404 public:
2405 HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2406 SetFlag(kCanBeDivByZero);
2407 SetFlag(kCanOverflow);
2408 }
2409
2410 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2411
2412 DECLARE_CONCRETE_INSTRUCTION(Div, "div")
2413
2414 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002415 virtual bool DataEquals(HValue* other) const { return true; }
2416
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002417 virtual Range* InferRange();
2418};
2419
2420
2421class HBitAnd: public HBitwiseBinaryOperation {
2422 public:
2423 HBitAnd(HValue* left, HValue* right)
2424 : HBitwiseBinaryOperation(left, right) { }
2425
2426 virtual bool IsCommutative() const { return true; }
2427 virtual HType CalculateInferredType() const;
2428
2429 DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
2430
2431 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002432 virtual bool DataEquals(HValue* other) const { return true; }
2433
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002434 virtual Range* InferRange();
2435};
2436
2437
2438class HBitXor: public HBitwiseBinaryOperation {
2439 public:
2440 HBitXor(HValue* left, HValue* right)
2441 : HBitwiseBinaryOperation(left, right) { }
2442
2443 virtual bool IsCommutative() const { return true; }
2444 virtual HType CalculateInferredType() const;
2445
2446 DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002447
2448 protected:
2449 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002450};
2451
2452
2453class HBitOr: public HBitwiseBinaryOperation {
2454 public:
2455 HBitOr(HValue* left, HValue* right)
2456 : HBitwiseBinaryOperation(left, right) { }
2457
2458 virtual bool IsCommutative() const { return true; }
2459 virtual HType CalculateInferredType() const;
2460
2461 DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
2462
2463 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002464 virtual bool DataEquals(HValue* other) const { return true; }
2465
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002466 virtual Range* InferRange();
2467};
2468
2469
2470class HShl: public HBitwiseBinaryOperation {
2471 public:
2472 HShl(HValue* left, HValue* right)
2473 : HBitwiseBinaryOperation(left, right) { }
2474
2475 virtual Range* InferRange();
2476 virtual HType CalculateInferredType() const;
2477
2478 DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002479
2480 protected:
2481 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002482};
2483
2484
2485class HShr: public HBitwiseBinaryOperation {
2486 public:
2487 HShr(HValue* left, HValue* right)
2488 : HBitwiseBinaryOperation(left, right) { }
2489
2490 virtual HType CalculateInferredType() const;
2491
2492 DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002493
2494 protected:
2495 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002496};
2497
2498
2499class HSar: public HBitwiseBinaryOperation {
2500 public:
2501 HSar(HValue* left, HValue* right)
2502 : HBitwiseBinaryOperation(left, right) { }
2503
2504 virtual Range* InferRange();
2505 virtual HType CalculateInferredType() const;
2506
2507 DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002508
2509 protected:
2510 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002511};
2512
2513
2514class HOsrEntry: public HInstruction {
2515 public:
2516 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
2517 SetFlag(kChangesOsrEntries);
2518 }
2519
2520 int ast_id() const { return ast_id_; }
2521
2522 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
2523
2524 private:
2525 int ast_id_;
2526};
2527
2528
2529class HParameter: public HInstruction {
2530 public:
2531 explicit HParameter(unsigned index) : index_(index) {
2532 set_representation(Representation::Tagged());
2533 }
2534
2535 unsigned index() const { return index_; }
2536
2537 virtual void PrintDataTo(StringStream* stream) const;
2538
2539 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2540
2541 private:
2542 unsigned index_;
2543};
2544
2545
2546class HCallStub: public HInstruction {
2547 public:
2548 HCallStub(CodeStub::Major major_key, int argument_count)
2549 : major_key_(major_key),
2550 argument_count_(argument_count),
2551 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
2552 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002553 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002554 }
2555
2556 CodeStub::Major major_key() { return major_key_; }
2557 int argument_count() { return argument_count_; }
2558
2559 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
2560 transcendental_type_ = transcendental_type;
2561 }
2562 TranscendentalCache::Type transcendental_type() {
2563 return transcendental_type_;
2564 }
2565 virtual void PrintDataTo(StringStream* stream) const;
2566
2567 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
2568
2569 private:
2570 CodeStub::Major major_key_;
2571 int argument_count_;
2572 TranscendentalCache::Type transcendental_type_;
2573};
2574
2575
2576class HUnknownOSRValue: public HInstruction {
2577 public:
2578 HUnknownOSRValue() { set_representation(Representation::Tagged()); }
2579
2580 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
2581};
2582
2583
2584class HLoadGlobal: public HInstruction {
2585 public:
2586 HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
2587 : cell_(cell), check_hole_value_(check_hole_value) {
2588 set_representation(Representation::Tagged());
2589 SetFlag(kUseGVN);
2590 SetFlag(kDependsOnGlobalVars);
2591 }
2592
2593 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2594 bool check_hole_value() const { return check_hole_value_; }
2595
2596 virtual Representation RequiredInputRepresentation(int index) const {
2597 return Representation::Tagged();
2598 }
2599 virtual void PrintDataTo(StringStream* stream) const;
2600
2601 virtual intptr_t Hashcode() const {
2602 ASSERT(!Heap::allow_allocation(false));
2603 return reinterpret_cast<intptr_t>(*cell_);
2604 }
2605
2606 DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
2607
2608 protected:
2609 virtual bool DataEquals(HValue* other) const {
2610 HLoadGlobal* b = HLoadGlobal::cast(other);
2611 return cell_.is_identical_to(b->cell());
2612 }
2613
2614 private:
2615 Handle<JSGlobalPropertyCell> cell_;
2616 bool check_hole_value_;
2617};
2618
2619
2620class HStoreGlobal: public HUnaryOperation {
2621 public:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002622 HStoreGlobal(HValue* value,
2623 Handle<JSGlobalPropertyCell> cell,
2624 bool check_hole_value)
2625 : HUnaryOperation(value),
2626 cell_(cell),
2627 check_hole_value_(check_hole_value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002628 SetFlag(kChangesGlobalVars);
2629 }
2630
2631 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002632 bool check_hole_value() const { return check_hole_value_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002633
2634 virtual Representation RequiredInputRepresentation(int index) const {
2635 return Representation::Tagged();
2636 }
2637 virtual void PrintDataTo(StringStream* stream) const;
2638
2639 DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
2640
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002641 private:
2642 Handle<JSGlobalPropertyCell> cell_;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002643 bool check_hole_value_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002644};
2645
2646
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002647class HLoadContextSlot: public HUnaryOperation {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002648 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002649 HLoadContextSlot(HValue* context , int slot_index)
2650 : HUnaryOperation(context), slot_index_(slot_index) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002651 set_representation(Representation::Tagged());
2652 SetFlag(kUseGVN);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002653 SetFlag(kDependsOnContextSlots);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002654 }
2655
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002656 int slot_index() const { return slot_index_; }
2657
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002658 virtual Representation RequiredInputRepresentation(int index) const {
2659 return Representation::Tagged();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002660 }
2661
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002662 virtual void PrintDataTo(StringStream* stream) const;
2663
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002664 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
2665
2666 protected:
2667 virtual bool DataEquals(HValue* other) const {
2668 HLoadContextSlot* b = HLoadContextSlot::cast(other);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002669 return (slot_index() == b->slot_index());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002670 }
2671
2672 private:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002673 int slot_index_;
2674};
2675
2676
2677static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
2678 return !value->type().IsSmi() &&
2679 !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
2680}
2681
2682
2683class HStoreContextSlot: public HBinaryOperation {
2684 public:
2685 HStoreContextSlot(HValue* context, int slot_index, HValue* value)
2686 : HBinaryOperation(context, value), slot_index_(slot_index) {
2687 SetFlag(kChangesContextSlots);
2688 }
2689
2690 HValue* context() const { return OperandAt(0); }
2691 HValue* value() const { return OperandAt(1); }
2692 int slot_index() const { return slot_index_; }
2693
2694 bool NeedsWriteBarrier() const {
2695 return StoringValueNeedsWriteBarrier(value());
2696 }
2697
2698 virtual Representation RequiredInputRepresentation(int index) const {
2699 return Representation::Tagged();
2700 }
2701
2702 virtual void PrintDataTo(StringStream* stream) const;
2703
2704 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store_context_slot")
2705
2706 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002707 int slot_index_;
2708};
2709
2710
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002711class HLoadNamedField: public HUnaryOperation {
2712 public:
2713 HLoadNamedField(HValue* object, bool is_in_object, int offset)
2714 : HUnaryOperation(object),
2715 is_in_object_(is_in_object),
2716 offset_(offset) {
2717 set_representation(Representation::Tagged());
2718 SetFlag(kUseGVN);
2719 if (is_in_object) {
2720 SetFlag(kDependsOnInobjectFields);
2721 } else {
2722 SetFlag(kDependsOnBackingStoreFields);
2723 }
2724 }
2725
2726 HValue* object() const { return OperandAt(0); }
2727 bool is_in_object() const { return is_in_object_; }
2728 int offset() const { return offset_; }
2729
2730 virtual Representation RequiredInputRepresentation(int index) const {
2731 return Representation::Tagged();
2732 }
2733 virtual void PrintDataTo(StringStream* stream) const;
2734
2735 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
2736
2737 protected:
2738 virtual bool DataEquals(HValue* other) const {
2739 HLoadNamedField* b = HLoadNamedField::cast(other);
2740 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
2741 }
2742
2743 private:
2744 bool is_in_object_;
2745 int offset_;
2746};
2747
2748
2749class HLoadNamedGeneric: public HUnaryOperation {
2750 public:
2751 HLoadNamedGeneric(HValue* object, Handle<Object> name)
2752 : HUnaryOperation(object), name_(name) {
2753 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002754 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002755 }
2756
2757 HValue* object() const { return OperandAt(0); }
2758 Handle<Object> name() const { return name_; }
2759
2760 virtual Representation RequiredInputRepresentation(int index) const {
2761 return Representation::Tagged();
2762 }
2763
2764 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
2765
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002766 private:
2767 Handle<Object> name_;
2768};
2769
2770
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002771class HLoadFunctionPrototype: public HUnaryOperation {
2772 public:
2773 explicit HLoadFunctionPrototype(HValue* function)
2774 : HUnaryOperation(function) {
2775 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002776 SetFlag(kUseGVN);
2777 SetFlag(kDependsOnCalls);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002778 }
2779
2780 HValue* function() const { return OperandAt(0); }
2781
2782 virtual Representation RequiredInputRepresentation(int index) const {
2783 return Representation::Tagged();
2784 }
2785
2786 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
2787
2788 protected:
2789 virtual bool DataEquals(HValue* other) const { return true; }
2790};
2791
2792
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002793class HLoadKeyed: public HBinaryOperation {
2794 public:
2795 HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
2796 set_representation(Representation::Tagged());
2797 }
2798
2799 virtual void PrintDataTo(StringStream* stream) const;
2800
2801 virtual Representation RequiredInputRepresentation(int index) const {
2802 return Representation::Tagged();
2803 }
2804 HValue* object() const { return OperandAt(0); }
2805 HValue* key() const { return OperandAt(1); }
2806
2807 DECLARE_INSTRUCTION(LoadKeyed)
2808};
2809
2810
2811class HLoadKeyedFastElement: public HLoadKeyed {
2812 public:
2813 HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2814 SetFlag(kDependsOnArrayElements);
2815 SetFlag(kUseGVN);
2816 }
2817
2818 virtual Representation RequiredInputRepresentation(int index) const {
2819 // The key is supposed to be Integer32.
2820 return (index == 1) ? Representation::Integer32()
2821 : Representation::Tagged();
2822 }
2823
2824 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
2825 "load_keyed_fast_element")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002826
2827 protected:
2828 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002829};
2830
2831
2832class HLoadKeyedGeneric: public HLoadKeyed {
2833 public:
2834 HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002835 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002836 }
2837
2838 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
2839};
2840
2841
2842class HStoreNamed: public HBinaryOperation {
2843 public:
2844 HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
2845 : HBinaryOperation(obj, val), name_(name) {
2846 }
2847
2848 virtual Representation RequiredInputRepresentation(int index) const {
2849 return Representation::Tagged();
2850 }
2851
2852 virtual void PrintDataTo(StringStream* stream) const;
2853
2854 HValue* object() const { return OperandAt(0); }
2855 Handle<Object> name() const { return name_; }
2856 HValue* value() const { return OperandAt(1); }
2857 void set_value(HValue* value) { SetOperandAt(1, value); }
2858
2859 DECLARE_INSTRUCTION(StoreNamed)
2860
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002861 private:
2862 Handle<Object> name_;
2863};
2864
2865
2866class HStoreNamedField: public HStoreNamed {
2867 public:
2868 HStoreNamedField(HValue* obj,
2869 Handle<Object> name,
2870 HValue* val,
2871 bool in_object,
2872 int offset)
2873 : HStoreNamed(obj, name, val),
2874 is_in_object_(in_object),
2875 offset_(offset) {
2876 if (is_in_object_) {
2877 SetFlag(kChangesInobjectFields);
2878 } else {
2879 SetFlag(kChangesBackingStoreFields);
2880 }
2881 }
2882
2883 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
2884
2885 virtual Representation RequiredInputRepresentation(int index) const {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002886 return Representation::Tagged();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002887 }
2888 virtual void PrintDataTo(StringStream* stream) const;
2889
2890 bool is_in_object() const { return is_in_object_; }
2891 int offset() const { return offset_; }
2892 Handle<Map> transition() const { return transition_; }
2893 void set_transition(Handle<Map> map) { transition_ = map; }
2894
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002895 bool NeedsWriteBarrier() const {
2896 return StoringValueNeedsWriteBarrier(value());
2897 }
2898
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002899 private:
2900 bool is_in_object_;
2901 int offset_;
2902 Handle<Map> transition_;
2903};
2904
2905
2906class HStoreNamedGeneric: public HStoreNamed {
2907 public:
2908 HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
2909 : HStoreNamed(obj, name, val) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002910 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002911 }
2912
2913 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
2914};
2915
2916
2917class HStoreKeyed: public HInstruction {
2918 public:
2919 HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
2920 SetOperandAt(0, obj);
2921 SetOperandAt(1, key);
2922 SetOperandAt(2, val);
2923 }
2924
2925 virtual void PrintDataTo(StringStream* stream) const;
2926 virtual int OperandCount() const { return operands_.length(); }
2927 virtual HValue* OperandAt(int index) const { return operands_[index]; }
2928
2929 virtual Representation RequiredInputRepresentation(int index) const {
2930 return Representation::Tagged();
2931 }
2932
2933 HValue* object() const { return OperandAt(0); }
2934 HValue* key() const { return OperandAt(1); }
2935 HValue* value() const { return OperandAt(2); }
2936
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002937 bool NeedsWriteBarrier() const {
2938 return StoringValueNeedsWriteBarrier(value());
2939 }
2940
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002941 DECLARE_INSTRUCTION(StoreKeyed)
2942
2943 protected:
2944 virtual void InternalSetOperandAt(int index, HValue* value) {
2945 operands_[index] = value;
2946 }
2947
2948 private:
2949 HOperandVector<3> operands_;
2950};
2951
2952
2953class HStoreKeyedFastElement: public HStoreKeyed {
2954 public:
2955 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
2956 : HStoreKeyed(obj, key, val) {
2957 SetFlag(kChangesArrayElements);
2958 }
2959
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002960 virtual Representation RequiredInputRepresentation(int index) const {
2961 // The key is supposed to be Integer32.
2962 return (index == 1) ? Representation::Integer32()
2963 : Representation::Tagged();
2964 }
2965
2966 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
2967 "store_keyed_fast_element")
2968};
2969
2970
2971class HStoreKeyedGeneric: public HStoreKeyed {
2972 public:
2973 HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
2974 : HStoreKeyed(obj, key, val) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002975 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002976 }
2977
2978 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
2979};
2980
2981
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002982class HStringCharCodeAt: public HBinaryOperation {
2983 public:
2984 HStringCharCodeAt(HValue* string, HValue* index)
2985 : HBinaryOperation(string, index) {
2986 set_representation(Representation::Integer32());
2987 SetFlag(kUseGVN);
2988 }
2989
2990 virtual Representation RequiredInputRepresentation(int index) const {
2991 // The index is supposed to be Integer32.
2992 return (index == 1) ? Representation::Integer32()
2993 : Representation::Tagged();
2994 }
2995
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002996 HValue* string() const { return OperandAt(0); }
2997 HValue* index() const { return OperandAt(1); }
2998
2999 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string_char_code_at")
3000
3001 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00003002 virtual bool DataEquals(HValue* other) const { return true; }
3003
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003004 virtual Range* InferRange() {
3005 return new Range(0, String::kMaxUC16CharCode);
3006 }
3007};
3008
3009
3010class HStringLength: public HUnaryOperation {
3011 public:
3012 explicit HStringLength(HValue* string) : HUnaryOperation(string) {
3013 set_representation(Representation::Tagged());
3014 SetFlag(kUseGVN);
3015 }
3016
3017 virtual Representation RequiredInputRepresentation(int index) const {
3018 return Representation::Tagged();
3019 }
3020
3021 virtual HType CalculateInferredType() const {
3022 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
3023 return HType::Smi();
3024 }
3025
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003026 DECLARE_CONCRETE_INSTRUCTION(StringLength, "string_length")
3027
3028 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00003029 virtual bool DataEquals(HValue* other) const { return true; }
3030
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003031 virtual Range* InferRange() {
3032 return new Range(0, String::kMaxLength);
3033 }
3034};
3035
3036
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003037class HMaterializedLiteral: public HInstruction {
3038 public:
3039 HMaterializedLiteral(int index, int depth)
3040 : literal_index_(index), depth_(depth) {
3041 set_representation(Representation::Tagged());
3042 }
3043
3044 int literal_index() const { return literal_index_; }
3045 int depth() const { return depth_; }
3046
3047 DECLARE_INSTRUCTION(MaterializedLiteral)
3048
3049 private:
3050 int literal_index_;
3051 int depth_;
3052};
3053
3054
3055class HArrayLiteral: public HMaterializedLiteral {
3056 public:
3057 HArrayLiteral(Handle<FixedArray> constant_elements,
3058 int length,
3059 int literal_index,
3060 int depth)
3061 : HMaterializedLiteral(literal_index, depth),
3062 length_(length),
3063 constant_elements_(constant_elements) {}
3064
3065 Handle<FixedArray> constant_elements() const { return constant_elements_; }
3066 int length() const { return length_; }
3067
3068 bool IsCopyOnWrite() const;
3069
3070 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
3071
3072 private:
3073 int length_;
3074 Handle<FixedArray> constant_elements_;
3075};
3076
3077
3078class HObjectLiteral: public HMaterializedLiteral {
3079 public:
3080 HObjectLiteral(Handle<FixedArray> constant_properties,
3081 bool fast_elements,
3082 int literal_index,
3083 int depth)
3084 : HMaterializedLiteral(literal_index, depth),
3085 constant_properties_(constant_properties),
3086 fast_elements_(fast_elements) {}
3087
3088 Handle<FixedArray> constant_properties() const {
3089 return constant_properties_;
3090 }
3091 bool fast_elements() const { return fast_elements_; }
3092
3093 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
3094
3095 private:
3096 Handle<FixedArray> constant_properties_;
3097 bool fast_elements_;
3098};
3099
3100
3101class HRegExpLiteral: public HMaterializedLiteral {
3102 public:
3103 HRegExpLiteral(Handle<String> pattern,
3104 Handle<String> flags,
3105 int literal_index)
3106 : HMaterializedLiteral(literal_index, 0),
3107 pattern_(pattern),
3108 flags_(flags) { }
3109
3110 Handle<String> pattern() { return pattern_; }
3111 Handle<String> flags() { return flags_; }
3112
3113 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
3114
3115 private:
3116 Handle<String> pattern_;
3117 Handle<String> flags_;
3118};
3119
3120
3121class HFunctionLiteral: public HInstruction {
3122 public:
3123 HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
3124 : shared_info_(shared), pretenure_(pretenure) {
3125 set_representation(Representation::Tagged());
3126 }
3127
3128 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
3129
3130 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
3131 bool pretenure() const { return pretenure_; }
3132
3133 private:
3134 Handle<SharedFunctionInfo> shared_info_;
3135 bool pretenure_;
3136};
3137
3138
3139class HTypeof: public HUnaryOperation {
3140 public:
3141 explicit HTypeof(HValue* value) : HUnaryOperation(value) {
3142 set_representation(Representation::Tagged());
3143 }
3144
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003145 virtual Representation RequiredInputRepresentation(int index) const {
3146 return Representation::Tagged();
3147 }
3148
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003149 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
3150};
3151
3152
3153class HValueOf: public HUnaryOperation {
3154 public:
3155 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
3156 set_representation(Representation::Tagged());
3157 }
3158
3159 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
3160};
3161
3162
3163class HDeleteProperty: public HBinaryOperation {
3164 public:
3165 HDeleteProperty(HValue* obj, HValue* key)
3166 : HBinaryOperation(obj, key) {
3167 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00003168 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003169 }
3170
3171 virtual Representation RequiredInputRepresentation(int index) const {
3172 return Representation::Tagged();
3173 }
3174
3175 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
3176
3177 HValue* object() const { return left(); }
3178 HValue* key() const { return right(); }
3179};
3180
3181#undef DECLARE_INSTRUCTION
3182#undef DECLARE_CONCRETE_INSTRUCTION
3183
3184} } // namespace v8::internal
3185
3186#endif // V8_HYDROGEN_INSTRUCTIONS_H_