blob: a0d932fbd24311f8eeb613edc706e6002cadd60b [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) \
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000051 V(BinaryCall) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000052 V(BinaryOperation) \
53 V(BitwiseBinaryOperation) \
54 V(Call) \
55 V(ControlInstruction) \
56 V(Instruction) \
57 V(LoadKeyed) \
58 V(MaterializedLiteral) \
59 V(Phi) \
60 V(StoreKeyed) \
61 V(StoreNamed) \
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000062 V(UnaryCall) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000063 V(UnaryControlInstruction) \
64 V(UnaryOperation) \
65 HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
66
67
68#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
kmillikin@chromium.org31b12772011-02-02 16:08:26 +000069 V(AbnormalExit) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000070 V(AccessArgumentsAt) \
71 V(Add) \
72 V(ApplyArguments) \
73 V(ArgumentsElements) \
74 V(ArgumentsLength) \
75 V(ArgumentsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000076 V(ArrayLiteral) \
77 V(BitAnd) \
78 V(BitNot) \
79 V(BitOr) \
80 V(BitXor) \
81 V(BlockEntry) \
82 V(BoundsCheck) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000083 V(CallConstantFunction) \
84 V(CallFunction) \
85 V(CallGlobal) \
86 V(CallKeyed) \
87 V(CallKnownGlobal) \
88 V(CallNamed) \
89 V(CallNew) \
90 V(CallRuntime) \
91 V(CallStub) \
92 V(Change) \
93 V(CheckFunction) \
94 V(CheckInstanceType) \
95 V(CheckMap) \
96 V(CheckNonSmi) \
97 V(CheckPrototypeMaps) \
98 V(CheckSmi) \
99 V(Compare) \
100 V(CompareJSObjectEq) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000101 V(CompareMap) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000102 V(Constant) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000103 V(Context) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000104 V(DeleteProperty) \
105 V(Deoptimize) \
106 V(Div) \
107 V(EnterInlined) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000108 V(FixedArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000109 V(FunctionLiteral) \
110 V(GlobalObject) \
111 V(GlobalReceiver) \
112 V(Goto) \
113 V(InstanceOf) \
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000114 V(InstanceOfKnownGlobal) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000115 V(IsNull) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000116 V(IsObject) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117 V(IsSmi) \
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000118 V(IsConstructCall) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000119 V(HasInstanceType) \
120 V(HasCachedArrayIndex) \
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000121 V(JSArrayLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000122 V(ClassOfTest) \
123 V(LeaveInlined) \
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000124 V(LoadContextSlot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000125 V(LoadElements) \
ager@chromium.org378b34e2011-01-28 08:04:38 +0000126 V(LoadFunctionPrototype) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000127 V(LoadGlobal) \
128 V(LoadKeyedFastElement) \
129 V(LoadKeyedGeneric) \
130 V(LoadNamedField) \
131 V(LoadNamedGeneric) \
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000132 V(LoadPixelArrayElement) \
133 V(LoadPixelArrayExternalPointer) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000134 V(Mod) \
135 V(Mul) \
136 V(ObjectLiteral) \
137 V(OsrEntry) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000138 V(OuterContext) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000139 V(Parameter) \
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000140 V(PixelArrayLength) \
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000141 V(Power) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000142 V(PushArgument) \
143 V(RegExpLiteral) \
144 V(Return) \
145 V(Sar) \
146 V(Shl) \
147 V(Shr) \
148 V(Simulate) \
149 V(StackCheck) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000150 V(StoreContextSlot) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000151 V(StoreGlobal) \
152 V(StoreKeyedFastElement) \
153 V(StoreKeyedGeneric) \
154 V(StoreNamedField) \
155 V(StoreNamedGeneric) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000156 V(StringCharCodeAt) \
157 V(StringLength) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000158 V(Sub) \
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000159 V(Test) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000160 V(Throw) \
161 V(Typeof) \
162 V(TypeofIs) \
163 V(UnaryMathOperation) \
164 V(UnknownOSRValue) \
165 V(ValueOf)
166
167#define GVN_FLAG_LIST(V) \
168 V(Calls) \
169 V(InobjectFields) \
170 V(BackingStoreFields) \
171 V(ArrayElements) \
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000172 V(PixelArrayElements) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000173 V(GlobalVars) \
174 V(Maps) \
175 V(ArrayLengths) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000176 V(ContextSlots) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000177 V(OsrEntries)
178
179#define DECLARE_INSTRUCTION(type) \
180 virtual bool Is##type() const { return true; } \
181 static H##type* cast(HValue* value) { \
182 ASSERT(value->Is##type()); \
183 return reinterpret_cast<H##type*>(value); \
184 } \
185 Opcode opcode() const { return HValue::k##type; }
186
187
188#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
189 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
190 virtual const char* Mnemonic() const { return mnemonic; } \
191 DECLARE_INSTRUCTION(type)
192
193
194
195template<int kSize>
196class HOperandVector : public EmbeddedVector<HValue*, kSize> {
197 public:
198 HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
199};
200
201
202class Range: public ZoneObject {
203 public:
204 Range() : lower_(kMinInt),
205 upper_(kMaxInt),
206 next_(NULL),
207 can_be_minus_zero_(false) { }
208
209 Range(int32_t lower, int32_t upper)
210 : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
211
212 bool IsInSmiRange() const {
213 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
214 }
215 void KeepOrder();
216 void Verify() const;
217 int32_t upper() const { return upper_; }
218 int32_t lower() const { return lower_; }
219 Range* next() const { return next_; }
220 Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
221 Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
222 void ClearLower() { lower_ = kMinInt; }
223 void ClearUpper() { upper_ = kMaxInt; }
224 Range* Copy() const { return new Range(lower_, upper_); }
225 bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
226 int32_t Mask() const;
227 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
228 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
229 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
230 bool CanBeNegative() const { return lower_ < 0; }
231 bool Includes(int value) const {
232 return lower_ <= value && upper_ >= value;
233 }
234
235 void Sar(int32_t value) {
236 int32_t bits = value & 0x1F;
237 lower_ = lower_ >> bits;
238 upper_ = upper_ >> bits;
239 set_can_be_minus_zero(false);
240 }
241
242 void Shl(int32_t value) {
243 int32_t bits = value & 0x1F;
244 int old_lower = lower_;
245 int old_upper = upper_;
246 lower_ = lower_ << bits;
247 upper_ = upper_ << bits;
248 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
249 upper_ = kMaxInt;
250 lower_ = kMinInt;
251 }
252 set_can_be_minus_zero(false);
253 }
254
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000255 // Adds a constant to the lower and upper bound of the range.
256 void AddConstant(int32_t value);
257
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000258 void StackUpon(Range* other) {
259 Intersect(other);
260 next_ = other;
261 }
262
263 void Intersect(Range* other) {
264 upper_ = Min(upper_, other->upper_);
265 lower_ = Max(lower_, other->lower_);
266 bool b = CanBeMinusZero() && other->CanBeMinusZero();
267 set_can_be_minus_zero(b);
268 }
269
270 void Union(Range* other) {
271 upper_ = Max(upper_, other->upper_);
272 lower_ = Min(lower_, other->lower_);
273 bool b = CanBeMinusZero() || other->CanBeMinusZero();
274 set_can_be_minus_zero(b);
275 }
276
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000277 // Compute a new result range and return true, if the operation
278 // can overflow.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000279 bool AddAndCheckOverflow(Range* other);
280 bool SubAndCheckOverflow(Range* other);
281 bool MulAndCheckOverflow(Range* other);
282
283 private:
284 int32_t lower_;
285 int32_t upper_;
286 Range* next_;
287 bool can_be_minus_zero_;
288};
289
290
291class Representation {
292 public:
293 enum Kind {
294 kNone,
295 kTagged,
296 kDouble,
297 kInteger32,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000298 kExternal,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000299 kNumRepresentations
300 };
301
302 Representation() : kind_(kNone) { }
303
304 static Representation None() { return Representation(kNone); }
305 static Representation Tagged() { return Representation(kTagged); }
306 static Representation Integer32() { return Representation(kInteger32); }
307 static Representation Double() { return Representation(kDouble); }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000308 static Representation External() { return Representation(kExternal); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000309
310 bool Equals(const Representation& other) const {
311 return kind_ == other.kind_;
312 }
313
314 Kind kind() const { return kind_; }
315 bool IsNone() const { return kind_ == kNone; }
316 bool IsTagged() const { return kind_ == kTagged; }
317 bool IsInteger32() const { return kind_ == kInteger32; }
318 bool IsDouble() const { return kind_ == kDouble; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000319 bool IsExternal() const { return kind_ == kExternal; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000320 bool IsSpecialization() const {
321 return kind_ == kInteger32 || kind_ == kDouble;
322 }
323 const char* Mnemonic() const;
324
325 private:
326 explicit Representation(Kind k) : kind_(k) { }
327
328 Kind kind_;
329};
330
331
332class HType {
333 public:
334 HType() : type_(kUninitialized) { }
335
336 static HType Tagged() { return HType(kTagged); }
337 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
338 static HType TaggedNumber() { return HType(kTaggedNumber); }
339 static HType Smi() { return HType(kSmi); }
340 static HType HeapNumber() { return HType(kHeapNumber); }
341 static HType String() { return HType(kString); }
342 static HType Boolean() { return HType(kBoolean); }
343 static HType NonPrimitive() { return HType(kNonPrimitive); }
344 static HType JSArray() { return HType(kJSArray); }
345 static HType JSObject() { return HType(kJSObject); }
346 static HType Uninitialized() { return HType(kUninitialized); }
347
348 // Return the weakest (least precise) common type.
349 HType Combine(HType other) {
350 return HType(static_cast<Type>(type_ & other.type_));
351 }
352
353 bool Equals(const HType& other) {
354 return type_ == other.type_;
355 }
356
357 bool IsSubtypeOf(const HType& other) {
358 return Combine(other).Equals(other);
359 }
360
361 bool IsTagged() {
362 ASSERT(type_ != kUninitialized);
363 return ((type_ & kTagged) == kTagged);
364 }
365
366 bool IsTaggedPrimitive() {
367 ASSERT(type_ != kUninitialized);
368 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
369 }
370
371 bool IsTaggedNumber() {
372 ASSERT(type_ != kUninitialized);
373 return ((type_ & kTaggedNumber) == kTaggedNumber);
374 }
375
376 bool IsSmi() {
377 ASSERT(type_ != kUninitialized);
378 return ((type_ & kSmi) == kSmi);
379 }
380
381 bool IsHeapNumber() {
382 ASSERT(type_ != kUninitialized);
383 return ((type_ & kHeapNumber) == kHeapNumber);
384 }
385
386 bool IsString() {
387 ASSERT(type_ != kUninitialized);
388 return ((type_ & kString) == kString);
389 }
390
391 bool IsBoolean() {
392 ASSERT(type_ != kUninitialized);
393 return ((type_ & kBoolean) == kBoolean);
394 }
395
396 bool IsNonPrimitive() {
397 ASSERT(type_ != kUninitialized);
398 return ((type_ & kNonPrimitive) == kNonPrimitive);
399 }
400
401 bool IsJSArray() {
402 ASSERT(type_ != kUninitialized);
403 return ((type_ & kJSArray) == kJSArray);
404 }
405
406 bool IsJSObject() {
407 ASSERT(type_ != kUninitialized);
408 return ((type_ & kJSObject) == kJSObject);
409 }
410
411 bool IsUninitialized() {
412 return type_ == kUninitialized;
413 }
414
415 static HType TypeFromValue(Handle<Object> value);
416
417 const char* ToString();
418 const char* ToShortString();
419
420 private:
421 enum Type {
422 kTagged = 0x1, // 0000 0000 0000 0001
423 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
424 kTaggedNumber = 0xd, // 0000 0000 0000 1101
425 kSmi = 0x1d, // 0000 0000 0001 1101
426 kHeapNumber = 0x2d, // 0000 0000 0010 1101
427 kString = 0x45, // 0000 0000 0100 0101
428 kBoolean = 0x85, // 0000 0000 1000 0101
429 kNonPrimitive = 0x101, // 0000 0001 0000 0001
430 kJSObject = 0x301, // 0000 0011 0000 0001
431 kJSArray = 0x701, // 0000 0111 1000 0001
432 kUninitialized = 0x1fff // 0001 1111 1111 1111
433 };
434
435 explicit HType(Type t) : type_(t) { }
436
437 Type type_;
438};
439
440
441class HValue: public ZoneObject {
442 public:
443 static const int kNoNumber = -1;
444
445 // There must be one corresponding kDepends flag for every kChanges flag and
446 // the order of the kChanges flags must be exactly the same as of the kDepends
447 // flags.
448 enum Flag {
449 // Declare global value numbering flags.
450 #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
451 GVN_FLAG_LIST(DECLARE_DO)
452 #undef DECLARE_DO
453 kFlexibleRepresentation,
454 kUseGVN,
455 kCanOverflow,
456 kBailoutOnMinusZero,
457 kCanBeDivByZero,
458 kIsArguments,
459 kTruncatingToInt32,
460 kLastFlag = kTruncatingToInt32
461 };
462
463 STATIC_ASSERT(kLastFlag < kBitsPerInt);
464
465 static const int kChangesToDependsFlagsLeftShift = 1;
466
467 static int ChangesFlagsMask() {
468 int result = 0;
469 // Create changes mask.
470#define DECLARE_DO(type) result |= (1 << kChanges##type);
471 GVN_FLAG_LIST(DECLARE_DO)
472#undef DECLARE_DO
473 return result;
474 }
475
476 static int DependsFlagsMask() {
477 return ConvertChangesToDependsFlags(ChangesFlagsMask());
478 }
479
480 static int ConvertChangesToDependsFlags(int flags) {
481 return flags << kChangesToDependsFlagsLeftShift;
482 }
483
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000484 static HValue* cast(HValue* value) { return value; }
485
486 enum Opcode {
487 // Declare a unique enum value for each hydrogen instruction.
488 #define DECLARE_DO(type) k##type,
489 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
490 #undef DECLARE_DO
491 kMaxInstructionClass
492 };
493
494 HValue() : block_(NULL),
495 id_(kNoNumber),
496 uses_(2),
497 type_(HType::Tagged()),
498 range_(NULL),
499 flags_(0) {}
500 virtual ~HValue() {}
501
502 HBasicBlock* block() const { return block_; }
503 void SetBlock(HBasicBlock* block);
504
505 int id() const { return id_; }
506 void set_id(int id) { id_ = id; }
507
508 const ZoneList<HValue*>* uses() const { return &uses_; }
509
510 virtual bool EmitAtUses() const { return false; }
511 Representation representation() const { return representation_; }
512 void ChangeRepresentation(Representation r) {
513 // Representation was already set and is allowed to be changed.
514 ASSERT(!representation_.IsNone());
515 ASSERT(!r.IsNone());
516 ASSERT(CheckFlag(kFlexibleRepresentation));
517 RepresentationChanged(r);
518 representation_ = r;
519 }
520
521 HType type() const { return type_; }
522 void set_type(HType type) {
523 ASSERT(uses_.length() == 0);
524 type_ = type;
525 }
526
527 // An operation needs to override this function iff:
528 // 1) it can produce an int32 output.
529 // 2) the true value of its output can potentially be minus zero.
530 // The implementation must set a flag so that it bails out in the case where
531 // it would otherwise output what should be a minus zero as an int32 zero.
532 // If the operation also exists in a form that takes int32 and outputs int32
533 // then the operation should return its input value so that we can propagate
534 // back. There are two operations that need to propagate back to more than
535 // one input. They are phi and binary add. They always return NULL and
536 // expect the caller to take care of things.
537 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
538 visited->Add(id());
539 return NULL;
540 }
541
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000542 bool IsDefinedAfter(HBasicBlock* other) const;
543
544 // Operands.
545 virtual int OperandCount() const { return 0; }
546 virtual HValue* OperandAt(int index) const {
547 UNREACHABLE();
548 return NULL;
549 }
550 void SetOperandAt(int index, HValue* value);
551
552 int LookupOperandIndex(int occurrence_index, HValue* op) const;
553 bool UsesMultipleTimes(HValue* op) const;
554
555 void ReplaceAndDelete(HValue* other);
556 void ReplaceValue(HValue* other);
557 void ReplaceAtUse(HValue* use, HValue* other);
558 void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
559 bool HasNoUses() const { return uses_.is_empty(); }
560 void ClearOperands();
561 void Delete();
562
563 int flags() const { return flags_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000564 void SetFlag(Flag f) { flags_ |= (1 << f); }
565 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
566 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
567
568 void SetAllSideEffects() { flags_ |= AllSideEffects(); }
569 void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
570 bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000571
572 Range* range() const { return range_; }
573 bool HasRange() const { return range_ != NULL; }
574 void AddNewRange(Range* r);
575 void RemoveLastAddedRange();
576 void ComputeInitialRange();
577
578 // Representation helpers.
579 virtual Representation RequiredInputRepresentation(int index) const {
580 return Representation::None();
581 }
582 virtual Representation InferredRepresentation() const {
583 return representation();
584 }
585
586 // This gives the instruction an opportunity to replace itself with an
587 // instruction that does the same in some better way. To replace an
588 // instruction with a new one, first add the new instruction to the graph,
589 // then return it. Return NULL to have the instruction deleted.
590 virtual HValue* Canonicalize() { return this; }
591
592 // Declare virtual type testers.
593#define DECLARE_DO(type) virtual bool Is##type() const { return false; }
594 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
595#undef DECLARE_DO
596
597 bool Equals(HValue* other) const;
598 virtual intptr_t Hashcode() const;
599
600 // Printing support.
601 virtual void PrintTo(StringStream* stream) const = 0;
602 void PrintNameTo(StringStream* stream);
603 static void PrintTypeTo(HType type, StringStream* stream);
604
605 virtual const char* Mnemonic() const = 0;
606 virtual Opcode opcode() const = 0;
607
608 // Updated the inferred type of this instruction and returns true if
609 // it has changed.
610 bool UpdateInferredType();
611
612 virtual HType CalculateInferredType() const;
613
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000614#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000615 virtual void Verify() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000616#endif
617
618 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000619 // This function must be overridden for instructions with flag kUseGVN, to
620 // compare the non-Operand parts of the instruction.
621 virtual bool DataEquals(HValue* other) const {
622 UNREACHABLE();
623 return false;
624 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000625 virtual void RepresentationChanged(Representation to) { }
626 virtual Range* InferRange();
627 virtual void DeleteFromGraph() = 0;
628 virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
629 void clear_block() {
630 ASSERT(block_ != NULL);
631 block_ = NULL;
632 }
633
634 void set_representation(Representation r) {
635 // Representation is set-once.
636 ASSERT(representation_.IsNone() && !r.IsNone());
637 representation_ = r;
638 }
639
640 private:
ager@chromium.org378b34e2011-01-28 08:04:38 +0000641 // A flag mask to mark an instruction as having arbitrary side effects.
642 static int AllSideEffects() {
643 return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
644 }
645
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000646 void InternalReplaceAtUse(HValue* use, HValue* other);
647 void RegisterUse(int index, HValue* new_value);
648
649 HBasicBlock* block_;
650
651 // The id of this instruction in the hydrogen graph, assigned when first
652 // added to the graph. Reflects creation order.
653 int id_;
654
655 Representation representation_;
656 ZoneList<HValue*> uses_;
657 HType type_;
658 Range* range_;
659 int flags_;
660
661 DISALLOW_COPY_AND_ASSIGN(HValue);
662};
663
664
665class HInstruction: public HValue {
666 public:
667 HInstruction* next() const { return next_; }
668 HInstruction* previous() const { return previous_; }
669
670 void PrintTo(StringStream* stream) const;
671 virtual void PrintDataTo(StringStream* stream) const {}
672
673 bool IsLinked() const { return block() != NULL; }
674 void Unlink();
675 void InsertBefore(HInstruction* next);
676 void InsertAfter(HInstruction* previous);
677
678 int position() const { return position_; }
679 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
680 void set_position(int position) { position_ = position; }
681
682 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
683
684#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000685 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000686#endif
687
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000688 // Returns whether this is some kind of deoptimizing check
689 // instruction.
690 virtual bool IsCheckInstruction() const { return false; }
691
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000692 DECLARE_INSTRUCTION(Instruction)
693
694 protected:
695 HInstruction()
696 : next_(NULL),
697 previous_(NULL),
698 position_(RelocInfo::kNoPosition) {
699 SetFlag(kDependsOnOsrEntries);
700 }
701
702 virtual void DeleteFromGraph() { Unlink(); }
703
704 private:
705 void InitializeAsFirst(HBasicBlock* block) {
706 ASSERT(!IsLinked());
707 SetBlock(block);
708 }
709
710 HInstruction* next_;
711 HInstruction* previous_;
712 int position_;
713
714 friend class HBasicBlock;
715};
716
717
718class HBlockEntry: public HInstruction {
719 public:
720 DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
721};
722
723
724class HControlInstruction: public HInstruction {
725 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000726 HControlInstruction(HBasicBlock* first, HBasicBlock* second)
727 : first_successor_(first), second_successor_(second) {
728 }
729
730 HBasicBlock* FirstSuccessor() const { return first_successor_; }
731 HBasicBlock* SecondSuccessor() const { return second_successor_; }
732
733 virtual void PrintDataTo(StringStream* stream) const;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000734
735 DECLARE_INSTRUCTION(ControlInstruction)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000736
737 private:
738 HBasicBlock* first_successor_;
739 HBasicBlock* second_successor_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000740};
741
742
743class HDeoptimize: public HControlInstruction {
744 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000745 HDeoptimize() : HControlInstruction(NULL, NULL) { }
746
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000747 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
748};
749
750
751class HGoto: public HControlInstruction {
752 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000753 explicit HGoto(HBasicBlock* target)
754 : HControlInstruction(target, NULL), include_stack_check_(false) {
755 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000756
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000757 void set_include_stack_check(bool include_stack_check) {
758 include_stack_check_ = include_stack_check;
759 }
760 bool include_stack_check() const { return include_stack_check_; }
761
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000762 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
763
764 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000765 bool include_stack_check_;
766};
767
768
769class HUnaryControlInstruction: public HControlInstruction {
770 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000771 explicit HUnaryControlInstruction(HValue* value,
772 HBasicBlock* true_target,
773 HBasicBlock* false_target)
774 : HControlInstruction(true_target, false_target) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000775 SetOperandAt(0, value);
776 }
777
778 virtual Representation RequiredInputRepresentation(int index) const {
779 return Representation::Tagged();
780 }
781
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000782 virtual void PrintDataTo(StringStream* stream) const;
783
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000784 HValue* value() const { return OperandAt(0); }
785 virtual int OperandCount() const { return 1; }
786 virtual HValue* OperandAt(int index) const { return operands_[index]; }
787
788 DECLARE_INSTRUCTION(UnaryControlInstruction)
789
790 protected:
791 virtual void InternalSetOperandAt(int index, HValue* value) {
792 operands_[index] = value;
793 }
794
795 private:
796 HOperandVector<1> operands_;
797};
798
799
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000800class HTest: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000801 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000802 HTest(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target)
803 : HUnaryControlInstruction(value, true_target, false_target) {
804 ASSERT(true_target != NULL && false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000805 }
806
807 virtual Representation RequiredInputRepresentation(int index) const {
808 return Representation::None();
809 }
810
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000811 DECLARE_CONCRETE_INSTRUCTION(Test, "test")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000812};
813
814
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000815class HCompareMap: public HUnaryControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000816 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000817 HCompareMap(HValue* value,
818 Handle<Map> map,
819 HBasicBlock* true_target,
820 HBasicBlock* false_target)
821 : HUnaryControlInstruction(value, true_target, false_target),
822 map_(map) {
823 ASSERT(true_target != NULL);
824 ASSERT(false_target != NULL);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000825 ASSERT(!map.is_null());
826 }
827
whesse@chromium.org023421e2010-12-21 12:19:12 +0000828 virtual void PrintDataTo(StringStream* stream) const;
829
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000830 Handle<Map> map() const { return map_; }
831
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000832 DECLARE_CONCRETE_INSTRUCTION(CompareMap, "compare_map")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000833
834 private:
835 Handle<Map> map_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000836};
837
838
839class HReturn: public HUnaryControlInstruction {
840 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000841 explicit HReturn(HValue* value)
842 : HUnaryControlInstruction(value, NULL, NULL) {
843 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000844
845 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
846};
847
848
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000849class HAbnormalExit: public HControlInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000850 public:
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000851 HAbnormalExit() : HControlInstruction(NULL, NULL) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000852
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000853 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000854};
855
856
857class HUnaryOperation: public HInstruction {
858 public:
859 explicit HUnaryOperation(HValue* value) {
860 SetOperandAt(0, value);
861 }
862
863 HValue* value() const { return OperandAt(0); }
864 virtual void PrintDataTo(StringStream* stream) const;
865 virtual int OperandCount() const { return 1; }
866 virtual HValue* OperandAt(int index) const { return operands_[index]; }
867
868 DECLARE_INSTRUCTION(UnaryOperation)
869
870 protected:
871 virtual void InternalSetOperandAt(int index, HValue* value) {
872 operands_[index] = value;
873 }
874
875 private:
876 HOperandVector<1> operands_;
877};
878
879
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000880class HThrow: public HUnaryOperation {
881 public:
882 explicit HThrow(HValue* value) : HUnaryOperation(value) {
883 SetAllSideEffects();
884 }
885
886 virtual Representation RequiredInputRepresentation(int index) const {
887 return Representation::Tagged();
888 }
889
890 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
891};
892
893
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000894class HChange: public HUnaryOperation {
895 public:
896 HChange(HValue* value,
897 Representation from,
898 Representation to)
899 : HUnaryOperation(value), from_(from), to_(to) {
900 ASSERT(!from.IsNone() && !to.IsNone());
901 ASSERT(!from.Equals(to));
902 set_representation(to);
903 SetFlag(kUseGVN);
904
905 if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
906 value->range()->IsInSmiRange()) {
907 set_type(HType::Smi());
908 }
909 }
910
911 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
912
913 Representation from() const { return from_; }
914 Representation to() const { return to_; }
915 virtual Representation RequiredInputRepresentation(int index) const {
916 return from_;
917 }
918
919 bool CanTruncateToInt32() const {
920 for (int i = 0; i < uses()->length(); ++i) {
921 if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
922 }
923 return true;
924 }
925
926 virtual void PrintDataTo(StringStream* stream) const;
927
928 DECLARE_CONCRETE_INSTRUCTION(Change,
929 CanTruncateToInt32() ? "truncate" : "change")
930
931 protected:
932 virtual bool DataEquals(HValue* other) const {
933 if (!other->IsChange()) return false;
934 HChange* change = HChange::cast(other);
935 return value() == change->value()
936 && to().Equals(change->to())
937 && CanTruncateToInt32() == change->CanTruncateToInt32();
938 }
939
940 private:
941 Representation from_;
942 Representation to_;
943};
944
945
946class HSimulate: public HInstruction {
947 public:
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000948 HSimulate(int ast_id, int pop_count, int environment_length)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000949 : ast_id_(ast_id),
950 pop_count_(pop_count),
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000951 environment_length_(environment_length),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000952 values_(2),
953 assigned_indexes_(2) {}
954 virtual ~HSimulate() {}
955
956 virtual void PrintDataTo(StringStream* stream) const;
957
958 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
959 int ast_id() const { return ast_id_; }
960 void set_ast_id(int id) {
961 ASSERT(!HasAstId());
962 ast_id_ = id;
963 }
964
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000965 int environment_length() const { return environment_length_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000966 int pop_count() const { return pop_count_; }
967 const ZoneList<HValue*>* values() const { return &values_; }
968 int GetAssignedIndexAt(int index) const {
969 ASSERT(HasAssignedIndexAt(index));
970 return assigned_indexes_[index];
971 }
972 bool HasAssignedIndexAt(int index) const {
973 return assigned_indexes_[index] != kNoIndex;
974 }
975 void AddAssignedValue(int index, HValue* value) {
976 AddValue(index, value);
977 }
978 void AddPushedValue(HValue* value) {
979 AddValue(kNoIndex, value);
980 }
981 virtual int OperandCount() const { return values_.length(); }
982 virtual HValue* OperandAt(int index) const { return values_[index]; }
983
984 DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
985
986#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000987 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000988#endif
989
990 protected:
991 virtual void InternalSetOperandAt(int index, HValue* value) {
992 values_[index] = value;
993 }
994
995 private:
996 static const int kNoIndex = -1;
997 void AddValue(int index, HValue* value) {
998 assigned_indexes_.Add(index);
999 // Resize the list of pushed values.
1000 values_.Add(NULL);
1001 // Set the operand through the base method in HValue to make sure that the
1002 // use lists are correctly updated.
1003 SetOperandAt(values_.length() - 1, value);
1004 }
1005 int ast_id_;
1006 int pop_count_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001007 int environment_length_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001008 ZoneList<HValue*> values_;
1009 ZoneList<int> assigned_indexes_;
1010};
1011
1012
1013class HStackCheck: public HInstruction {
1014 public:
1015 HStackCheck() { }
1016
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001017 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001018};
1019
1020
1021class HEnterInlined: public HInstruction {
1022 public:
1023 HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
1024 : closure_(closure), function_(function) {
1025 }
1026
1027 virtual void PrintDataTo(StringStream* stream) const;
1028
1029 Handle<JSFunction> closure() const { return closure_; }
1030 FunctionLiteral* function() const { return function_; }
1031
1032 DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
1033
1034 private:
1035 Handle<JSFunction> closure_;
1036 FunctionLiteral* function_;
1037};
1038
1039
1040class HLeaveInlined: public HInstruction {
1041 public:
1042 HLeaveInlined() {}
1043
1044 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
1045};
1046
1047
1048class HPushArgument: public HUnaryOperation {
1049 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001050 explicit HPushArgument(HValue* value) : HUnaryOperation(value) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001051
1052 virtual Representation RequiredInputRepresentation(int index) const {
1053 return Representation::Tagged();
1054 }
1055
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001056 HValue* argument() const { return OperandAt(0); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001057
1058 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001059};
1060
1061
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001062class HContext: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001063 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001064 HContext() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001065 set_representation(Representation::Tagged());
1066 SetFlag(kUseGVN);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001067 }
1068
1069 DECLARE_CONCRETE_INSTRUCTION(Context, "context");
1070
1071 protected:
1072 virtual bool DataEquals(HValue* other) const { return true; }
1073};
1074
1075
1076class HOuterContext: public HUnaryOperation {
1077 public:
1078 explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
1079 set_representation(Representation::Tagged());
1080 SetFlag(kUseGVN);
1081 }
1082
1083 DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer_context");
1084
1085 protected:
1086 virtual bool DataEquals(HValue* other) const { return true; }
1087};
1088
1089
1090class HGlobalObject: public HUnaryOperation {
1091 public:
1092 explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
1093 set_representation(Representation::Tagged());
1094 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001095 }
1096
1097 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001098
1099 protected:
1100 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001101};
1102
1103
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001104class HGlobalReceiver: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001105 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001106 explicit HGlobalReceiver(HValue* global_object)
1107 : HUnaryOperation(global_object) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001108 set_representation(Representation::Tagged());
1109 SetFlag(kUseGVN);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001110 }
1111
1112 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001113
1114 protected:
1115 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001116};
1117
1118
1119class HCall: public HInstruction {
1120 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001121 // The argument count includes the receiver.
1122 explicit HCall(int argument_count) : argument_count_(argument_count) {
1123 set_representation(Representation::Tagged());
1124 SetAllSideEffects();
1125 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001126
1127 virtual HType CalculateInferredType() const { return HType::Tagged(); }
1128
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001129 virtual int argument_count() const { return argument_count_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001130
1131 virtual void PrintDataTo(StringStream* stream) const;
1132
1133 DECLARE_INSTRUCTION(Call)
1134
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001135 private:
1136 int argument_count_;
1137};
1138
1139
1140class HUnaryCall: public HCall {
1141 public:
1142 HUnaryCall(HValue* value, int argument_count)
1143 : HCall(argument_count), value_(NULL) {
1144 SetOperandAt(0, value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001145 }
1146
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001147 virtual void PrintDataTo(StringStream* stream) const;
1148
1149 HValue* value() const { return value_; }
1150
1151 virtual int OperandCount() const { return 1; }
1152 virtual HValue* OperandAt(int index) const {
1153 ASSERT(index == 0);
1154 return value_;
1155 }
1156
1157 DECLARE_INSTRUCTION(UnaryCall)
1158
1159 protected:
1160 virtual void InternalSetOperandAt(int index, HValue* value) {
1161 ASSERT(index == 0);
1162 value_ = value;
1163 }
1164
1165 private:
1166 HValue* value_;
1167};
1168
1169
1170class HBinaryCall: public HCall {
1171 public:
1172 HBinaryCall(HValue* first, HValue* second, int argument_count)
1173 : HCall(argument_count) {
1174 SetOperandAt(0, first);
1175 SetOperandAt(1, second);
1176 }
1177
1178 virtual void PrintDataTo(StringStream* stream) const;
1179
1180 HValue* first() const { return operands_[0]; }
1181 HValue* second() const { return operands_[1]; }
1182
1183 virtual int OperandCount() const { return 2; }
1184 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1185
1186 DECLARE_INSTRUCTION(BinaryCall)
1187
1188 protected:
1189 virtual void InternalSetOperandAt(int index, HValue* value) {
1190 operands_[index] = value;
1191 }
1192
1193 private:
1194 HOperandVector<2> operands_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001195};
1196
1197
1198class HCallConstantFunction: public HCall {
1199 public:
1200 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1201 : HCall(argument_count), function_(function) { }
1202
1203 Handle<JSFunction> function() const { return function_; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001204
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001205 bool IsApplyFunction() const {
1206 return function_->code() == Builtins::builtin(Builtins::FunctionApply);
1207 }
1208
1209 virtual void PrintDataTo(StringStream* stream) const;
1210
1211 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
1212
1213 private:
1214 Handle<JSFunction> function_;
1215};
1216
1217
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001218class HCallKeyed: public HBinaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001219 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001220 HCallKeyed(HValue* context, HValue* key, int argument_count)
1221 : HBinaryCall(context, key, argument_count) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001222 }
1223
1224 virtual Representation RequiredInputRepresentation(int index) const {
1225 return Representation::Tagged();
1226 }
1227
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001228 HValue* context() const { return first(); }
1229 HValue* key() const { return second(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001230
1231 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
1232};
1233
1234
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001235class HCallNamed: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001236 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001237 HCallNamed(HValue* context, Handle<String> name, int argument_count)
1238 : HUnaryCall(context, argument_count), name_(name) {
1239 }
1240
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001241 virtual void PrintDataTo(StringStream* stream) const;
1242
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001243 HValue* context() const { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001244 Handle<String> name() const { return name_; }
1245
1246 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
1247
1248 private:
1249 Handle<String> name_;
1250};
1251
1252
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001253class HCallFunction: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001254 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001255 HCallFunction(HValue* context, int argument_count)
1256 : HUnaryCall(context, argument_count) {
1257 }
1258
1259 HValue* context() const { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001260
1261 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
1262};
1263
1264
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001265class HCallGlobal: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001266 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001267 HCallGlobal(HValue* context, Handle<String> name, int argument_count)
1268 : HUnaryCall(context, argument_count), name_(name) {
1269 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001270
1271 virtual void PrintDataTo(StringStream* stream) const;
1272
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001273 HValue* context() const { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001274 Handle<String> name() const { return name_; }
1275
1276 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
1277
1278 private:
1279 Handle<String> name_;
1280};
1281
1282
1283class HCallKnownGlobal: public HCall {
1284 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001285 HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001286 : HCall(argument_count), target_(target) { }
1287
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001288 virtual void PrintDataTo(StringStream* stream) const;
1289
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001290 Handle<JSFunction> target() const { return target_; }
1291
1292 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
1293
1294 private:
1295 Handle<JSFunction> target_;
1296};
1297
1298
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001299class HCallNew: public HBinaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001300 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001301 HCallNew(HValue* context, HValue* constructor, int argument_count)
1302 : HBinaryCall(context, constructor, argument_count) {
1303 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001304
1305 virtual Representation RequiredInputRepresentation(int index) const {
1306 return Representation::Tagged();
1307 }
1308
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001309 HValue* context() const { return first(); }
1310 HValue* constructor() const { return second(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001311
1312 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
1313};
1314
1315
1316class HCallRuntime: public HCall {
1317 public:
1318 HCallRuntime(Handle<String> name,
1319 Runtime::Function* c_function,
1320 int argument_count)
1321 : HCall(argument_count), c_function_(c_function), name_(name) { }
1322 virtual void PrintDataTo(StringStream* stream) const;
1323
1324 Runtime::Function* function() const { return c_function_; }
1325 Handle<String> name() const { return name_; }
1326
1327 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
1328
1329 private:
1330 Runtime::Function* c_function_;
1331 Handle<String> name_;
1332};
1333
1334
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001335class HJSArrayLength: public HUnaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001336 public:
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001337 explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001338 // The length of an array is stored as a tagged value in the array
1339 // object. It is guaranteed to be 32 bit integer, but it can be
1340 // represented as either a smi or heap number.
1341 set_representation(Representation::Tagged());
1342 SetFlag(kDependsOnArrayLengths);
1343 SetFlag(kUseGVN);
1344 }
1345
1346 virtual Representation RequiredInputRepresentation(int index) const {
1347 return Representation::Tagged();
1348 }
1349
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001350 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001351
1352 protected:
1353 virtual bool DataEquals(HValue* other) const { return true; }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001354};
1355
1356
1357class HFixedArrayLength: public HUnaryOperation {
1358 public:
1359 explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
1360 set_representation(Representation::Tagged());
1361 SetFlag(kDependsOnArrayLengths);
1362 SetFlag(kUseGVN);
1363 }
1364
1365 virtual Representation RequiredInputRepresentation(int index) const {
1366 return Representation::Tagged();
1367 }
1368
1369 DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001370
1371 protected:
1372 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001373};
1374
1375
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001376class HPixelArrayLength: public HUnaryOperation {
1377 public:
1378 explicit HPixelArrayLength(HValue* value) : HUnaryOperation(value) {
1379 set_representation(Representation::Integer32());
1380 // The result of this instruction is idempotent as long as its inputs don't
1381 // change. The length of a pixel array cannot change once set, so it's not
1382 // necessary to introduce a kDependsOnArrayLengths or any other dependency.
1383 SetFlag(kUseGVN);
1384 }
1385
1386 virtual Representation RequiredInputRepresentation(int index) const {
1387 return Representation::Tagged();
1388 }
1389
1390 DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel_array_length")
1391
1392 protected:
1393 virtual bool DataEquals(HValue* other) const { return true; }
1394};
1395
1396
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001397class HBitNot: public HUnaryOperation {
1398 public:
1399 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1400 set_representation(Representation::Integer32());
1401 SetFlag(kUseGVN);
1402 SetFlag(kTruncatingToInt32);
1403 }
1404
1405 virtual Representation RequiredInputRepresentation(int index) const {
1406 return Representation::Integer32();
1407 }
1408 virtual HType CalculateInferredType() const;
1409
1410 DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001411
1412 protected:
1413 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001414};
1415
1416
1417class HUnaryMathOperation: public HUnaryOperation {
1418 public:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001419 HUnaryMathOperation(HValue* value, BuiltinFunctionId op)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001420 : HUnaryOperation(value), op_(op) {
1421 switch (op) {
1422 case kMathFloor:
1423 case kMathRound:
1424 case kMathCeil:
1425 set_representation(Representation::Integer32());
1426 break;
1427 case kMathAbs:
1428 set_representation(Representation::Tagged());
1429 SetFlag(kFlexibleRepresentation);
1430 break;
1431 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001432 case kMathPowHalf:
1433 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001434 case kMathSin:
1435 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001436 set_representation(Representation::Double());
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001437 break;
1438 default:
1439 UNREACHABLE();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001440 }
1441 SetFlag(kUseGVN);
1442 }
1443
1444 virtual void PrintDataTo(StringStream* stream) const;
1445
1446 virtual HType CalculateInferredType() const;
1447
1448 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1449
1450 virtual Representation RequiredInputRepresentation(int index) const {
1451 switch (op_) {
1452 case kMathFloor:
1453 case kMathRound:
1454 case kMathCeil:
1455 case kMathSqrt:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001456 case kMathPowHalf:
1457 case kMathLog:
whesse@chromium.org023421e2010-12-21 12:19:12 +00001458 case kMathSin:
1459 case kMathCos:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001460 return Representation::Double();
1461 break;
1462 case kMathAbs:
1463 return representation();
1464 break;
1465 default:
1466 return Representation::None();
1467 }
1468 }
1469
1470 virtual HValue* Canonicalize() {
1471 // If the input is integer32 then we replace the floor instruction
1472 // with its inputs. This happens before the representation changes are
1473 // introduced.
1474 if (op() == kMathFloor) {
1475 if (value()->representation().IsInteger32()) return value();
1476 }
1477 return this;
1478 }
1479
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001480 BuiltinFunctionId op() const { return op_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001481 const char* OpName() const;
1482
1483 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
1484
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001485 protected:
1486 virtual bool DataEquals(HValue* other) const {
1487 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
1488 return op_ == b->op();
1489 }
1490
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001491 private:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001492 BuiltinFunctionId op_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001493};
1494
1495
1496class HLoadElements: public HUnaryOperation {
1497 public:
1498 explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1499 set_representation(Representation::Tagged());
1500 SetFlag(kUseGVN);
1501 SetFlag(kDependsOnMaps);
1502 }
1503
1504 virtual Representation RequiredInputRepresentation(int index) const {
1505 return Representation::Tagged();
1506 }
1507
1508 DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001509
1510 protected:
1511 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001512};
1513
1514
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001515class HLoadPixelArrayExternalPointer: public HUnaryOperation {
1516 public:
1517 explicit HLoadPixelArrayExternalPointer(HValue* value)
1518 : HUnaryOperation(value) {
1519 set_representation(Representation::External());
1520 // The result of this instruction is idempotent as long as its inputs don't
1521 // change. The external array of a pixel array elements object cannot
1522 // change once set, so it's no necessary to introduce any additional
1523 // dependencies on top of the inputs.
1524 SetFlag(kUseGVN);
1525 }
1526
1527 virtual Representation RequiredInputRepresentation(int index) const {
1528 return Representation::Tagged();
1529 }
1530
1531 DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
1532 "load-pixel-array-external-pointer")
1533
1534 protected:
1535 virtual bool DataEquals(HValue* other) const { return true; }
1536};
1537
1538
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001539class HCheckMap: public HUnaryOperation {
1540 public:
1541 HCheckMap(HValue* value, Handle<Map> map)
1542 : HUnaryOperation(value), map_(map) {
1543 set_representation(Representation::Tagged());
1544 SetFlag(kUseGVN);
1545 SetFlag(kDependsOnMaps);
1546 }
1547
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001548 virtual bool IsCheckInstruction() const { return true; }
1549
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001550 virtual Representation RequiredInputRepresentation(int index) const {
1551 return Representation::Tagged();
1552 }
1553 virtual void PrintDataTo(StringStream* stream) const;
1554 virtual HType CalculateInferredType() const;
1555
1556#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001557 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001558#endif
1559
1560 Handle<Map> map() const { return map_; }
1561
1562 DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
1563
1564 protected:
1565 virtual bool DataEquals(HValue* other) const {
1566 HCheckMap* b = HCheckMap::cast(other);
1567 return map_.is_identical_to(b->map());
1568 }
1569
1570 private:
1571 Handle<Map> map_;
1572};
1573
1574
1575class HCheckFunction: public HUnaryOperation {
1576 public:
1577 HCheckFunction(HValue* value, Handle<JSFunction> function)
1578 : HUnaryOperation(value), target_(function) {
1579 set_representation(Representation::Tagged());
1580 SetFlag(kUseGVN);
1581 }
1582
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001583 virtual bool IsCheckInstruction() const { return true; }
1584
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001585 virtual Representation RequiredInputRepresentation(int index) const {
1586 return Representation::Tagged();
1587 }
1588 virtual void PrintDataTo(StringStream* stream) const;
1589 virtual HType CalculateInferredType() const;
1590
1591#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001592 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001593#endif
1594
1595 Handle<JSFunction> target() const { return target_; }
1596
1597 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
1598
1599 protected:
1600 virtual bool DataEquals(HValue* other) const {
1601 HCheckFunction* b = HCheckFunction::cast(other);
1602 return target_.is_identical_to(b->target());
1603 }
1604
1605 private:
1606 Handle<JSFunction> target_;
1607};
1608
1609
1610class HCheckInstanceType: public HUnaryOperation {
1611 public:
1612 // Check that the instance type is in the range [first, last] where
1613 // both first and last are included.
1614 HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
1615 : HUnaryOperation(value), first_(first), last_(last) {
1616 ASSERT(first <= last);
1617 set_representation(Representation::Tagged());
1618 SetFlag(kUseGVN);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001619 if ((FIRST_STRING_TYPE < first && last <= LAST_STRING_TYPE) ||
1620 (FIRST_STRING_TYPE <= first && last < LAST_STRING_TYPE)) {
1621 // A particular string instance type can change because of GC or
1622 // externalization, but the value still remains a string.
1623 SetFlag(kDependsOnMaps);
1624 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001625 }
1626
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001627 virtual bool IsCheckInstruction() const { return true; }
1628
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001629 virtual Representation RequiredInputRepresentation(int index) const {
1630 return Representation::Tagged();
1631 }
1632
1633#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001634 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001635#endif
1636
1637 static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
1638
1639 InstanceType first() const { return first_; }
1640 InstanceType last() const { return last_; }
1641
1642 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")
1643
1644 protected:
1645 // TODO(ager): It could be nice to allow the ommision of instance
1646 // type checks if we have already performed an instance type check
1647 // with a larger range.
1648 virtual bool DataEquals(HValue* other) const {
1649 HCheckInstanceType* b = HCheckInstanceType::cast(other);
1650 return (first_ == b->first()) && (last_ == b->last());
1651 }
1652
1653 private:
1654 InstanceType first_;
1655 InstanceType last_;
1656};
1657
1658
1659class HCheckNonSmi: public HUnaryOperation {
1660 public:
1661 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
1662 set_representation(Representation::Tagged());
1663 SetFlag(kUseGVN);
1664 }
1665
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001666 virtual bool IsCheckInstruction() const { return true; }
1667
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001668 virtual Representation RequiredInputRepresentation(int index) const {
1669 return Representation::Tagged();
1670 }
1671
1672 virtual HType CalculateInferredType() const;
1673
1674#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001675 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001676#endif
1677
1678 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001679
1680 protected:
1681 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001682};
1683
1684
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001685class HCheckPrototypeMaps: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001686 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001687 HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
1688 : prototype_(prototype), holder_(holder) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001689 SetFlag(kUseGVN);
1690 SetFlag(kDependsOnMaps);
1691 }
1692
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001693 virtual bool IsCheckInstruction() const { return true; }
1694
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001695#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001696 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001697#endif
1698
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001699 Handle<JSObject> prototype() const { return prototype_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001700 Handle<JSObject> holder() const { return holder_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001701
1702 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
1703
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001704 virtual intptr_t Hashcode() const {
1705 ASSERT(!Heap::IsAllocationAllowed());
1706 intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
1707 hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
1708 return hash;
1709 }
1710
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001711 protected:
1712 virtual bool DataEquals(HValue* other) const {
1713 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001714 return prototype_.is_identical_to(b->prototype()) &&
1715 holder_.is_identical_to(b->holder());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001716 }
1717
1718 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001719 Handle<JSObject> prototype_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001720 Handle<JSObject> holder_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001721};
1722
1723
1724class HCheckSmi: public HUnaryOperation {
1725 public:
1726 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
1727 set_representation(Representation::Tagged());
1728 SetFlag(kUseGVN);
1729 }
1730
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001731 virtual bool IsCheckInstruction() const { return true; }
1732
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001733 virtual Representation RequiredInputRepresentation(int index) const {
1734 return Representation::Tagged();
1735 }
1736 virtual HType CalculateInferredType() const;
1737
1738#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001739 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001740#endif
1741
1742 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00001743
1744 protected:
1745 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001746};
1747
1748
1749class HPhi: public HValue {
1750 public:
1751 explicit HPhi(int merged_index)
1752 : inputs_(2),
1753 merged_index_(merged_index),
1754 phi_id_(-1) {
1755 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1756 non_phi_uses_[i] = 0;
1757 indirect_uses_[i] = 0;
1758 }
1759 ASSERT(merged_index >= 0);
1760 set_representation(Representation::Tagged());
1761 SetFlag(kFlexibleRepresentation);
1762 }
1763
1764 virtual Representation InferredRepresentation() const {
1765 bool double_occurred = false;
1766 bool int32_occurred = false;
1767 for (int i = 0; i < OperandCount(); ++i) {
1768 HValue* value = OperandAt(i);
1769 if (value->representation().IsDouble()) double_occurred = true;
1770 if (value->representation().IsInteger32()) int32_occurred = true;
1771 if (value->representation().IsTagged()) return Representation::Tagged();
1772 }
1773
1774 if (double_occurred) return Representation::Double();
1775 if (int32_occurred) return Representation::Integer32();
1776 return Representation::None();
1777 }
1778
1779 virtual Range* InferRange();
1780 virtual Representation RequiredInputRepresentation(int index) const {
1781 return representation();
1782 }
1783 virtual HType CalculateInferredType() const;
1784 virtual int OperandCount() const { return inputs_.length(); }
1785 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
1786 HValue* GetRedundantReplacement() const;
1787 void AddInput(HValue* value);
1788
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001789 bool IsReceiver() { return merged_index_ == 0; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001790
1791 int merged_index() const { return merged_index_; }
1792
1793 virtual const char* Mnemonic() const { return "phi"; }
1794
1795 virtual void PrintTo(StringStream* stream) const;
1796
1797#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001798 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001799#endif
1800
1801 DECLARE_INSTRUCTION(Phi)
1802
1803 void InitRealUses(int id);
1804 void AddNonPhiUsesFrom(HPhi* other);
1805 void AddIndirectUsesTo(int* use_count);
1806
1807 int tagged_non_phi_uses() const {
1808 return non_phi_uses_[Representation::kTagged];
1809 }
1810 int int32_non_phi_uses() const {
1811 return non_phi_uses_[Representation::kInteger32];
1812 }
1813 int double_non_phi_uses() const {
1814 return non_phi_uses_[Representation::kDouble];
1815 }
1816 int tagged_indirect_uses() const {
1817 return indirect_uses_[Representation::kTagged];
1818 }
1819 int int32_indirect_uses() const {
1820 return indirect_uses_[Representation::kInteger32];
1821 }
1822 int double_indirect_uses() const {
1823 return indirect_uses_[Representation::kDouble];
1824 }
1825 int phi_id() { return phi_id_; }
1826
1827 protected:
1828 virtual void DeleteFromGraph();
1829 virtual void InternalSetOperandAt(int index, HValue* value) {
1830 inputs_[index] = value;
1831 }
1832
1833 private:
1834 ZoneList<HValue*> inputs_;
1835 int merged_index_;
1836
1837 int non_phi_uses_[Representation::kNumRepresentations];
1838 int indirect_uses_[Representation::kNumRepresentations];
1839 int phi_id_;
1840};
1841
1842
1843class HArgumentsObject: public HInstruction {
1844 public:
1845 HArgumentsObject() {
1846 set_representation(Representation::Tagged());
1847 SetFlag(kIsArguments);
1848 }
1849
1850 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
1851};
1852
1853
1854class HConstant: public HInstruction {
1855 public:
1856 HConstant(Handle<Object> handle, Representation r);
1857
1858 Handle<Object> handle() const { return handle_; }
1859
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001860 bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
1861
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001862 virtual bool EmitAtUses() const { return !representation().IsDouble(); }
1863 virtual void PrintDataTo(StringStream* stream) const;
1864 virtual HType CalculateInferredType() const;
1865 bool IsInteger() const { return handle_->IsSmi(); }
1866 HConstant* CopyToRepresentation(Representation r) const;
1867 HConstant* CopyToTruncatedInt32() const;
1868 bool HasInteger32Value() const { return has_int32_value_; }
1869 int32_t Integer32Value() const {
1870 ASSERT(HasInteger32Value());
1871 return int32_value_;
1872 }
1873 bool HasDoubleValue() const { return has_double_value_; }
1874 double DoubleValue() const {
1875 ASSERT(HasDoubleValue());
1876 return double_value_;
1877 }
1878 bool HasStringValue() const { return handle_->IsString(); }
1879
1880 virtual intptr_t Hashcode() const {
1881 ASSERT(!Heap::allow_allocation(false));
1882 return reinterpret_cast<intptr_t>(*handle());
1883 }
1884
1885#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00001886 virtual void Verify() { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001887#endif
1888
1889 DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
1890
1891 protected:
1892 virtual Range* InferRange();
1893
1894 virtual bool DataEquals(HValue* other) const {
1895 HConstant* other_constant = HConstant::cast(other);
1896 return handle().is_identical_to(other_constant->handle());
1897 }
1898
1899 private:
1900 Handle<Object> handle_;
1901 HType constant_type_;
1902
1903 // The following two values represent the int32 and the double value of the
1904 // given constant if there is a lossless conversion between the constant
1905 // and the specific representation.
1906 bool has_int32_value_;
1907 int32_t int32_value_;
1908 bool has_double_value_;
1909 double double_value_;
1910};
1911
1912
1913class HBinaryOperation: public HInstruction {
1914 public:
1915 HBinaryOperation(HValue* left, HValue* right) {
1916 ASSERT(left != NULL && right != NULL);
1917 SetOperandAt(0, left);
1918 SetOperandAt(1, right);
1919 }
1920
1921 HValue* left() const { return OperandAt(0); }
1922 HValue* right() const { return OperandAt(1); }
1923
1924 // TODO(kasperl): Move these helpers to the IA-32 Lithium
1925 // instruction sequence builder.
1926 HValue* LeastConstantOperand() const {
1927 if (IsCommutative() && left()->IsConstant()) return right();
1928 return left();
1929 }
1930 HValue* MostConstantOperand() const {
1931 if (IsCommutative() && left()->IsConstant()) return left();
1932 return right();
1933 }
1934
1935 virtual bool IsCommutative() const { return false; }
1936
1937 virtual void PrintDataTo(StringStream* stream) const;
1938 virtual int OperandCount() const { return operands_.length(); }
1939 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1940
1941 DECLARE_INSTRUCTION(BinaryOperation)
1942
1943 protected:
1944 virtual void InternalSetOperandAt(int index, HValue* value) {
1945 operands_[index] = value;
1946 }
1947
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001948 HOperandVector<2> operands_;
1949};
1950
1951
1952class HApplyArguments: public HInstruction {
1953 public:
1954 HApplyArguments(HValue* function,
1955 HValue* receiver,
1956 HValue* length,
1957 HValue* elements) {
1958 set_representation(Representation::Tagged());
1959 SetOperandAt(0, function);
1960 SetOperandAt(1, receiver);
1961 SetOperandAt(2, length);
1962 SetOperandAt(3, elements);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001963 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001964 }
1965
1966 virtual Representation RequiredInputRepresentation(int index) const {
1967 // The length is untagged, all other inputs are tagged.
1968 return (index == 2)
1969 ? Representation::Integer32()
1970 : Representation::Tagged();
1971 }
1972
1973 HValue* function() const { return OperandAt(0); }
1974 HValue* receiver() const { return OperandAt(1); }
1975 HValue* length() const { return OperandAt(2); }
1976 HValue* elements() const { return OperandAt(3); }
1977
1978 virtual int OperandCount() const { return operands_.length(); }
1979 virtual HValue* OperandAt(int index) const { return operands_[index]; }
1980
1981 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
1982
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001983 protected:
1984 virtual void InternalSetOperandAt(int index, HValue* value) {
1985 operands_[index] = value;
1986 }
1987
1988 private:
1989 HOperandVector<4> operands_;
1990};
1991
1992
1993class HArgumentsElements: public HInstruction {
1994 public:
1995 HArgumentsElements() {
1996 // The value produced by this instruction is a pointer into the stack
1997 // that looks as if it was a smi because of alignment.
1998 set_representation(Representation::Tagged());
1999 SetFlag(kUseGVN);
2000 }
2001
2002 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002003
2004 protected:
2005 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002006};
2007
2008
2009class HArgumentsLength: public HUnaryOperation {
2010 public:
2011 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
2012 set_representation(Representation::Integer32());
2013 SetFlag(kUseGVN);
2014 }
2015
2016 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002017
2018 protected:
2019 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002020};
2021
2022
2023class HAccessArgumentsAt: public HInstruction {
2024 public:
2025 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
2026 set_representation(Representation::Tagged());
2027 SetFlag(kUseGVN);
2028 SetOperandAt(0, arguments);
2029 SetOperandAt(1, length);
2030 SetOperandAt(2, index);
2031 }
2032
2033 virtual void PrintDataTo(StringStream* stream) const;
2034
2035 virtual Representation RequiredInputRepresentation(int index) const {
2036 // The arguments elements is considered tagged.
2037 return index == 0
2038 ? Representation::Tagged()
2039 : Representation::Integer32();
2040 }
2041
2042 HValue* arguments() const { return operands_[0]; }
2043 HValue* length() const { return operands_[1]; }
2044 HValue* index() const { return operands_[2]; }
2045
2046 virtual int OperandCount() const { return operands_.length(); }
2047 virtual HValue* OperandAt(int index) const { return operands_[index]; }
2048
2049 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
2050
2051 protected:
2052 virtual void InternalSetOperandAt(int index, HValue* value) {
2053 operands_[index] = value;
2054 }
2055
ager@chromium.org378b34e2011-01-28 08:04:38 +00002056 virtual bool DataEquals(HValue* other) const { return true; }
2057
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002058 private:
2059 HOperandVector<3> operands_;
2060};
2061
2062
2063class HBoundsCheck: public HBinaryOperation {
2064 public:
2065 HBoundsCheck(HValue* index, HValue* length)
2066 : HBinaryOperation(index, length) {
2067 SetFlag(kUseGVN);
2068 }
2069
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002070 virtual bool IsCheckInstruction() const { return true; }
2071
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002072 virtual Representation RequiredInputRepresentation(int index) const {
2073 return Representation::Integer32();
2074 }
2075
2076#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +00002077 virtual void Verify();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002078#endif
2079
2080 HValue* index() const { return left(); }
2081 HValue* length() const { return right(); }
2082
2083 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002084
2085 protected:
2086 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002087};
2088
2089
2090class HBitwiseBinaryOperation: public HBinaryOperation {
2091 public:
2092 HBitwiseBinaryOperation(HValue* left, HValue* right)
2093 : HBinaryOperation(left, right) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002094 set_representation(Representation::Tagged());
2095 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002096 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002097 }
2098
2099 virtual Representation RequiredInputRepresentation(int index) const {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002100 return representation();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002101 }
2102
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002103 virtual void RepresentationChanged(Representation to) {
2104 if (!to.IsTagged()) {
2105 ASSERT(to.IsInteger32());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002106 ClearAllSideEffects();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002107 SetFlag(kTruncatingToInt32);
2108 SetFlag(kUseGVN);
2109 }
2110 }
2111
2112 HType CalculateInferredType() const;
2113
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002114 DECLARE_INSTRUCTION(BitwiseBinaryOperation)
2115};
2116
2117
2118class HArithmeticBinaryOperation: public HBinaryOperation {
2119 public:
2120 HArithmeticBinaryOperation(HValue* left, HValue* right)
2121 : HBinaryOperation(left, right) {
2122 set_representation(Representation::Tagged());
2123 SetFlag(kFlexibleRepresentation);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002124 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002125 }
2126
2127 virtual void RepresentationChanged(Representation to) {
2128 if (!to.IsTagged()) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002129 ClearAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002130 SetFlag(kUseGVN);
2131 }
2132 }
2133
2134 virtual HType CalculateInferredType() const;
2135 virtual Representation RequiredInputRepresentation(int index) const {
2136 return representation();
2137 }
2138 virtual Representation InferredRepresentation() const {
2139 if (left()->representation().Equals(right()->representation())) {
2140 return left()->representation();
2141 }
2142 return HValue::InferredRepresentation();
2143 }
2144
2145 DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
2146};
2147
2148
2149class HCompare: public HBinaryOperation {
2150 public:
2151 HCompare(HValue* left, HValue* right, Token::Value token)
2152 : HBinaryOperation(left, right), token_(token) {
2153 ASSERT(Token::IsCompareOp(token));
2154 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002155 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002156 }
2157
2158 void SetInputRepresentation(Representation r);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002159
2160 virtual bool EmitAtUses() const {
2161 return !HasSideEffects() && (uses()->length() <= 1);
2162 }
2163
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002164 virtual Representation RequiredInputRepresentation(int index) const {
2165 return input_representation_;
2166 }
2167 Representation GetInputRepresentation() const {
2168 return input_representation_;
2169 }
2170 Token::Value token() const { return token_; }
2171 virtual void PrintDataTo(StringStream* stream) const;
2172
2173 virtual HType CalculateInferredType() const;
2174
2175 virtual intptr_t Hashcode() const {
2176 return HValue::Hashcode() * 7 + token_;
2177 }
2178
2179 DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
2180
2181 protected:
2182 virtual bool DataEquals(HValue* other) const {
2183 HCompare* comp = HCompare::cast(other);
2184 return token_ == comp->token();
2185 }
2186
2187 private:
2188 Representation input_representation_;
2189 Token::Value token_;
2190};
2191
2192
2193class HCompareJSObjectEq: public HBinaryOperation {
2194 public:
2195 HCompareJSObjectEq(HValue* left, HValue* right)
2196 : HBinaryOperation(left, right) {
2197 set_representation(Representation::Tagged());
2198 SetFlag(kUseGVN);
2199 }
2200
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002201 virtual bool EmitAtUses() const {
2202 return !HasSideEffects() && (uses()->length() <= 1);
2203 }
2204
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002205 virtual Representation RequiredInputRepresentation(int index) const {
2206 return Representation::Tagged();
2207 }
2208 virtual HType CalculateInferredType() const;
2209
2210 DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002211
2212 protected:
2213 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002214};
2215
2216
2217class HUnaryPredicate: public HUnaryOperation {
2218 public:
2219 explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
2220 set_representation(Representation::Tagged());
2221 SetFlag(kUseGVN);
2222 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002223
2224 virtual bool EmitAtUses() const {
2225 return !HasSideEffects() && (uses()->length() <= 1);
2226 }
2227
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002228 virtual Representation RequiredInputRepresentation(int index) const {
2229 return Representation::Tagged();
2230 }
2231 virtual HType CalculateInferredType() const;
2232};
2233
2234
2235class HIsNull: public HUnaryPredicate {
2236 public:
2237 HIsNull(HValue* value, bool is_strict)
2238 : HUnaryPredicate(value), is_strict_(is_strict) { }
2239
2240 bool is_strict() const { return is_strict_; }
2241
2242 DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
2243
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002244 protected:
2245 virtual bool DataEquals(HValue* other) const {
2246 HIsNull* b = HIsNull::cast(other);
2247 return is_strict_ == b->is_strict();
2248 }
2249
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002250 private:
2251 bool is_strict_;
2252};
2253
2254
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002255class HIsObject: public HUnaryPredicate {
2256 public:
2257 explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }
2258
2259 DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002260
2261 protected:
2262 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002263};
2264
2265
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002266class HIsSmi: public HUnaryPredicate {
2267 public:
2268 explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
2269
2270 DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002271
2272 protected:
2273 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002274};
2275
2276
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002277class HIsConstructCall: public HInstruction {
2278 public:
2279 HIsConstructCall() {
2280 set_representation(Representation::Tagged());
2281 SetFlag(kUseGVN);
2282 }
2283
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002284 virtual bool EmitAtUses() const {
2285 return !HasSideEffects() && (uses()->length() <= 1);
2286 }
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002287
2288 DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is_construct_call")
2289
2290 protected:
2291 virtual bool DataEquals(HValue* other) const { return true; }
2292};
2293
2294
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002295class HHasInstanceType: public HUnaryPredicate {
2296 public:
2297 HHasInstanceType(HValue* value, InstanceType type)
2298 : HUnaryPredicate(value), from_(type), to_(type) { }
2299 HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
2300 : HUnaryPredicate(value), from_(from), to_(to) {
2301 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
2302 }
2303
2304 InstanceType from() { return from_; }
2305 InstanceType to() { return to_; }
2306
2307 virtual void PrintDataTo(StringStream* stream) const;
2308
2309 DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
2310
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002311 protected:
2312 virtual bool DataEquals(HValue* other) const {
2313 HHasInstanceType* b = HHasInstanceType::cast(other);
2314 return (from_ == b->from()) && (to_ == b->to());
2315 }
2316
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002317 private:
2318 InstanceType from_;
2319 InstanceType to_; // Inclusive range, not all combinations work.
2320};
2321
2322
2323class HHasCachedArrayIndex: public HUnaryPredicate {
2324 public:
2325 explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
2326
2327 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002328
2329 protected:
2330 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002331};
2332
2333
2334class HClassOfTest: public HUnaryPredicate {
2335 public:
2336 HClassOfTest(HValue* value, Handle<String> class_name)
2337 : HUnaryPredicate(value), class_name_(class_name) { }
2338
2339 DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
2340
2341 virtual void PrintDataTo(StringStream* stream) const;
2342
2343 Handle<String> class_name() const { return class_name_; }
2344
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002345 protected:
2346 virtual bool DataEquals(HValue* other) const {
2347 HClassOfTest* b = HClassOfTest::cast(other);
2348 return class_name_.is_identical_to(b->class_name_);
2349 }
2350
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002351 private:
2352 Handle<String> class_name_;
2353};
2354
2355
2356class HTypeofIs: public HUnaryPredicate {
2357 public:
2358 HTypeofIs(HValue* value, Handle<String> type_literal)
2359 : HUnaryPredicate(value), type_literal_(type_literal) { }
2360
2361 Handle<String> type_literal() { return type_literal_; }
2362 virtual void PrintDataTo(StringStream* stream) const;
2363
2364 DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
2365
2366 protected:
2367 virtual bool DataEquals(HValue* other) const {
2368 HTypeofIs* b = HTypeofIs::cast(other);
2369 return type_literal_.is_identical_to(b->type_literal_);
2370 }
2371
2372 private:
2373 Handle<String> type_literal_;
2374};
2375
2376
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002377class HInstanceOf: public HInstruction {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002378 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002379 HInstanceOf(HValue* context, HValue* left, HValue* right) {
2380 SetOperandAt(0, context);
2381 SetOperandAt(1, left);
2382 SetOperandAt(2, right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002383 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002384 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002385 }
2386
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002387 HValue* context() const { return operands_[0]; }
2388 HValue* left() const { return operands_[1]; }
2389 HValue* right() const { return operands_[2]; }
2390
2391 virtual bool EmitAtUses() const {
2392 return !HasSideEffects() && (uses()->length() <= 1);
2393 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002394
2395 virtual Representation RequiredInputRepresentation(int index) const {
2396 return Representation::Tagged();
2397 }
2398
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002399 virtual void PrintDataTo(StringStream* stream) const;
2400
2401 virtual int OperandCount() const { return 3; }
2402 virtual HValue* OperandAt(int index) const { return operands_[index]; }
2403
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002404 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002405
2406 protected:
2407 virtual void InternalSetOperandAt(int index, HValue* value) {
2408 operands_[index] = value;
2409 }
2410
2411 private:
2412 HOperandVector<3> operands_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002413};
2414
2415
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002416class HInstanceOfKnownGlobal: public HUnaryOperation {
2417 public:
2418 HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right)
2419 : HUnaryOperation(left), function_(right) {
2420 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002421 SetAllSideEffects();
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002422 }
2423
2424 Handle<JSFunction> function() { return function_; }
2425
2426 virtual Representation RequiredInputRepresentation(int index) const {
2427 return Representation::Tagged();
2428 }
2429
2430 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
2431 "instance_of_known_global")
2432
2433 private:
2434 Handle<JSFunction> function_;
2435};
2436
2437
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002438class HPower: public HBinaryOperation {
2439 public:
2440 HPower(HValue* left, HValue* right)
2441 : HBinaryOperation(left, right) {
2442 set_representation(Representation::Double());
2443 SetFlag(kUseGVN);
2444 }
2445
2446 virtual Representation RequiredInputRepresentation(int index) const {
2447 return (index == 1) ? Representation::None() : Representation::Double();
2448 }
2449
2450 DECLARE_CONCRETE_INSTRUCTION(Power, "power")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002451
2452 protected:
2453 virtual bool DataEquals(HValue* other) const { return true; }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002454};
2455
2456
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002457class HAdd: public HArithmeticBinaryOperation {
2458 public:
2459 HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2460 SetFlag(kCanOverflow);
2461 }
2462
2463 // Add is only commutative if two integer values are added and not if two
2464 // tagged values are added (because it might be a String concatenation).
2465 virtual bool IsCommutative() const {
2466 return !representation().IsTagged();
2467 }
2468
2469 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2470
2471 virtual HType CalculateInferredType() const;
2472
2473 DECLARE_CONCRETE_INSTRUCTION(Add, "add")
2474
2475 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002476 virtual bool DataEquals(HValue* other) const { return true; }
2477
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002478 virtual Range* InferRange();
2479};
2480
2481
2482class HSub: public HArithmeticBinaryOperation {
2483 public:
2484 HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2485 SetFlag(kCanOverflow);
2486 }
2487
2488 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2489
2490 DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
2491
2492 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002493 virtual bool DataEquals(HValue* other) const { return true; }
2494
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002495 virtual Range* InferRange();
2496};
2497
2498
2499class HMul: public HArithmeticBinaryOperation {
2500 public:
2501 HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2502 SetFlag(kCanOverflow);
2503 }
2504
2505 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2506
2507 // Only commutative if it is certain that not two objects are multiplicated.
2508 virtual bool IsCommutative() const {
2509 return !representation().IsTagged();
2510 }
2511
2512 DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
2513
2514 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002515 virtual bool DataEquals(HValue* other) const { return true; }
2516
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002517 virtual Range* InferRange();
2518};
2519
2520
2521class HMod: public HArithmeticBinaryOperation {
2522 public:
2523 HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2524 SetFlag(kCanBeDivByZero);
2525 }
2526
2527 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2528
2529 DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
2530
2531 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002532 virtual bool DataEquals(HValue* other) const { return true; }
2533
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002534 virtual Range* InferRange();
2535};
2536
2537
2538class HDiv: public HArithmeticBinaryOperation {
2539 public:
2540 HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2541 SetFlag(kCanBeDivByZero);
2542 SetFlag(kCanOverflow);
2543 }
2544
2545 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2546
2547 DECLARE_CONCRETE_INSTRUCTION(Div, "div")
2548
2549 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002550 virtual bool DataEquals(HValue* other) const { return true; }
2551
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002552 virtual Range* InferRange();
2553};
2554
2555
2556class HBitAnd: public HBitwiseBinaryOperation {
2557 public:
2558 HBitAnd(HValue* left, HValue* right)
2559 : HBitwiseBinaryOperation(left, right) { }
2560
2561 virtual bool IsCommutative() const { return true; }
2562 virtual HType CalculateInferredType() const;
2563
2564 DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
2565
2566 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002567 virtual bool DataEquals(HValue* other) const { return true; }
2568
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002569 virtual Range* InferRange();
2570};
2571
2572
2573class HBitXor: public HBitwiseBinaryOperation {
2574 public:
2575 HBitXor(HValue* left, HValue* right)
2576 : HBitwiseBinaryOperation(left, right) { }
2577
2578 virtual bool IsCommutative() const { return true; }
2579 virtual HType CalculateInferredType() const;
2580
2581 DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002582
2583 protected:
2584 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002585};
2586
2587
2588class HBitOr: public HBitwiseBinaryOperation {
2589 public:
2590 HBitOr(HValue* left, HValue* right)
2591 : HBitwiseBinaryOperation(left, right) { }
2592
2593 virtual bool IsCommutative() const { return true; }
2594 virtual HType CalculateInferredType() const;
2595
2596 DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
2597
2598 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002599 virtual bool DataEquals(HValue* other) const { return true; }
2600
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002601 virtual Range* InferRange();
2602};
2603
2604
2605class HShl: public HBitwiseBinaryOperation {
2606 public:
2607 HShl(HValue* left, HValue* right)
2608 : HBitwiseBinaryOperation(left, right) { }
2609
2610 virtual Range* InferRange();
2611 virtual HType CalculateInferredType() const;
2612
2613 DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002614
2615 protected:
2616 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002617};
2618
2619
2620class HShr: public HBitwiseBinaryOperation {
2621 public:
2622 HShr(HValue* left, HValue* right)
2623 : HBitwiseBinaryOperation(left, right) { }
2624
2625 virtual HType CalculateInferredType() const;
2626
2627 DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002628
2629 protected:
2630 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002631};
2632
2633
2634class HSar: public HBitwiseBinaryOperation {
2635 public:
2636 HSar(HValue* left, HValue* right)
2637 : HBitwiseBinaryOperation(left, right) { }
2638
2639 virtual Range* InferRange();
2640 virtual HType CalculateInferredType() const;
2641
2642 DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002643
2644 protected:
2645 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002646};
2647
2648
2649class HOsrEntry: public HInstruction {
2650 public:
2651 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
2652 SetFlag(kChangesOsrEntries);
2653 }
2654
2655 int ast_id() const { return ast_id_; }
2656
2657 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
2658
2659 private:
2660 int ast_id_;
2661};
2662
2663
2664class HParameter: public HInstruction {
2665 public:
2666 explicit HParameter(unsigned index) : index_(index) {
2667 set_representation(Representation::Tagged());
2668 }
2669
2670 unsigned index() const { return index_; }
2671
2672 virtual void PrintDataTo(StringStream* stream) const;
2673
2674 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2675
2676 private:
2677 unsigned index_;
2678};
2679
2680
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002681class HCallStub: public HUnaryCall {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002682 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002683 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
2684 : HUnaryCall(context, argument_count),
2685 major_key_(major_key),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002686 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002687 }
2688
2689 CodeStub::Major major_key() { return major_key_; }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002690
2691 HValue* context() const { return value(); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002692
2693 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
2694 transcendental_type_ = transcendental_type;
2695 }
2696 TranscendentalCache::Type transcendental_type() {
2697 return transcendental_type_;
2698 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002699
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002700 virtual void PrintDataTo(StringStream* stream) const;
2701
2702 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
2703
2704 private:
2705 CodeStub::Major major_key_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002706 TranscendentalCache::Type transcendental_type_;
2707};
2708
2709
2710class HUnknownOSRValue: public HInstruction {
2711 public:
2712 HUnknownOSRValue() { set_representation(Representation::Tagged()); }
2713
2714 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
2715};
2716
2717
2718class HLoadGlobal: public HInstruction {
2719 public:
2720 HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
2721 : cell_(cell), check_hole_value_(check_hole_value) {
2722 set_representation(Representation::Tagged());
2723 SetFlag(kUseGVN);
2724 SetFlag(kDependsOnGlobalVars);
2725 }
2726
2727 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2728 bool check_hole_value() const { return check_hole_value_; }
2729
2730 virtual Representation RequiredInputRepresentation(int index) const {
2731 return Representation::Tagged();
2732 }
2733 virtual void PrintDataTo(StringStream* stream) const;
2734
2735 virtual intptr_t Hashcode() const {
2736 ASSERT(!Heap::allow_allocation(false));
2737 return reinterpret_cast<intptr_t>(*cell_);
2738 }
2739
2740 DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
2741
2742 protected:
2743 virtual bool DataEquals(HValue* other) const {
2744 HLoadGlobal* b = HLoadGlobal::cast(other);
2745 return cell_.is_identical_to(b->cell());
2746 }
2747
2748 private:
2749 Handle<JSGlobalPropertyCell> cell_;
2750 bool check_hole_value_;
2751};
2752
2753
2754class HStoreGlobal: public HUnaryOperation {
2755 public:
ager@chromium.org378b34e2011-01-28 08:04:38 +00002756 HStoreGlobal(HValue* value,
2757 Handle<JSGlobalPropertyCell> cell,
2758 bool check_hole_value)
2759 : HUnaryOperation(value),
2760 cell_(cell),
2761 check_hole_value_(check_hole_value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002762 SetFlag(kChangesGlobalVars);
2763 }
2764
2765 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002766 bool check_hole_value() const { return check_hole_value_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002767
2768 virtual Representation RequiredInputRepresentation(int index) const {
2769 return Representation::Tagged();
2770 }
2771 virtual void PrintDataTo(StringStream* stream) const;
2772
2773 DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
2774
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002775 private:
2776 Handle<JSGlobalPropertyCell> cell_;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002777 bool check_hole_value_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002778};
2779
2780
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002781class HLoadContextSlot: public HUnaryOperation {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002782 public:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002783 HLoadContextSlot(HValue* context , int slot_index)
2784 : HUnaryOperation(context), slot_index_(slot_index) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002785 set_representation(Representation::Tagged());
2786 SetFlag(kUseGVN);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002787 SetFlag(kDependsOnContextSlots);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002788 }
2789
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002790 int slot_index() const { return slot_index_; }
2791
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002792 virtual Representation RequiredInputRepresentation(int index) const {
2793 return Representation::Tagged();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002794 }
2795
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002796 virtual void PrintDataTo(StringStream* stream) const;
2797
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002798 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
2799
2800 protected:
2801 virtual bool DataEquals(HValue* other) const {
2802 HLoadContextSlot* b = HLoadContextSlot::cast(other);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002803 return (slot_index() == b->slot_index());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002804 }
2805
2806 private:
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002807 int slot_index_;
2808};
2809
2810
2811static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
2812 return !value->type().IsSmi() &&
2813 !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
2814}
2815
2816
2817class HStoreContextSlot: public HBinaryOperation {
2818 public:
2819 HStoreContextSlot(HValue* context, int slot_index, HValue* value)
2820 : HBinaryOperation(context, value), slot_index_(slot_index) {
2821 SetFlag(kChangesContextSlots);
2822 }
2823
2824 HValue* context() const { return OperandAt(0); }
2825 HValue* value() const { return OperandAt(1); }
2826 int slot_index() const { return slot_index_; }
2827
2828 bool NeedsWriteBarrier() const {
2829 return StoringValueNeedsWriteBarrier(value());
2830 }
2831
2832 virtual Representation RequiredInputRepresentation(int index) const {
2833 return Representation::Tagged();
2834 }
2835
2836 virtual void PrintDataTo(StringStream* stream) const;
2837
2838 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store_context_slot")
2839
2840 private:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002841 int slot_index_;
2842};
2843
2844
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002845class HLoadNamedField: public HUnaryOperation {
2846 public:
2847 HLoadNamedField(HValue* object, bool is_in_object, int offset)
2848 : HUnaryOperation(object),
2849 is_in_object_(is_in_object),
2850 offset_(offset) {
2851 set_representation(Representation::Tagged());
2852 SetFlag(kUseGVN);
2853 if (is_in_object) {
2854 SetFlag(kDependsOnInobjectFields);
2855 } else {
2856 SetFlag(kDependsOnBackingStoreFields);
2857 }
2858 }
2859
2860 HValue* object() const { return OperandAt(0); }
2861 bool is_in_object() const { return is_in_object_; }
2862 int offset() const { return offset_; }
2863
2864 virtual Representation RequiredInputRepresentation(int index) const {
2865 return Representation::Tagged();
2866 }
2867 virtual void PrintDataTo(StringStream* stream) const;
2868
2869 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
2870
2871 protected:
2872 virtual bool DataEquals(HValue* other) const {
2873 HLoadNamedField* b = HLoadNamedField::cast(other);
2874 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
2875 }
2876
2877 private:
2878 bool is_in_object_;
2879 int offset_;
2880};
2881
2882
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002883class HLoadNamedGeneric: public HBinaryOperation {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002884 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002885 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
2886 : HBinaryOperation(context, object), name_(name) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002887 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002888 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002889 }
2890
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002891 HValue* context() const { return OperandAt(0); }
2892 HValue* object() const { return OperandAt(1); }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002893 Handle<Object> name() const { return name_; }
2894
2895 virtual Representation RequiredInputRepresentation(int index) const {
2896 return Representation::Tagged();
2897 }
2898
2899 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
2900
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002901 private:
2902 Handle<Object> name_;
2903};
2904
2905
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002906class HLoadFunctionPrototype: public HUnaryOperation {
2907 public:
2908 explicit HLoadFunctionPrototype(HValue* function)
2909 : HUnaryOperation(function) {
2910 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00002911 SetFlag(kUseGVN);
2912 SetFlag(kDependsOnCalls);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002913 }
2914
2915 HValue* function() const { return OperandAt(0); }
2916
2917 virtual Representation RequiredInputRepresentation(int index) const {
2918 return Representation::Tagged();
2919 }
2920
2921 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
2922
2923 protected:
2924 virtual bool DataEquals(HValue* other) const { return true; }
2925};
2926
2927
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002928class HLoadKeyed: public HBinaryOperation {
2929 public:
2930 HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
2931 set_representation(Representation::Tagged());
2932 }
2933
2934 virtual void PrintDataTo(StringStream* stream) const;
2935
2936 virtual Representation RequiredInputRepresentation(int index) const {
2937 return Representation::Tagged();
2938 }
2939 HValue* object() const { return OperandAt(0); }
2940 HValue* key() const { return OperandAt(1); }
2941
2942 DECLARE_INSTRUCTION(LoadKeyed)
2943};
2944
2945
2946class HLoadKeyedFastElement: public HLoadKeyed {
2947 public:
2948 HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2949 SetFlag(kDependsOnArrayElements);
2950 SetFlag(kUseGVN);
2951 }
2952
2953 virtual Representation RequiredInputRepresentation(int index) const {
2954 // The key is supposed to be Integer32.
2955 return (index == 1) ? Representation::Integer32()
2956 : Representation::Tagged();
2957 }
2958
2959 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
2960 "load_keyed_fast_element")
ager@chromium.org378b34e2011-01-28 08:04:38 +00002961
2962 protected:
2963 virtual bool DataEquals(HValue* other) const { return true; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002964};
2965
2966
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002967class HLoadPixelArrayElement: public HBinaryOperation {
2968 public:
2969 HLoadPixelArrayElement(HValue* external_elements, HValue* key)
2970 : HBinaryOperation(external_elements, key) {
2971 set_representation(Representation::Integer32());
2972 SetFlag(kDependsOnPixelArrayElements);
2973 // Native code could change the pixel array.
2974 SetFlag(kDependsOnCalls);
2975 SetFlag(kUseGVN);
2976 }
2977
2978 virtual void PrintDataTo(StringStream* stream) const;
2979
2980 virtual Representation RequiredInputRepresentation(int index) const {
2981 // The key is supposed to be Integer32, but the base pointer
2982 // for the element load is a naked pointer.
2983 return (index == 1) ? Representation::Integer32()
2984 : Representation::External();
2985 }
2986
2987 HValue* external_pointer() const { return OperandAt(0); }
2988 HValue* key() const { return OperandAt(1); }
2989
2990 DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
2991 "load_pixel_array_element")
2992
2993 protected:
2994 virtual bool DataEquals(HValue* other) const { return true; }
2995};
2996
2997
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002998class HLoadKeyedGeneric: public HLoadKeyed {
2999 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003000 HLoadKeyedGeneric(HContext* context, HValue* obj, HValue* key)
3001 : HLoadKeyed(obj, key), context_(NULL) {
3002 SetOperandAt(2, context);
ager@chromium.org378b34e2011-01-28 08:04:38 +00003003 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003004 }
3005
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003006 HValue* context() const { return context_; }
3007 HValue* object() const { return operands_[0]; }
3008 HValue* key() const { return operands_[1]; }
3009
3010 virtual int OperandCount() const { return 3; }
3011 virtual HValue* OperandAt(int index) const {
3012 return (index < 2) ? operands_[index] : context_;
3013 }
3014
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003015 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003016
3017 protected:
3018 virtual void InternalSetOperandAt(int index, HValue* value);
3019
3020 private:
3021 HValue* context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003022};
3023
3024
3025class HStoreNamed: public HBinaryOperation {
3026 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003027 HStoreNamed(HValue* obj, Handle<String> name, HValue* val)
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003028 : HBinaryOperation(obj, val), name_(name) {
3029 }
3030
3031 virtual Representation RequiredInputRepresentation(int index) const {
3032 return Representation::Tagged();
3033 }
3034
3035 virtual void PrintDataTo(StringStream* stream) const;
3036
3037 HValue* object() const { return OperandAt(0); }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003038 Handle<String> name() const { return name_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003039 HValue* value() const { return OperandAt(1); }
3040 void set_value(HValue* value) { SetOperandAt(1, value); }
3041
3042 DECLARE_INSTRUCTION(StoreNamed)
3043
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003044 private:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003045 Handle<String> name_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003046};
3047
3048
3049class HStoreNamedField: public HStoreNamed {
3050 public:
3051 HStoreNamedField(HValue* obj,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003052 Handle<String> name,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003053 HValue* val,
3054 bool in_object,
3055 int offset)
3056 : HStoreNamed(obj, name, val),
3057 is_in_object_(in_object),
3058 offset_(offset) {
3059 if (is_in_object_) {
3060 SetFlag(kChangesInobjectFields);
3061 } else {
3062 SetFlag(kChangesBackingStoreFields);
3063 }
3064 }
3065
3066 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
3067
3068 virtual Representation RequiredInputRepresentation(int index) const {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00003069 return Representation::Tagged();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003070 }
3071 virtual void PrintDataTo(StringStream* stream) const;
3072
3073 bool is_in_object() const { return is_in_object_; }
3074 int offset() const { return offset_; }
3075 Handle<Map> transition() const { return transition_; }
3076 void set_transition(Handle<Map> map) { transition_ = map; }
3077
ricow@chromium.org83aa5492011-02-07 12:42:56 +00003078 bool NeedsWriteBarrier() const {
3079 return StoringValueNeedsWriteBarrier(value());
3080 }
3081
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003082 private:
3083 bool is_in_object_;
3084 int offset_;
3085 Handle<Map> transition_;
3086};
3087
3088
3089class HStoreNamedGeneric: public HStoreNamed {
3090 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003091 HStoreNamedGeneric(HValue* context,
3092 HValue* object,
3093 Handle<String> name,
3094 HValue* value)
3095 : HStoreNamed(object, name, value), context_(NULL) {
3096 SetOperandAt(2, context);
ager@chromium.org378b34e2011-01-28 08:04:38 +00003097 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003098 }
3099
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003100 HValue* context() const { return context_; }
3101 HValue* object() const { return operands_[0]; }
3102 HValue* value() const { return operands_[1]; }
3103
3104 virtual int OperandCount() const { return 3; }
3105
3106 virtual HValue* OperandAt(int index) const {
3107 return (index < 2) ? operands_[index] : context_;
3108 }
3109
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003110 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003111
3112 protected:
3113 virtual void InternalSetOperandAt(int index, HValue* value);
3114
3115 private:
3116 HValue* context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003117};
3118
3119
3120class HStoreKeyed: public HInstruction {
3121 public:
3122 HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
3123 SetOperandAt(0, obj);
3124 SetOperandAt(1, key);
3125 SetOperandAt(2, val);
3126 }
3127
3128 virtual void PrintDataTo(StringStream* stream) const;
3129 virtual int OperandCount() const { return operands_.length(); }
3130 virtual HValue* OperandAt(int index) const { return operands_[index]; }
3131
3132 virtual Representation RequiredInputRepresentation(int index) const {
3133 return Representation::Tagged();
3134 }
3135
3136 HValue* object() const { return OperandAt(0); }
3137 HValue* key() const { return OperandAt(1); }
3138 HValue* value() const { return OperandAt(2); }
3139
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00003140 bool NeedsWriteBarrier() const {
3141 return StoringValueNeedsWriteBarrier(value());
3142 }
3143
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003144 DECLARE_INSTRUCTION(StoreKeyed)
3145
3146 protected:
3147 virtual void InternalSetOperandAt(int index, HValue* value) {
3148 operands_[index] = value;
3149 }
3150
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003151 HOperandVector<3> operands_;
3152};
3153
3154
3155class HStoreKeyedFastElement: public HStoreKeyed {
3156 public:
3157 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
3158 : HStoreKeyed(obj, key, val) {
3159 SetFlag(kChangesArrayElements);
3160 }
3161
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003162 virtual Representation RequiredInputRepresentation(int index) const {
3163 // The key is supposed to be Integer32.
3164 return (index == 1) ? Representation::Integer32()
3165 : Representation::Tagged();
3166 }
3167
3168 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
3169 "store_keyed_fast_element")
3170};
3171
3172
3173class HStoreKeyedGeneric: public HStoreKeyed {
3174 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003175 HStoreKeyedGeneric(HValue* context,
3176 HValue* object,
3177 HValue* key,
3178 HValue* value)
3179 : HStoreKeyed(object, key, value), context_(NULL) {
3180 SetOperandAt(3, context);
ager@chromium.org378b34e2011-01-28 08:04:38 +00003181 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003182 }
3183
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003184 HValue* context() const { return context_; }
3185 HValue* object() const { return operands_[0]; }
3186 HValue* key() const { return operands_[1]; }
3187 HValue* value() const { return operands_[2]; }
3188
3189 virtual int OperandCount() const { return 4; }
3190
3191 virtual HValue* OperandAt(int index) const {
3192 return (index < 3) ? operands_[index] : context_;
3193 }
3194
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003195 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003196
3197 protected:
3198 virtual void InternalSetOperandAt(int index, HValue* value);
3199
3200 private:
3201 HValue* context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003202};
3203
3204
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003205class HStringCharCodeAt: public HBinaryOperation {
3206 public:
3207 HStringCharCodeAt(HValue* string, HValue* index)
3208 : HBinaryOperation(string, index) {
3209 set_representation(Representation::Integer32());
3210 SetFlag(kUseGVN);
3211 }
3212
3213 virtual Representation RequiredInputRepresentation(int index) const {
3214 // The index is supposed to be Integer32.
3215 return (index == 1) ? Representation::Integer32()
3216 : Representation::Tagged();
3217 }
3218
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003219 HValue* string() const { return OperandAt(0); }
3220 HValue* index() const { return OperandAt(1); }
3221
3222 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string_char_code_at")
3223
3224 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00003225 virtual bool DataEquals(HValue* other) const { return true; }
3226
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003227 virtual Range* InferRange() {
3228 return new Range(0, String::kMaxUC16CharCode);
3229 }
3230};
3231
3232
3233class HStringLength: public HUnaryOperation {
3234 public:
3235 explicit HStringLength(HValue* string) : HUnaryOperation(string) {
3236 set_representation(Representation::Tagged());
3237 SetFlag(kUseGVN);
3238 }
3239
3240 virtual Representation RequiredInputRepresentation(int index) const {
3241 return Representation::Tagged();
3242 }
3243
3244 virtual HType CalculateInferredType() const {
3245 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
3246 return HType::Smi();
3247 }
3248
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003249 DECLARE_CONCRETE_INSTRUCTION(StringLength, "string_length")
3250
3251 protected:
ager@chromium.org378b34e2011-01-28 08:04:38 +00003252 virtual bool DataEquals(HValue* other) const { return true; }
3253
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003254 virtual Range* InferRange() {
3255 return new Range(0, String::kMaxLength);
3256 }
3257};
3258
3259
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003260class HMaterializedLiteral: public HInstruction {
3261 public:
3262 HMaterializedLiteral(int index, int depth)
3263 : literal_index_(index), depth_(depth) {
3264 set_representation(Representation::Tagged());
3265 }
3266
3267 int literal_index() const { return literal_index_; }
3268 int depth() const { return depth_; }
3269
3270 DECLARE_INSTRUCTION(MaterializedLiteral)
3271
3272 private:
3273 int literal_index_;
3274 int depth_;
3275};
3276
3277
3278class HArrayLiteral: public HMaterializedLiteral {
3279 public:
3280 HArrayLiteral(Handle<FixedArray> constant_elements,
3281 int length,
3282 int literal_index,
3283 int depth)
3284 : HMaterializedLiteral(literal_index, depth),
3285 length_(length),
3286 constant_elements_(constant_elements) {}
3287
3288 Handle<FixedArray> constant_elements() const { return constant_elements_; }
3289 int length() const { return length_; }
3290
3291 bool IsCopyOnWrite() const;
3292
3293 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
3294
3295 private:
3296 int length_;
3297 Handle<FixedArray> constant_elements_;
3298};
3299
3300
3301class HObjectLiteral: public HMaterializedLiteral {
3302 public:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003303 HObjectLiteral(HValue* context,
3304 Handle<FixedArray> constant_properties,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003305 bool fast_elements,
3306 int literal_index,
3307 int depth)
3308 : HMaterializedLiteral(literal_index, depth),
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003309 context_(NULL),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003310 constant_properties_(constant_properties),
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003311 fast_elements_(fast_elements) {
3312 SetOperandAt(0, context);
3313 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003314
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003315 HValue* context() const { return context_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003316 Handle<FixedArray> constant_properties() const {
3317 return constant_properties_;
3318 }
3319 bool fast_elements() const { return fast_elements_; }
3320
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003321 virtual int OperandCount() const { return 1; }
3322 virtual HValue* OperandAt(int index) const { return context_; }
3323
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003324 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
3325
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003326 protected:
3327 virtual void InternalSetOperandAt(int index, HValue* value) {
3328 context_ = value;
3329 }
3330
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003331 private:
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00003332 HValue* context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003333 Handle<FixedArray> constant_properties_;
3334 bool fast_elements_;
3335};
3336
3337
3338class HRegExpLiteral: public HMaterializedLiteral {
3339 public:
3340 HRegExpLiteral(Handle<String> pattern,
3341 Handle<String> flags,
3342 int literal_index)
3343 : HMaterializedLiteral(literal_index, 0),
3344 pattern_(pattern),
3345 flags_(flags) { }
3346
3347 Handle<String> pattern() { return pattern_; }
3348 Handle<String> flags() { return flags_; }
3349
3350 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
3351
3352 private:
3353 Handle<String> pattern_;
3354 Handle<String> flags_;
3355};
3356
3357
3358class HFunctionLiteral: public HInstruction {
3359 public:
3360 HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
3361 : shared_info_(shared), pretenure_(pretenure) {
3362 set_representation(Representation::Tagged());
3363 }
3364
3365 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
3366
3367 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
3368 bool pretenure() const { return pretenure_; }
3369
3370 private:
3371 Handle<SharedFunctionInfo> shared_info_;
3372 bool pretenure_;
3373};
3374
3375
3376class HTypeof: public HUnaryOperation {
3377 public:
3378 explicit HTypeof(HValue* value) : HUnaryOperation(value) {
3379 set_representation(Representation::Tagged());
3380 }
3381
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003382 virtual Representation RequiredInputRepresentation(int index) const {
3383 return Representation::Tagged();
3384 }
3385
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003386 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
3387};
3388
3389
3390class HValueOf: public HUnaryOperation {
3391 public:
3392 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
3393 set_representation(Representation::Tagged());
3394 }
3395
3396 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
3397};
3398
3399
3400class HDeleteProperty: public HBinaryOperation {
3401 public:
3402 HDeleteProperty(HValue* obj, HValue* key)
3403 : HBinaryOperation(obj, key) {
3404 set_representation(Representation::Tagged());
ager@chromium.org378b34e2011-01-28 08:04:38 +00003405 SetAllSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00003406 }
3407
3408 virtual Representation RequiredInputRepresentation(int index) const {
3409 return Representation::Tagged();
3410 }
3411
3412 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
3413
3414 HValue* object() const { return left(); }
3415 HValue* key() const { return right(); }
3416};
3417
3418#undef DECLARE_INSTRUCTION
3419#undef DECLARE_CONCRETE_INSTRUCTION
3420
3421} } // namespace v8::internal
3422
3423#endif // V8_HYDROGEN_INSTRUCTIONS_H_