| Index: src/hydrogen-instructions.h
|
| ===================================================================
|
| --- src/hydrogen-instructions.h (revision 7948)
|
| +++ src/hydrogen-instructions.h (working copy)
|
| @@ -30,6 +30,7 @@
|
|
|
| #include "v8.h"
|
|
|
| +#include "allocation.h"
|
| #include "code-stubs.h"
|
| #include "data-flow.h"
|
| #include "small-pointer-list.h"
|
| @@ -86,10 +87,12 @@
|
| V(CheckNonSmi) \
|
| V(CheckPrototypeMaps) \
|
| V(CheckSmi) \
|
| + V(ClampToUint8) \
|
| V(ClassOfTest) \
|
| V(Compare) \
|
| V(CompareJSObjectEq) \
|
| V(CompareMap) \
|
| + V(CompareSymbolEq) \
|
| V(Constant) \
|
| V(Context) \
|
| V(DeleteProperty) \
|
| @@ -98,6 +101,7 @@
|
| V(EnterInlined) \
|
| V(ExternalArrayLength) \
|
| V(FixedArrayLength) \
|
| + V(ForceRepresentation) \
|
| V(FunctionLiteral) \
|
| V(GetCachedArrayIndex) \
|
| V(GlobalObject) \
|
| @@ -109,10 +113,11 @@
|
| V(InstanceOf) \
|
| V(InstanceOfKnownGlobal) \
|
| V(InvokeFunction) \
|
| + V(IsConstructCall) \
|
| V(IsNull) \
|
| V(IsObject) \
|
| V(IsSmi) \
|
| - V(IsConstructCall) \
|
| + V(IsUndetectable) \
|
| V(JSArrayLength) \
|
| V(LeaveInlined) \
|
| V(LoadContextSlot) \
|
| @@ -548,12 +553,12 @@
|
| Representation representation() const { return representation_; }
|
| void ChangeRepresentation(Representation r) {
|
| // Representation was already set and is allowed to be changed.
|
| - ASSERT(!representation_.IsNone());
|
| ASSERT(!r.IsNone());
|
| ASSERT(CheckFlag(kFlexibleRepresentation));
|
| RepresentationChanged(r);
|
| representation_ = r;
|
| }
|
| + void AssumeRepresentation(Representation r);
|
|
|
| virtual bool IsConvertibleToInteger() const { return true; }
|
|
|
| @@ -627,7 +632,9 @@
|
| // Printing support.
|
| virtual void PrintTo(StringStream* stream) = 0;
|
| void PrintNameTo(StringStream* stream);
|
| - static void PrintTypeTo(HType type, StringStream* stream);
|
| + void PrintTypeTo(StringStream* stream);
|
| + void PrintRangeTo(StringStream* stream);
|
| + void PrintChangesTo(StringStream* stream);
|
|
|
| const char* Mnemonic() const;
|
|
|
| @@ -740,6 +747,8 @@
|
| SetBlock(block);
|
| }
|
|
|
| + void PrintMnemonicTo(StringStream* stream);
|
| +
|
| HInstruction* next_;
|
| HInstruction* previous_;
|
| int position_;
|
| @@ -855,6 +864,11 @@
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
|
|
|
| + enum UseEnvironment {
|
| + kNoUses,
|
| + kUseAll
|
| + };
|
| +
|
| protected:
|
| virtual void InternalSetOperandAt(int index, HValue* value) {
|
| values_[index] = value;
|
| @@ -996,6 +1010,25 @@
|
| };
|
|
|
|
|
| +class HForceRepresentation: public HTemplateInstruction<1> {
|
| + public:
|
| + HForceRepresentation(HValue* value, Representation required_representation) {
|
| + SetOperandAt(0, value);
|
| + set_representation(required_representation);
|
| + }
|
| +
|
| + HValue* value() { return OperandAt(0); }
|
| +
|
| + virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return representation(); // Same as the output representation.
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
|
| +};
|
| +
|
| +
|
| class HChange: public HUnaryOperation {
|
| public:
|
| HChange(HValue* value,
|
| @@ -1041,6 +1074,46 @@
|
| };
|
|
|
|
|
| +class HClampToUint8: public HUnaryOperation {
|
| + public:
|
| + explicit HClampToUint8(HValue* value)
|
| + : HUnaryOperation(value),
|
| + input_rep_(Representation::None()) {
|
| + SetFlag(kFlexibleRepresentation);
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return input_rep_;
|
| + }
|
| +
|
| + virtual Representation InferredRepresentation() {
|
| + // TODO(danno): Inference on input types should happen separately from
|
| + // return representation.
|
| + Representation new_rep = value()->representation();
|
| + if (input_rep_.IsNone()) {
|
| + if (!new_rep.IsNone()) {
|
| + input_rep_ = new_rep;
|
| + return Representation::Integer32();
|
| + } else {
|
| + return Representation::None();
|
| + }
|
| + } else {
|
| + return Representation::Integer32();
|
| + }
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) { return true; }
|
| +
|
| + private:
|
| + Representation input_rep_;
|
| +};
|
| +
|
| +
|
| class HSimulate: public HInstruction {
|
| public:
|
| HSimulate(int ast_id, int pop_count)
|
| @@ -1756,20 +1829,18 @@
|
|
|
| class HCheckInstanceType: public HUnaryOperation {
|
| public:
|
| - // Check that the instance type is in the range [first, last] where
|
| - // both first and last are included.
|
| - HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
|
| - : HUnaryOperation(value), first_(first), last_(last) {
|
| - ASSERT(first <= last);
|
| - set_representation(Representation::Tagged());
|
| - SetFlag(kUseGVN);
|
| - if ((FIRST_STRING_TYPE < first && last <= LAST_STRING_TYPE) ||
|
| - (FIRST_STRING_TYPE <= first && last < LAST_STRING_TYPE)) {
|
| - // A particular string instance type can change because of GC or
|
| - // externalization, but the value still remains a string.
|
| - SetFlag(kDependsOnMaps);
|
| - }
|
| + static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value) {
|
| + return new HCheckInstanceType(value, IS_JS_OBJECT_OR_JS_FUNCTION);
|
| }
|
| + static HCheckInstanceType* NewIsJSArray(HValue* value) {
|
| + return new HCheckInstanceType(value, IS_JS_ARRAY);
|
| + }
|
| + static HCheckInstanceType* NewIsString(HValue* value) {
|
| + return new HCheckInstanceType(value, IS_STRING);
|
| + }
|
| + static HCheckInstanceType* NewIsSymbol(HValue* value) {
|
| + return new HCheckInstanceType(value, IS_SYMBOL);
|
| + }
|
|
|
| virtual bool IsCheckInstruction() const { return true; }
|
|
|
| @@ -1784,18 +1855,16 @@
|
| virtual HValue* Canonicalize() {
|
| if (!value()->type().IsUninitialized() &&
|
| value()->type().IsString() &&
|
| - first() == FIRST_STRING_TYPE &&
|
| - last() == LAST_STRING_TYPE) {
|
| + check_ == IS_STRING) {
|
| return NULL;
|
| }
|
| return this;
|
| }
|
|
|
| - static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
|
| + bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
|
| + void GetCheckInterval(InstanceType* first, InstanceType* last);
|
| + void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
|
|
|
| - InstanceType first() const { return first_; }
|
| - InstanceType last() const { return last_; }
|
| -
|
| DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
|
|
|
| protected:
|
| @@ -1804,12 +1873,25 @@
|
| // with a larger range.
|
| virtual bool DataEquals(HValue* other) {
|
| HCheckInstanceType* b = HCheckInstanceType::cast(other);
|
| - return (first_ == b->first()) && (last_ == b->last());
|
| + return check_ == b->check_;
|
| }
|
|
|
| private:
|
| - InstanceType first_;
|
| - InstanceType last_;
|
| + enum Check {
|
| + IS_JS_OBJECT_OR_JS_FUNCTION,
|
| + IS_JS_ARRAY,
|
| + IS_STRING,
|
| + IS_SYMBOL,
|
| + LAST_INTERVAL_CHECK = IS_JS_ARRAY
|
| + };
|
| +
|
| + HCheckInstanceType(HValue* value, Check check)
|
| + : HUnaryOperation(value), check_(check) {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + const Check check_;
|
| };
|
|
|
|
|
| @@ -2395,6 +2477,40 @@
|
| };
|
|
|
|
|
| +class HCompareSymbolEq: public HBinaryOperation {
|
| + public:
|
| + HCompareSymbolEq(HValue* left, HValue* right, Token::Value op)
|
| + : HBinaryOperation(left, right), op_(op) {
|
| + ASSERT(op == Token::EQ || op == Token::EQ_STRICT);
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + SetFlag(kDependsOnMaps);
|
| + }
|
| +
|
| + Token::Value op() const { return op_; }
|
| +
|
| + virtual bool EmitAtUses() {
|
| + return !HasSideEffects() && !HasMultipleUses();
|
| + }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return Representation::Tagged();
|
| + }
|
| +
|
| + virtual HType CalculateInferredType() { return HType::Boolean(); }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(CompareSymbolEq);
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) {
|
| + return op_ == HCompareSymbolEq::cast(other)->op_;
|
| + }
|
| +
|
| + private:
|
| + const Token::Value op_;
|
| +};
|
| +
|
| +
|
| class HUnaryPredicate: public HUnaryOperation {
|
| public:
|
| explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
|
| @@ -2455,6 +2571,17 @@
|
| };
|
|
|
|
|
| +class HIsUndetectable: public HUnaryPredicate {
|
| + public:
|
| + explicit HIsUndetectable(HValue* value) : HUnaryPredicate(value) { }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(IsUndetectable)
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) { return true; }
|
| +};
|
| +
|
| +
|
| class HIsConstructCall: public HTemplateInstruction<0> {
|
| public:
|
| HIsConstructCall() {
|
| @@ -3253,6 +3380,8 @@
|
|
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| + bool RequiresHoleCheck() const;
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement)
|
|
|
| protected:
|
| @@ -3309,7 +3438,7 @@
|
|
|
| class HLoadKeyedGeneric: public HTemplateInstruction<3> {
|
| public:
|
| - HLoadKeyedGeneric(HContext* context, HValue* obj, HValue* key) {
|
| + HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
|
| set_representation(Representation::Tagged());
|
| SetOperandAt(0, obj);
|
| SetOperandAt(1, key);
|
|
|