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