| Index: src/hydrogen-instructions.h
|
| ===================================================================
|
| --- src/hydrogen-instructions.h (revision 6800)
|
| +++ src/hydrogen-instructions.h (working copy)
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2010 the V8 project authors. All rights reserved.
|
| +// Copyright 2011 the V8 project authors. All rights reserved.
|
| // Redistribution and use in source and binary forms, with or without
|
| // modification, are permitted provided that the following conditions are
|
| // met:
|
| @@ -46,110 +46,9 @@
|
| class LChunkBuilder;
|
|
|
|
|
| -// Type hierarchy:
|
| -//
|
| -// HValue
|
| -// HInstruction
|
| -// HAccessArgumentsAt
|
| -// HApplyArguments
|
| -// HArgumentsElements
|
| -// HArgumentsLength
|
| -// HArgumentsObject
|
| -// HBinaryOperation
|
| -// HArithmeticBinaryOperation
|
| -// HAdd
|
| -// HDiv
|
| -// HMod
|
| -// HMul
|
| -// HSub
|
| -// HBitwiseBinaryOperation
|
| -// HBitAnd
|
| -// HBitOr
|
| -// HBitXor
|
| -// HSar
|
| -// HShl
|
| -// HShr
|
| -// HBoundsCheck
|
| -// HCompare
|
| -// HCompareJSObjectEq
|
| -// HInstanceOf
|
| -// HLoadKeyed
|
| -// HLoadKeyedFastElement
|
| -// HLoadKeyedGeneric
|
| -// HPower
|
| -// HStoreNamed
|
| -// HStoreNamedField
|
| -// HStoreNamedGeneric
|
| -// HBlockEntry
|
| -// HCall
|
| -// HCallConstantFunction
|
| -// HCallFunction
|
| -// HCallGlobal
|
| -// HCallKeyed
|
| -// HCallKnownGlobal
|
| -// HCallNamed
|
| -// HCallNew
|
| -// HCallRuntime
|
| -// HCallStub
|
| -// HConstant
|
| -// HControlInstruction
|
| -// HDeoptimize
|
| -// HGoto
|
| -// HUnaryControlInstruction
|
| -// HBranch
|
| -// HCompareMapAndBranch
|
| -// HReturn
|
| -// HThrow
|
| -// HEnterInlined
|
| -// HFunctionLiteral
|
| -// HGlobalObject
|
| -// HGlobalReceiver
|
| -// HLeaveInlined
|
| -// HLoadGlobal
|
| -// HMaterializedLiteral
|
| -// HArrayLiteral
|
| -// HObjectLiteral
|
| -// HRegExpLiteral
|
| -// HOsrEntry
|
| -// HParameter
|
| -// HSimulate
|
| -// HStackCheck
|
| -// HStoreKeyed
|
| -// HStoreKeyedFastElement
|
| -// HStoreKeyedGeneric
|
| -// HUnaryOperation
|
| -// HBitNot
|
| -// HChange
|
| -// HCheckFunction
|
| -// HCheckInstanceType
|
| -// HCheckMap
|
| -// HCheckNonSmi
|
| -// HCheckPrototypeMaps
|
| -// HCheckSmi
|
| -// HDeleteProperty
|
| -// HFixedArrayLength
|
| -// HJSArrayLength
|
| -// HLoadElements
|
| -// HTypeofIs
|
| -// HLoadNamedField
|
| -// HLoadNamedGeneric
|
| -// HLoadFunctionPrototype
|
| -// HPushArgument
|
| -// HTypeof
|
| -// HUnaryMathOperation
|
| -// HUnaryPredicate
|
| -// HClassOfTest
|
| -// HHasCachedArrayIndex
|
| -// HHasInstanceType
|
| -// HIsNull
|
| -// HIsObject
|
| -// HIsSmi
|
| -// HValueOf
|
| -// HUnknownOSRValue
|
| -// HPhi
|
| -
|
| #define HYDROGEN_ALL_INSTRUCTION_LIST(V) \
|
| V(ArithmeticBinaryOperation) \
|
| + V(BinaryCall) \
|
| V(BinaryOperation) \
|
| V(BitwiseBinaryOperation) \
|
| V(Call) \
|
| @@ -160,12 +59,14 @@
|
| V(Phi) \
|
| V(StoreKeyed) \
|
| V(StoreNamed) \
|
| + V(UnaryCall) \
|
| V(UnaryControlInstruction) \
|
| V(UnaryOperation) \
|
| HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
|
|
|
|
|
| #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
|
| + V(AbnormalExit) \
|
| V(AccessArgumentsAt) \
|
| V(Add) \
|
| V(ApplyArguments) \
|
| @@ -179,7 +80,6 @@
|
| V(BitXor) \
|
| V(BlockEntry) \
|
| V(BoundsCheck) \
|
| - V(Branch) \
|
| V(CallConstantFunction) \
|
| V(CallFunction) \
|
| V(CallGlobal) \
|
| @@ -198,8 +98,9 @@
|
| V(CheckSmi) \
|
| V(Compare) \
|
| V(CompareJSObjectEq) \
|
| - V(CompareMapAndBranch) \
|
| + V(CompareMap) \
|
| V(Constant) \
|
| + V(Context) \
|
| V(DeleteProperty) \
|
| V(Deoptimize) \
|
| V(Div) \
|
| @@ -210,26 +111,33 @@
|
| V(GlobalReceiver) \
|
| V(Goto) \
|
| V(InstanceOf) \
|
| + V(InstanceOfKnownGlobal) \
|
| V(IsNull) \
|
| V(IsObject) \
|
| V(IsSmi) \
|
| + V(IsConstructCall) \
|
| V(HasInstanceType) \
|
| V(HasCachedArrayIndex) \
|
| V(JSArrayLength) \
|
| V(ClassOfTest) \
|
| V(LeaveInlined) \
|
| + V(LoadContextSlot) \
|
| V(LoadElements) \
|
| + V(LoadFunctionPrototype) \
|
| V(LoadGlobal) \
|
| V(LoadKeyedFastElement) \
|
| V(LoadKeyedGeneric) \
|
| V(LoadNamedField) \
|
| V(LoadNamedGeneric) \
|
| - V(LoadFunctionPrototype) \
|
| + V(LoadPixelArrayElement) \
|
| + V(LoadPixelArrayExternalPointer) \
|
| V(Mod) \
|
| V(Mul) \
|
| V(ObjectLiteral) \
|
| V(OsrEntry) \
|
| + V(OuterContext) \
|
| V(Parameter) \
|
| + V(PixelArrayLength) \
|
| V(Power) \
|
| V(PushArgument) \
|
| V(RegExpLiteral) \
|
| @@ -239,12 +147,16 @@
|
| V(Shr) \
|
| V(Simulate) \
|
| V(StackCheck) \
|
| + V(StoreContextSlot) \
|
| V(StoreGlobal) \
|
| V(StoreKeyedFastElement) \
|
| V(StoreKeyedGeneric) \
|
| V(StoreNamedField) \
|
| V(StoreNamedGeneric) \
|
| + V(StringCharCodeAt) \
|
| + V(StringLength) \
|
| V(Sub) \
|
| + V(Test) \
|
| V(Throw) \
|
| V(Typeof) \
|
| V(TypeofIs) \
|
| @@ -257,10 +169,11 @@
|
| V(InobjectFields) \
|
| V(BackingStoreFields) \
|
| V(ArrayElements) \
|
| + V(PixelArrayElements) \
|
| V(GlobalVars) \
|
| V(Maps) \
|
| V(ArrayLengths) \
|
| - V(FunctionPrototypes) \
|
| + V(ContextSlots) \
|
| V(OsrEntries)
|
|
|
| #define DECLARE_INSTRUCTION(type) \
|
| @@ -382,6 +295,7 @@
|
| kTagged,
|
| kDouble,
|
| kInteger32,
|
| + kExternal,
|
| kNumRepresentations
|
| };
|
|
|
| @@ -391,6 +305,7 @@
|
| static Representation Tagged() { return Representation(kTagged); }
|
| static Representation Integer32() { return Representation(kInteger32); }
|
| static Representation Double() { return Representation(kDouble); }
|
| + static Representation External() { return Representation(kExternal); }
|
|
|
| bool Equals(const Representation& other) const {
|
| return kind_ == other.kind_;
|
| @@ -401,6 +316,7 @@
|
| bool IsTagged() const { return kind_ == kTagged; }
|
| bool IsInteger32() const { return kind_ == kInteger32; }
|
| bool IsDouble() const { return kind_ == kDouble; }
|
| + bool IsExternal() const { return kind_ == kExternal; }
|
| bool IsSpecialization() const {
|
| return kind_ == kInteger32 || kind_ == kDouble;
|
| }
|
| @@ -565,11 +481,6 @@
|
| return flags << kChangesToDependsFlagsLeftShift;
|
| }
|
|
|
| - // A flag mask to mark an instruction as having arbitrary side effects.
|
| - static int AllSideEffects() {
|
| - return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
|
| - }
|
| -
|
| static HValue* cast(HValue* value) { return value; }
|
|
|
| enum Opcode {
|
| @@ -628,9 +539,6 @@
|
| return NULL;
|
| }
|
|
|
| - bool HasSideEffects() const {
|
| - return (flags_ & AllSideEffects()) != 0;
|
| - }
|
| bool IsDefinedAfter(HBasicBlock* other) const;
|
|
|
| // Operands.
|
| @@ -653,13 +561,14 @@
|
| void Delete();
|
|
|
| int flags() const { return flags_; }
|
| - void SetFlagMask(int mask) { flags_ |= mask; }
|
| - void SetFlag(Flag f) { SetFlagMask(1 << f); }
|
| - void ClearFlagMask(int mask) { flags_ &= ~mask; }
|
| - void ClearFlag(Flag f) { ClearFlagMask(1 << f); }
|
| - bool CheckFlag(Flag f) const { return CheckFlagMask(1 << f); }
|
| - bool CheckFlagMask(int mask) const { return (flags_ & mask) != 0; }
|
| + void SetFlag(Flag f) { flags_ |= (1 << f); }
|
| + void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
|
| + bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
|
|
|
| + void SetAllSideEffects() { flags_ |= AllSideEffects(); }
|
| + void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
|
| + bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
|
| +
|
| Range* range() const { return range_; }
|
| bool HasRange() const { return range_ != NULL; }
|
| void AddNewRange(Range* r);
|
| @@ -702,15 +611,17 @@
|
|
|
| virtual HType CalculateInferredType() const;
|
|
|
| - // Helper for type conversions used by normal and phi instructions.
|
| - void InsertInputConversion(HInstruction* previous, int index, HType type);
|
| -
|
| #ifdef DEBUG
|
| - virtual void Verify() const = 0;
|
| + virtual void Verify() = 0;
|
| #endif
|
|
|
| protected:
|
| - virtual bool DataEquals(HValue* other) const { return true; }
|
| + // This function must be overridden for instructions with flag kUseGVN, to
|
| + // compare the non-Operand parts of the instruction.
|
| + virtual bool DataEquals(HValue* other) const {
|
| + UNREACHABLE();
|
| + return false;
|
| + }
|
| virtual void RepresentationChanged(Representation to) { }
|
| virtual Range* InferRange();
|
| virtual void DeleteFromGraph() = 0;
|
| @@ -727,6 +638,11 @@
|
| }
|
|
|
| private:
|
| + // A flag mask to mark an instruction as having arbitrary side effects.
|
| + static int AllSideEffects() {
|
| + return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
|
| + }
|
| +
|
| void InternalReplaceAtUse(HValue* use, HValue* other);
|
| void RegisterUse(int index, HValue* new_value);
|
|
|
| @@ -766,9 +682,13 @@
|
| virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const;
|
| + virtual void Verify();
|
| #endif
|
|
|
| + // Returns whether this is some kind of deoptimizing check
|
| + // instruction.
|
| + virtual bool IsCheckInstruction() const { return false; }
|
| +
|
| DECLARE_INSTRUCTION(Instruction)
|
|
|
| protected:
|
| @@ -803,44 +723,55 @@
|
|
|
| class HControlInstruction: public HInstruction {
|
| public:
|
| - virtual HBasicBlock* FirstSuccessor() const { return NULL; }
|
| - virtual HBasicBlock* SecondSuccessor() const { return NULL; }
|
| + HControlInstruction(HBasicBlock* first, HBasicBlock* second)
|
| + : first_successor_(first), second_successor_(second) {
|
| + }
|
|
|
| + HBasicBlock* FirstSuccessor() const { return first_successor_; }
|
| + HBasicBlock* SecondSuccessor() const { return second_successor_; }
|
| +
|
| + virtual void PrintDataTo(StringStream* stream) const;
|
| +
|
| DECLARE_INSTRUCTION(ControlInstruction)
|
| +
|
| + private:
|
| + HBasicBlock* first_successor_;
|
| + HBasicBlock* second_successor_;
|
| };
|
|
|
|
|
| class HDeoptimize: public HControlInstruction {
|
| public:
|
| + HDeoptimize() : HControlInstruction(NULL, NULL) { }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
|
| };
|
|
|
|
|
| class HGoto: public HControlInstruction {
|
| public:
|
| - explicit HGoto(HBasicBlock* destination)
|
| - : destination_(destination),
|
| - include_stack_check_(false) {}
|
| + explicit HGoto(HBasicBlock* target)
|
| + : HControlInstruction(target, NULL), include_stack_check_(false) {
|
| + }
|
|
|
| - virtual HBasicBlock* FirstSuccessor() const { return destination_; }
|
| void set_include_stack_check(bool include_stack_check) {
|
| include_stack_check_ = include_stack_check;
|
| }
|
| bool include_stack_check() const { return include_stack_check_; }
|
|
|
| - virtual void PrintDataTo(StringStream* stream) const;
|
| -
|
| DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
|
|
|
| private:
|
| - HBasicBlock* destination_;
|
| bool include_stack_check_;
|
| };
|
|
|
|
|
| class HUnaryControlInstruction: public HControlInstruction {
|
| public:
|
| - explicit HUnaryControlInstruction(HValue* value) {
|
| + explicit HUnaryControlInstruction(HValue* value,
|
| + HBasicBlock* true_target,
|
| + HBasicBlock* false_target)
|
| + : HControlInstruction(true_target, false_target) {
|
| SetOperandAt(0, value);
|
| }
|
|
|
| @@ -848,6 +779,8 @@
|
| return Representation::Tagged();
|
| }
|
|
|
| + virtual void PrintDataTo(StringStream* stream) const;
|
| +
|
| HValue* value() const { return OperandAt(0); }
|
| virtual int OperandCount() const { return 1; }
|
| virtual HValue* OperandAt(int index) const { return operands_[index]; }
|
| @@ -864,85 +797,60 @@
|
| };
|
|
|
|
|
| -class HBranch: public HUnaryControlInstruction {
|
| +class HTest: public HUnaryControlInstruction {
|
| public:
|
| - HBranch(HBasicBlock* true_destination,
|
| - HBasicBlock* false_destination,
|
| - HValue* boolean_value)
|
| - : HUnaryControlInstruction(boolean_value),
|
| - true_destination_(true_destination),
|
| - false_destination_(false_destination) {
|
| - ASSERT(true_destination != NULL && false_destination != NULL);
|
| + HTest(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target)
|
| + : HUnaryControlInstruction(value, true_target, false_target) {
|
| + ASSERT(true_target != NULL && false_target != NULL);
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::None();
|
| }
|
|
|
| - virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
|
| - virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
|
| -
|
| - virtual void PrintDataTo(StringStream* stream) const;
|
| -
|
| - DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
|
| -
|
| - private:
|
| - HBasicBlock* true_destination_;
|
| - HBasicBlock* false_destination_;
|
| + DECLARE_CONCRETE_INSTRUCTION(Test, "test")
|
| };
|
|
|
|
|
| -class HCompareMapAndBranch: public HUnaryControlInstruction {
|
| +class HCompareMap: public HUnaryControlInstruction {
|
| public:
|
| - HCompareMapAndBranch(HValue* result,
|
| - Handle<Map> map,
|
| - HBasicBlock* true_destination,
|
| - HBasicBlock* false_destination)
|
| - : HUnaryControlInstruction(result),
|
| - map_(map),
|
| - true_destination_(true_destination),
|
| - false_destination_(false_destination) {
|
| - ASSERT(true_destination != NULL);
|
| - ASSERT(false_destination != NULL);
|
| + HCompareMap(HValue* value,
|
| + Handle<Map> map,
|
| + HBasicBlock* true_target,
|
| + HBasicBlock* false_target)
|
| + : HUnaryControlInstruction(value, true_target, false_target),
|
| + map_(map) {
|
| + ASSERT(true_target != NULL);
|
| + ASSERT(false_target != NULL);
|
| ASSERT(!map.is_null());
|
| }
|
|
|
| - virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
|
| - virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
|
| -
|
| - HBasicBlock* true_destination() const { return true_destination_; }
|
| - HBasicBlock* false_destination() const { return false_destination_; }
|
| -
|
| virtual void PrintDataTo(StringStream* stream) const;
|
|
|
| Handle<Map> map() const { return map_; }
|
|
|
| - DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch")
|
| + DECLARE_CONCRETE_INSTRUCTION(CompareMap, "compare_map")
|
|
|
| private:
|
| Handle<Map> map_;
|
| - HBasicBlock* true_destination_;
|
| - HBasicBlock* false_destination_;
|
| };
|
|
|
|
|
| class HReturn: public HUnaryControlInstruction {
|
| public:
|
| - explicit HReturn(HValue* result) : HUnaryControlInstruction(result) { }
|
| + explicit HReturn(HValue* value)
|
| + : HUnaryControlInstruction(value, NULL, NULL) {
|
| + }
|
|
|
| - virtual void PrintDataTo(StringStream* stream) const;
|
| -
|
| DECLARE_CONCRETE_INSTRUCTION(Return, "return")
|
| };
|
|
|
|
|
| -class HThrow: public HUnaryControlInstruction {
|
| +class HAbnormalExit: public HControlInstruction {
|
| public:
|
| - explicit HThrow(HValue* value) : HUnaryControlInstruction(value) { }
|
| + HAbnormalExit() : HControlInstruction(NULL, NULL) { }
|
|
|
| - virtual void PrintDataTo(StringStream* stream) const;
|
| -
|
| - DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
|
| + DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
|
| };
|
|
|
|
|
| @@ -969,6 +877,20 @@
|
| };
|
|
|
|
|
| +class HThrow: public HUnaryOperation {
|
| + public:
|
| + explicit HThrow(HValue* value) : HUnaryOperation(value) {
|
| + SetAllSideEffects();
|
| + }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return Representation::Tagged();
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
|
| +};
|
| +
|
| +
|
| class HChange: public HUnaryOperation {
|
| public:
|
| HChange(HValue* value,
|
| @@ -1062,7 +984,7 @@
|
| DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const;
|
| + virtual void Verify();
|
| #endif
|
|
|
| protected:
|
| @@ -1092,7 +1014,7 @@
|
| public:
|
| HStackCheck() { }
|
|
|
| - DECLARE_CONCRETE_INSTRUCTION(Throw, "stack_check")
|
| + DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
|
| };
|
|
|
|
|
| @@ -1125,86 +1047,151 @@
|
|
|
| class HPushArgument: public HUnaryOperation {
|
| public:
|
| - explicit HPushArgument(HValue* value)
|
| - : HUnaryOperation(value), argument_index_(-1) {
|
| - set_representation(Representation::Tagged());
|
| - }
|
| + explicit HPushArgument(HValue* value) : HUnaryOperation(value) { }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
|
|
| - virtual void PrintDataTo(StringStream* stream) const;
|
| HValue* argument() const { return OperandAt(0); }
|
| - int argument_index() const { return argument_index_; }
|
| - void set_argument_index(int index) {
|
| - ASSERT(argument_index_ == -1 || index == argument_index_);
|
| - argument_index_ = index;
|
| - }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
|
| +};
|
|
|
| - private:
|
| - int argument_index_;
|
| +
|
| +class HContext: public HInstruction {
|
| + public:
|
| + HContext() {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(Context, "context");
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| -class HGlobalObject: public HInstruction {
|
| +class HOuterContext: public HUnaryOperation {
|
| public:
|
| - HGlobalObject() {
|
| + explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
|
| set_representation(Representation::Tagged());
|
| SetFlag(kUseGVN);
|
| - SetFlag(kDependsOnCalls);
|
| }
|
|
|
| + DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer_context");
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +};
|
| +
|
| +
|
| +class HGlobalObject: public HUnaryOperation {
|
| + public:
|
| + explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| -class HGlobalReceiver: public HInstruction {
|
| +class HGlobalReceiver: public HUnaryOperation {
|
| public:
|
| - HGlobalReceiver() {
|
| + explicit HGlobalReceiver(HValue* global_object)
|
| + : HUnaryOperation(global_object) {
|
| set_representation(Representation::Tagged());
|
| SetFlag(kUseGVN);
|
| - SetFlag(kDependsOnCalls);
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| class HCall: public HInstruction {
|
| public:
|
| - // Construct a call with uninitialized arguments. The argument count
|
| - // includes the receiver.
|
| - explicit HCall(int count);
|
| + // The argument count includes the receiver.
|
| + explicit HCall(int argument_count) : argument_count_(argument_count) {
|
| + set_representation(Representation::Tagged());
|
| + SetAllSideEffects();
|
| + }
|
|
|
| virtual HType CalculateInferredType() const { return HType::Tagged(); }
|
|
|
| - // TODO(3190496): This needs a cleanup. We don't want the arguments
|
| - // be operands of the call instruction. This results in bad code quality.
|
| - virtual int argument_count() const { return arguments_.length(); }
|
| - virtual int OperandCount() const { return argument_count(); }
|
| - virtual HValue* OperandAt(int index) const { return arguments_[index]; }
|
| - virtual HPushArgument* PushArgumentAt(int index) const {
|
| - return HPushArgument::cast(OperandAt(index));
|
| + virtual int argument_count() const { return argument_count_; }
|
| +
|
| + virtual void PrintDataTo(StringStream* stream) const;
|
| +
|
| + DECLARE_INSTRUCTION(Call)
|
| +
|
| + private:
|
| + int argument_count_;
|
| +};
|
| +
|
| +
|
| +class HUnaryCall: public HCall {
|
| + public:
|
| + HUnaryCall(HValue* value, int argument_count)
|
| + : HCall(argument_count), value_(NULL) {
|
| + SetOperandAt(0, value);
|
| }
|
| - virtual HValue* ArgumentAt(int index) const {
|
| - return PushArgumentAt(index)->argument();
|
| +
|
| + virtual void PrintDataTo(StringStream* stream) const;
|
| +
|
| + HValue* value() const { return value_; }
|
| +
|
| + virtual int OperandCount() const { return 1; }
|
| + virtual HValue* OperandAt(int index) const {
|
| + ASSERT(index == 0);
|
| + return value_;
|
| }
|
| - virtual void SetArgumentAt(int index, HPushArgument* push_argument);
|
|
|
| + DECLARE_INSTRUCTION(UnaryCall)
|
| +
|
| + protected:
|
| + virtual void InternalSetOperandAt(int index, HValue* value) {
|
| + ASSERT(index == 0);
|
| + value_ = value;
|
| + }
|
| +
|
| + private:
|
| + HValue* value_;
|
| +};
|
| +
|
| +
|
| +class HBinaryCall: public HCall {
|
| + public:
|
| + HBinaryCall(HValue* first, HValue* second, int argument_count)
|
| + : HCall(argument_count) {
|
| + SetOperandAt(0, first);
|
| + SetOperandAt(1, second);
|
| + }
|
| +
|
| virtual void PrintDataTo(StringStream* stream) const;
|
|
|
| - DECLARE_INSTRUCTION(Call)
|
| + HValue* first() const { return operands_[0]; }
|
| + HValue* second() const { return operands_[1]; }
|
|
|
| + virtual int OperandCount() const { return 2; }
|
| + virtual HValue* OperandAt(int index) const { return operands_[index]; }
|
| +
|
| + DECLARE_INSTRUCTION(BinaryCall)
|
| +
|
| protected:
|
| virtual void InternalSetOperandAt(int index, HValue* value) {
|
| - arguments_[index] = value;
|
| + operands_[index] = value;
|
| }
|
|
|
| - int argument_count_;
|
| - Vector<HValue*> arguments_;
|
| + private:
|
| + HOperandVector<2> operands_;
|
| };
|
|
|
|
|
| @@ -1214,6 +1201,7 @@
|
| : HCall(argument_count), function_(function) { }
|
|
|
| Handle<JSFunction> function() const { return function_; }
|
| +
|
| bool IsApplyFunction() const {
|
| return function_->code() == Builtins::builtin(Builtins::FunctionApply);
|
| }
|
| @@ -1227,42 +1215,32 @@
|
| };
|
|
|
|
|
| -class HCallKeyed: public HCall {
|
| +class HCallKeyed: public HBinaryCall {
|
| public:
|
| - HCallKeyed(HValue* key, int argument_count)
|
| - : HCall(argument_count + 1) {
|
| - SetOperandAt(0, key);
|
| + HCallKeyed(HValue* context, HValue* key, int argument_count)
|
| + : HBinaryCall(context, key, argument_count) {
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
|
|
| - // TODO(3190496): This is a hack to get an additional operand that
|
| - // is not an argument to work with the current setup. This _needs_ a cleanup.
|
| - // (see HCall)
|
| - virtual void PrintDataTo(StringStream* stream) const;
|
| - HValue* key() const { return OperandAt(0); }
|
| - virtual int argument_count() const { return arguments_.length() - 1; }
|
| - virtual int OperandCount() const { return arguments_.length(); }
|
| - virtual HValue* OperandAt(int index) const { return arguments_[index]; }
|
| - virtual HPushArgument* PushArgumentAt(int index) const {
|
| - return HPushArgument::cast(OperandAt(index + 1));
|
| - }
|
| - virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
|
| - HCall::SetArgumentAt(index + 1, push_argument);
|
| - }
|
| + HValue* context() const { return first(); }
|
| + HValue* key() const { return second(); }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
|
| };
|
|
|
|
|
| -class HCallNamed: public HCall {
|
| +class HCallNamed: public HUnaryCall {
|
| public:
|
| - HCallNamed(Handle<String> name, int argument_count)
|
| - : HCall(argument_count), name_(name) { }
|
| + HCallNamed(HValue* context, Handle<String> name, int argument_count)
|
| + : HUnaryCall(context, argument_count), name_(name) {
|
| + }
|
| +
|
| virtual void PrintDataTo(StringStream* stream) const;
|
|
|
| + HValue* context() const { return value(); }
|
| Handle<String> name() const { return name_; }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
|
| @@ -1272,21 +1250,27 @@
|
| };
|
|
|
|
|
| -class HCallFunction: public HCall {
|
| +class HCallFunction: public HUnaryCall {
|
| public:
|
| - explicit HCallFunction(int argument_count) : HCall(argument_count) { }
|
| + HCallFunction(HValue* context, int argument_count)
|
| + : HUnaryCall(context, argument_count) {
|
| + }
|
|
|
| + HValue* context() const { return value(); }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
|
| };
|
|
|
|
|
| -class HCallGlobal: public HCall {
|
| +class HCallGlobal: public HUnaryCall {
|
| public:
|
| - HCallGlobal(Handle<String> name, int argument_count)
|
| - : HCall(argument_count), name_(name) { }
|
| + HCallGlobal(HValue* context, Handle<String> name, int argument_count)
|
| + : HUnaryCall(context, argument_count), name_(name) {
|
| + }
|
|
|
| virtual void PrintDataTo(StringStream* stream) const;
|
|
|
| + HValue* context() const { return value(); }
|
| Handle<String> name() const { return name_; }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
|
| @@ -1298,10 +1282,11 @@
|
|
|
| class HCallKnownGlobal: public HCall {
|
| public:
|
| - HCallKnownGlobal(Handle<JSFunction> target,
|
| - int argument_count)
|
| + HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
|
| : HCall(argument_count), target_(target) { }
|
|
|
| + virtual void PrintDataTo(StringStream* stream) const;
|
| +
|
| Handle<JSFunction> target() const { return target_; }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
|
| @@ -1311,15 +1296,18 @@
|
| };
|
|
|
|
|
| -class HCallNew: public HCall {
|
| +class HCallNew: public HBinaryCall {
|
| public:
|
| - explicit HCallNew(int argument_count) : HCall(argument_count) { }
|
| + HCallNew(HValue* context, HValue* constructor, int argument_count)
|
| + : HBinaryCall(context, constructor, argument_count) {
|
| + }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
|
|
| - HValue* constructor() const { return ArgumentAt(0); }
|
| + HValue* context() const { return first(); }
|
| + HValue* constructor() const { return second(); }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
|
| };
|
| @@ -1360,6 +1348,9 @@
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -1376,9 +1367,33 @@
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| +class HPixelArrayLength: public HUnaryOperation {
|
| + public:
|
| + explicit HPixelArrayLength(HValue* value) : HUnaryOperation(value) {
|
| + set_representation(Representation::Integer32());
|
| + // The result of this instruction is idempotent as long as its inputs don't
|
| + // change. The length of a pixel array cannot change once set, so it's not
|
| + // necessary to introduce a kDependsOnArrayLengths or any other dependency.
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return Representation::Tagged();
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(PixelArrayLength, "pixel_array_length")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +};
|
| +
|
| +
|
| class HBitNot: public HUnaryOperation {
|
| public:
|
| explicit HBitNot(HValue* value) : HUnaryOperation(value) {
|
| @@ -1393,6 +1408,9 @@
|
| virtual HType CalculateInferredType() const;
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -1488,9 +1506,36 @@
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| +class HLoadPixelArrayExternalPointer: public HUnaryOperation {
|
| + public:
|
| + explicit HLoadPixelArrayExternalPointer(HValue* value)
|
| + : HUnaryOperation(value) {
|
| + set_representation(Representation::External());
|
| + // The result of this instruction is idempotent as long as its inputs don't
|
| + // change. The external array of a pixel array elements object cannot
|
| + // change once set, so it's no necessary to introduce any additional
|
| + // dependencies on top of the inputs.
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return Representation::Tagged();
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayExternalPointer,
|
| + "load-pixel-array-external-pointer")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +};
|
| +
|
| +
|
| class HCheckMap: public HUnaryOperation {
|
| public:
|
| HCheckMap(HValue* value, Handle<Map> map)
|
| @@ -1500,6 +1545,8 @@
|
| SetFlag(kDependsOnMaps);
|
| }
|
|
|
| + virtual bool IsCheckInstruction() const { return true; }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
| @@ -1507,7 +1554,7 @@
|
| virtual HType CalculateInferredType() const;
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const;
|
| + virtual void Verify();
|
| #endif
|
|
|
| Handle<Map> map() const { return map_; }
|
| @@ -1533,6 +1580,8 @@
|
| SetFlag(kUseGVN);
|
| }
|
|
|
| + virtual bool IsCheckInstruction() const { return true; }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
| @@ -1540,7 +1589,7 @@
|
| virtual HType CalculateInferredType() const;
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const;
|
| + virtual void Verify();
|
| #endif
|
|
|
| Handle<JSFunction> target() const { return target_; }
|
| @@ -1567,14 +1616,22 @@
|
| 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);
|
| + }
|
| }
|
|
|
| + virtual bool IsCheckInstruction() const { return true; }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const;
|
| + virtual void Verify();
|
| #endif
|
|
|
| static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
|
| @@ -1606,6 +1663,8 @@
|
| SetFlag(kUseGVN);
|
| }
|
|
|
| + virtual bool IsCheckInstruction() const { return true; }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
| @@ -1613,49 +1672,52 @@
|
| virtual HType CalculateInferredType() const;
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const;
|
| + virtual void Verify();
|
| #endif
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| -class HCheckPrototypeMaps: public HUnaryOperation {
|
| +class HCheckPrototypeMaps: public HInstruction {
|
| public:
|
| - HCheckPrototypeMaps(HValue* value,
|
| - Handle<JSObject> holder,
|
| - Handle<Map> receiver_map)
|
| - : HUnaryOperation(value),
|
| - holder_(holder),
|
| - receiver_map_(receiver_map) {
|
| - set_representation(Representation::Tagged());
|
| + HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
|
| + : prototype_(prototype), holder_(holder) {
|
| SetFlag(kUseGVN);
|
| SetFlag(kDependsOnMaps);
|
| }
|
|
|
| - virtual Representation RequiredInputRepresentation(int index) const {
|
| - return Representation::Tagged();
|
| - }
|
| + virtual bool IsCheckInstruction() const { return true; }
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const;
|
| + virtual void Verify();
|
| #endif
|
|
|
| + Handle<JSObject> prototype() const { return prototype_; }
|
| Handle<JSObject> holder() const { return holder_; }
|
| - Handle<Map> receiver_map() const { return receiver_map_; }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
|
|
|
| + virtual intptr_t Hashcode() const {
|
| + ASSERT(!Heap::IsAllocationAllowed());
|
| + intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
|
| + hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
|
| + return hash;
|
| + }
|
| +
|
| protected:
|
| virtual bool DataEquals(HValue* other) const {
|
| HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
|
| - return holder_.is_identical_to(b->holder()) &&
|
| - receiver_map_.is_identical_to(b->receiver_map());
|
| + return prototype_.is_identical_to(b->prototype()) &&
|
| + holder_.is_identical_to(b->holder());
|
| }
|
|
|
| private:
|
| + Handle<JSObject> prototype_;
|
| Handle<JSObject> holder_;
|
| - Handle<Map> receiver_map_;
|
| };
|
|
|
|
|
| @@ -1666,16 +1728,21 @@
|
| SetFlag(kUseGVN);
|
| }
|
|
|
| + virtual bool IsCheckInstruction() const { return true; }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
| virtual HType CalculateInferredType() const;
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const;
|
| + virtual void Verify();
|
| #endif
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -1719,7 +1786,7 @@
|
| HValue* GetRedundantReplacement() const;
|
| void AddInput(HValue* value);
|
|
|
| - bool HasReceiverOperand();
|
| + bool IsReceiver() { return merged_index_ == 0; }
|
|
|
| int merged_index() const { return merged_index_; }
|
|
|
| @@ -1728,7 +1795,7 @@
|
| virtual void PrintTo(StringStream* stream) const;
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const;
|
| + virtual void Verify();
|
| #endif
|
|
|
| DECLARE_INSTRUCTION(Phi)
|
| @@ -1816,7 +1883,7 @@
|
| }
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const { }
|
| + virtual void Verify() { }
|
| #endif
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
|
| @@ -1878,7 +1945,6 @@
|
| operands_[index] = value;
|
| }
|
|
|
| - private:
|
| HOperandVector<2> operands_;
|
| };
|
|
|
| @@ -1894,6 +1960,7 @@
|
| SetOperandAt(1, receiver);
|
| SetOperandAt(2, length);
|
| SetOperandAt(3, elements);
|
| + SetAllSideEffects();
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| @@ -1913,8 +1980,6 @@
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
|
|
|
| -
|
| -
|
| protected:
|
| virtual void InternalSetOperandAt(int index, HValue* value) {
|
| operands_[index] = value;
|
| @@ -1935,6 +2000,9 @@
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -1946,6 +2014,9 @@
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -1982,6 +2053,8 @@
|
| operands_[index] = value;
|
| }
|
|
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +
|
| private:
|
| HOperandVector<3> operands_;
|
| };
|
| @@ -1994,18 +2067,23 @@
|
| SetFlag(kUseGVN);
|
| }
|
|
|
| + virtual bool IsCheckInstruction() const { return true; }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Integer32();
|
| }
|
|
|
| #ifdef DEBUG
|
| - virtual void Verify() const;
|
| + virtual void Verify();
|
| #endif
|
|
|
| HValue* index() const { return left(); }
|
| HValue* length() const { return right(); }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -2013,16 +2091,26 @@
|
| public:
|
| HBitwiseBinaryOperation(HValue* left, HValue* right)
|
| : HBinaryOperation(left, right) {
|
| - // Default to truncating, Integer32, UseGVN.
|
| - set_representation(Representation::Integer32());
|
| - SetFlag(kTruncatingToInt32);
|
| - SetFlag(kUseGVN);
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kFlexibleRepresentation);
|
| + SetAllSideEffects();
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| - return Representation::Integer32();
|
| + return representation();
|
| }
|
|
|
| + virtual void RepresentationChanged(Representation to) {
|
| + if (!to.IsTagged()) {
|
| + ASSERT(to.IsInteger32());
|
| + ClearAllSideEffects();
|
| + SetFlag(kTruncatingToInt32);
|
| + SetFlag(kUseGVN);
|
| + }
|
| + }
|
| +
|
| + HType CalculateInferredType() const;
|
| +
|
| DECLARE_INSTRUCTION(BitwiseBinaryOperation)
|
| };
|
|
|
| @@ -2033,12 +2121,12 @@
|
| : HBinaryOperation(left, right) {
|
| set_representation(Representation::Tagged());
|
| SetFlag(kFlexibleRepresentation);
|
| - SetFlagMask(AllSideEffects());
|
| + SetAllSideEffects();
|
| }
|
|
|
| virtual void RepresentationChanged(Representation to) {
|
| if (!to.IsTagged()) {
|
| - ClearFlagMask(AllSideEffects());
|
| + ClearAllSideEffects();
|
| SetFlag(kUseGVN);
|
| }
|
| }
|
| @@ -2064,11 +2152,15 @@
|
| : HBinaryOperation(left, right), token_(token) {
|
| ASSERT(Token::IsCompareOp(token));
|
| set_representation(Representation::Tagged());
|
| - SetFlagMask(AllSideEffects());
|
| + SetAllSideEffects();
|
| }
|
|
|
| void SetInputRepresentation(Representation r);
|
| - virtual bool EmitAtUses() const { return uses()->length() <= 1; }
|
| +
|
| + virtual bool EmitAtUses() const {
|
| + return !HasSideEffects() && (uses()->length() <= 1);
|
| + }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return input_representation_;
|
| }
|
| @@ -2106,13 +2198,19 @@
|
| SetFlag(kUseGVN);
|
| }
|
|
|
| - virtual bool EmitAtUses() const { return uses()->length() <= 1; }
|
| + virtual bool EmitAtUses() const {
|
| + return !HasSideEffects() && (uses()->length() <= 1);
|
| + }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
| virtual HType CalculateInferredType() const;
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -2122,7 +2220,11 @@
|
| set_representation(Representation::Tagged());
|
| SetFlag(kUseGVN);
|
| }
|
| - virtual bool EmitAtUses() const { return uses()->length() <= 1; }
|
| +
|
| + virtual bool EmitAtUses() const {
|
| + return !HasSideEffects() && (uses()->length() <= 1);
|
| + }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
| @@ -2155,6 +2257,9 @@
|
| explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -2163,9 +2268,30 @@
|
| explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| +class HIsConstructCall: public HInstruction {
|
| + public:
|
| + HIsConstructCall() {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + virtual bool EmitAtUses() const {
|
| + return !HasSideEffects() && (uses()->length() <= 1);
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is_construct_call")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +};
|
| +
|
| +
|
| class HHasInstanceType: public HUnaryPredicate {
|
| public:
|
| HHasInstanceType(HValue* value, InstanceType type)
|
| @@ -2199,6 +2325,9 @@
|
| explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -2245,23 +2374,67 @@
|
| };
|
|
|
|
|
| -class HInstanceOf: public HBinaryOperation {
|
| +class HInstanceOf: public HInstruction {
|
| public:
|
| - HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
|
| + HInstanceOf(HValue* context, HValue* left, HValue* right) {
|
| + SetOperandAt(0, context);
|
| + SetOperandAt(1, left);
|
| + SetOperandAt(2, right);
|
| set_representation(Representation::Tagged());
|
| - SetFlagMask(AllSideEffects());
|
| + SetAllSideEffects();
|
| }
|
|
|
| - virtual bool EmitAtUses() const { return uses()->length() <= 1; }
|
| + HValue* context() const { return operands_[0]; }
|
| + HValue* left() const { return operands_[1]; }
|
| + HValue* right() const { return operands_[2]; }
|
|
|
| + virtual bool EmitAtUses() const {
|
| + return !HasSideEffects() && (uses()->length() <= 1);
|
| + }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| }
|
|
|
| + virtual void PrintDataTo(StringStream* stream) const;
|
| +
|
| + virtual int OperandCount() const { return 3; }
|
| + virtual HValue* OperandAt(int index) const { return operands_[index]; }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
|
| +
|
| + protected:
|
| + virtual void InternalSetOperandAt(int index, HValue* value) {
|
| + operands_[index] = value;
|
| + }
|
| +
|
| + private:
|
| + HOperandVector<3> operands_;
|
| };
|
|
|
|
|
| +class HInstanceOfKnownGlobal: public HUnaryOperation {
|
| + public:
|
| + HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right)
|
| + : HUnaryOperation(left), function_(right) {
|
| + set_representation(Representation::Tagged());
|
| + SetAllSideEffects();
|
| + }
|
| +
|
| + Handle<JSFunction> function() { return function_; }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return Representation::Tagged();
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
|
| + "instance_of_known_global")
|
| +
|
| + private:
|
| + Handle<JSFunction> function_;
|
| +};
|
| +
|
| +
|
| class HPower: public HBinaryOperation {
|
| public:
|
| HPower(HValue* left, HValue* right)
|
| @@ -2275,6 +2448,9 @@
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(Power, "power")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -2297,6 +2473,8 @@
|
| DECLARE_CONCRETE_INSTRUCTION(Add, "add")
|
|
|
| protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +
|
| virtual Range* InferRange();
|
| };
|
|
|
| @@ -2312,6 +2490,8 @@
|
| DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
|
|
|
| protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +
|
| virtual Range* InferRange();
|
| };
|
|
|
| @@ -2332,6 +2512,8 @@
|
| DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
|
|
|
| protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +
|
| virtual Range* InferRange();
|
| };
|
|
|
| @@ -2347,6 +2529,8 @@
|
| DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
|
|
|
| protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +
|
| virtual Range* InferRange();
|
| };
|
|
|
| @@ -2363,6 +2547,8 @@
|
| DECLARE_CONCRETE_INSTRUCTION(Div, "div")
|
|
|
| protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +
|
| virtual Range* InferRange();
|
| };
|
|
|
| @@ -2378,6 +2564,8 @@
|
| DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
|
|
|
| protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +
|
| virtual Range* InferRange();
|
| };
|
|
|
| @@ -2391,6 +2579,9 @@
|
| virtual HType CalculateInferredType() const;
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -2405,6 +2596,8 @@
|
| DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
|
|
|
| protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +
|
| virtual Range* InferRange();
|
| };
|
|
|
| @@ -2418,6 +2611,9 @@
|
| virtual HType CalculateInferredType() const;
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -2429,6 +2625,9 @@
|
| virtual HType CalculateInferredType() const;
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -2441,6 +2640,9 @@
|
| virtual HType CalculateInferredType() const;
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| @@ -2476,32 +2678,31 @@
|
| };
|
|
|
|
|
| -class HCallStub: public HInstruction {
|
| +class HCallStub: public HUnaryCall {
|
| public:
|
| - HCallStub(CodeStub::Major major_key, int argument_count)
|
| - : major_key_(major_key),
|
| - argument_count_(argument_count),
|
| + HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
|
| + : HUnaryCall(context, argument_count),
|
| + major_key_(major_key),
|
| transcendental_type_(TranscendentalCache::kNumberOfCaches) {
|
| - set_representation(Representation::Tagged());
|
| - SetFlagMask(AllSideEffects());
|
| }
|
|
|
| CodeStub::Major major_key() { return major_key_; }
|
| - int argument_count() { return argument_count_; }
|
|
|
| + HValue* context() const { return value(); }
|
| +
|
| void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
|
| transcendental_type_ = transcendental_type;
|
| }
|
| TranscendentalCache::Type transcendental_type() {
|
| return transcendental_type_;
|
| }
|
| +
|
| virtual void PrintDataTo(StringStream* stream) const;
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
|
|
|
| private:
|
| CodeStub::Major major_key_;
|
| - int argument_count_;
|
| TranscendentalCache::Type transcendental_type_;
|
| };
|
|
|
| @@ -2552,12 +2753,17 @@
|
|
|
| class HStoreGlobal: public HUnaryOperation {
|
| public:
|
| - HStoreGlobal(HValue* value, Handle<JSGlobalPropertyCell> cell)
|
| - : HUnaryOperation(value), cell_(cell) {
|
| + HStoreGlobal(HValue* value,
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + bool check_hole_value)
|
| + : HUnaryOperation(value),
|
| + cell_(cell),
|
| + check_hole_value_(check_hole_value) {
|
| SetFlag(kChangesGlobalVars);
|
| }
|
|
|
| Handle<JSGlobalPropertyCell> cell() const { return cell_; }
|
| + bool check_hole_value() const { return check_hole_value_; }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| return Representation::Tagged();
|
| @@ -2566,17 +2772,76 @@
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
|
|
|
| + private:
|
| + Handle<JSGlobalPropertyCell> cell_;
|
| + bool check_hole_value_;
|
| +};
|
| +
|
| +
|
| +class HLoadContextSlot: public HUnaryOperation {
|
| + public:
|
| + HLoadContextSlot(HValue* context , int slot_index)
|
| + : HUnaryOperation(context), slot_index_(slot_index) {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + SetFlag(kDependsOnContextSlots);
|
| + }
|
| +
|
| + int slot_index() const { return slot_index_; }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return Representation::Tagged();
|
| + }
|
| +
|
| + virtual void PrintDataTo(StringStream* stream) const;
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
|
| +
|
| protected:
|
| virtual bool DataEquals(HValue* other) const {
|
| - HStoreGlobal* b = HStoreGlobal::cast(other);
|
| - return cell_.is_identical_to(b->cell());
|
| + HLoadContextSlot* b = HLoadContextSlot::cast(other);
|
| + return (slot_index() == b->slot_index());
|
| }
|
|
|
| private:
|
| - Handle<JSGlobalPropertyCell> cell_;
|
| + int slot_index_;
|
| };
|
|
|
|
|
| +static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
|
| + return !value->type().IsSmi() &&
|
| + !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
|
| +}
|
| +
|
| +
|
| +class HStoreContextSlot: public HBinaryOperation {
|
| + public:
|
| + HStoreContextSlot(HValue* context, int slot_index, HValue* value)
|
| + : HBinaryOperation(context, value), slot_index_(slot_index) {
|
| + SetFlag(kChangesContextSlots);
|
| + }
|
| +
|
| + HValue* context() const { return OperandAt(0); }
|
| + HValue* value() const { return OperandAt(1); }
|
| + int slot_index() const { return slot_index_; }
|
| +
|
| + bool NeedsWriteBarrier() const {
|
| + return StoringValueNeedsWriteBarrier(value());
|
| + }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return Representation::Tagged();
|
| + }
|
| +
|
| + virtual void PrintDataTo(StringStream* stream) const;
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store_context_slot")
|
| +
|
| + private:
|
| + int slot_index_;
|
| +};
|
| +
|
| +
|
| class HLoadNamedField: public HUnaryOperation {
|
| public:
|
| HLoadNamedField(HValue* object, bool is_in_object, int offset)
|
| @@ -2615,15 +2880,16 @@
|
| };
|
|
|
|
|
| -class HLoadNamedGeneric: public HUnaryOperation {
|
| +class HLoadNamedGeneric: public HBinaryOperation {
|
| public:
|
| - HLoadNamedGeneric(HValue* object, Handle<Object> name)
|
| - : HUnaryOperation(object), name_(name) {
|
| + HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
|
| + : HBinaryOperation(context, object), name_(name) {
|
| set_representation(Representation::Tagged());
|
| - SetFlagMask(AllSideEffects());
|
| + SetAllSideEffects();
|
| }
|
|
|
| - HValue* object() const { return OperandAt(0); }
|
| + HValue* context() const { return OperandAt(0); }
|
| + HValue* object() const { return OperandAt(1); }
|
| Handle<Object> name() const { return name_; }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| @@ -2632,12 +2898,6 @@
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
|
|
|
| - protected:
|
| - virtual bool DataEquals(HValue* other) const {
|
| - HLoadNamedGeneric* b = HLoadNamedGeneric::cast(other);
|
| - return name_.is_identical_to(b->name_);
|
| - }
|
| -
|
| private:
|
| Handle<Object> name_;
|
| };
|
| @@ -2648,7 +2908,8 @@
|
| explicit HLoadFunctionPrototype(HValue* function)
|
| : HUnaryOperation(function) {
|
| set_representation(Representation::Tagged());
|
| - SetFlagMask(kDependsOnFunctionPrototypes);
|
| + SetFlag(kUseGVN);
|
| + SetFlag(kDependsOnCalls);
|
| }
|
|
|
| HValue* function() const { return OperandAt(0); }
|
| @@ -2697,28 +2958,73 @@
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
|
| "load_keyed_fast_element")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| };
|
|
|
|
|
| +class HLoadPixelArrayElement: public HBinaryOperation {
|
| + public:
|
| + HLoadPixelArrayElement(HValue* external_elements, HValue* key)
|
| + : HBinaryOperation(external_elements, key) {
|
| + set_representation(Representation::Integer32());
|
| + SetFlag(kDependsOnPixelArrayElements);
|
| + // Native code could change the pixel array.
|
| + SetFlag(kDependsOnCalls);
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + virtual void PrintDataTo(StringStream* stream) const;
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + // The key is supposed to be Integer32, but the base pointer
|
| + // for the element load is a naked pointer.
|
| + return (index == 1) ? Representation::Integer32()
|
| + : Representation::External();
|
| + }
|
| +
|
| + HValue* external_pointer() const { return OperandAt(0); }
|
| + HValue* key() const { return OperandAt(1); }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(LoadPixelArrayElement,
|
| + "load_pixel_array_element")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +};
|
| +
|
| +
|
| class HLoadKeyedGeneric: public HLoadKeyed {
|
| public:
|
| - HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
|
| - SetFlagMask(AllSideEffects());
|
| + HLoadKeyedGeneric(HContext* context, HValue* obj, HValue* key)
|
| + : HLoadKeyed(obj, key), context_(NULL) {
|
| + SetOperandAt(2, context);
|
| + SetAllSideEffects();
|
| }
|
|
|
| + HValue* context() const { return context_; }
|
| + HValue* object() const { return operands_[0]; }
|
| + HValue* key() const { return operands_[1]; }
|
| +
|
| + virtual int OperandCount() const { return 3; }
|
| + virtual HValue* OperandAt(int index) const {
|
| + return (index < 2) ? operands_[index] : context_;
|
| + }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
|
| -};
|
|
|
| + protected:
|
| + virtual void InternalSetOperandAt(int index, HValue* value);
|
|
|
| -static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
|
| - return !value->type().IsSmi() &&
|
| - !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
|
| -}
|
| + private:
|
| + HValue* context_;
|
| +};
|
|
|
|
|
| class HStoreNamed: public HBinaryOperation {
|
| public:
|
| - HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
|
| + HStoreNamed(HValue* obj, Handle<String> name, HValue* val)
|
| : HBinaryOperation(obj, val), name_(name) {
|
| }
|
|
|
| @@ -2729,31 +3035,21 @@
|
| virtual void PrintDataTo(StringStream* stream) const;
|
|
|
| HValue* object() const { return OperandAt(0); }
|
| - Handle<Object> name() const { return name_; }
|
| + Handle<String> name() const { return name_; }
|
| HValue* value() const { return OperandAt(1); }
|
| void set_value(HValue* value) { SetOperandAt(1, value); }
|
|
|
| - bool NeedsWriteBarrier() const {
|
| - return StoringValueNeedsWriteBarrier(value());
|
| - }
|
| -
|
| DECLARE_INSTRUCTION(StoreNamed)
|
|
|
| - protected:
|
| - virtual bool DataEquals(HValue* other) const {
|
| - HStoreNamed* b = HStoreNamed::cast(other);
|
| - return name_.is_identical_to(b->name_);
|
| - }
|
| -
|
| private:
|
| - Handle<Object> name_;
|
| + Handle<String> name_;
|
| };
|
|
|
|
|
| class HStoreNamedField: public HStoreNamed {
|
| public:
|
| HStoreNamedField(HValue* obj,
|
| - Handle<Object> name,
|
| + Handle<String> name,
|
| HValue* val,
|
| bool in_object,
|
| int offset)
|
| @@ -2770,7 +3066,7 @@
|
| DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
|
|
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
| - return Representation::Tagged();
|
| + return Representation::Tagged();
|
| }
|
| virtual void PrintDataTo(StringStream* stream) const;
|
|
|
| @@ -2779,6 +3075,10 @@
|
| Handle<Map> transition() const { return transition_; }
|
| void set_transition(Handle<Map> map) { transition_ = map; }
|
|
|
| + bool NeedsWriteBarrier() const {
|
| + return StoringValueNeedsWriteBarrier(value());
|
| + }
|
| +
|
| private:
|
| bool is_in_object_;
|
| int offset_;
|
| @@ -2788,12 +3088,32 @@
|
|
|
| class HStoreNamedGeneric: public HStoreNamed {
|
| public:
|
| - HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
|
| - : HStoreNamed(obj, name, val) {
|
| - SetFlagMask(AllSideEffects());
|
| + HStoreNamedGeneric(HValue* context,
|
| + HValue* object,
|
| + Handle<String> name,
|
| + HValue* value)
|
| + : HStoreNamed(object, name, value), context_(NULL) {
|
| + SetOperandAt(2, context);
|
| + SetAllSideEffects();
|
| }
|
|
|
| + HValue* context() const { return context_; }
|
| + HValue* object() const { return operands_[0]; }
|
| + HValue* value() const { return operands_[1]; }
|
| +
|
| + virtual int OperandCount() const { return 3; }
|
| +
|
| + virtual HValue* OperandAt(int index) const {
|
| + return (index < 2) ? operands_[index] : context_;
|
| + }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
|
| +
|
| + protected:
|
| + virtual void InternalSetOperandAt(int index, HValue* value);
|
| +
|
| + private:
|
| + HValue* context_;
|
| };
|
|
|
|
|
| @@ -2828,7 +3148,6 @@
|
| operands_[index] = value;
|
| }
|
|
|
| - private:
|
| HOperandVector<3> operands_;
|
| };
|
|
|
| @@ -2853,15 +3172,91 @@
|
|
|
| class HStoreKeyedGeneric: public HStoreKeyed {
|
| public:
|
| - HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
|
| - : HStoreKeyed(obj, key, val) {
|
| - SetFlagMask(AllSideEffects());
|
| + HStoreKeyedGeneric(HValue* context,
|
| + HValue* object,
|
| + HValue* key,
|
| + HValue* value)
|
| + : HStoreKeyed(object, key, value), context_(NULL) {
|
| + SetOperandAt(3, context);
|
| + SetAllSideEffects();
|
| }
|
|
|
| + HValue* context() const { return context_; }
|
| + HValue* object() const { return operands_[0]; }
|
| + HValue* key() const { return operands_[1]; }
|
| + HValue* value() const { return operands_[2]; }
|
| +
|
| + virtual int OperandCount() const { return 4; }
|
| +
|
| + virtual HValue* OperandAt(int index) const {
|
| + return (index < 3) ? operands_[index] : context_;
|
| + }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
|
| +
|
| + protected:
|
| + virtual void InternalSetOperandAt(int index, HValue* value);
|
| +
|
| + private:
|
| + HValue* context_;
|
| };
|
|
|
|
|
| +class HStringCharCodeAt: public HBinaryOperation {
|
| + public:
|
| + HStringCharCodeAt(HValue* string, HValue* index)
|
| + : HBinaryOperation(string, index) {
|
| + set_representation(Representation::Integer32());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + // The index is supposed to be Integer32.
|
| + return (index == 1) ? Representation::Integer32()
|
| + : Representation::Tagged();
|
| + }
|
| +
|
| + HValue* string() const { return OperandAt(0); }
|
| + HValue* index() const { return OperandAt(1); }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string_char_code_at")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +
|
| + virtual Range* InferRange() {
|
| + return new Range(0, String::kMaxUC16CharCode);
|
| + }
|
| +};
|
| +
|
| +
|
| +class HStringLength: public HUnaryOperation {
|
| + public:
|
| + explicit HStringLength(HValue* string) : HUnaryOperation(string) {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return Representation::Tagged();
|
| + }
|
| +
|
| + virtual HType CalculateInferredType() const {
|
| + STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
|
| + return HType::Smi();
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(StringLength, "string_length")
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) const { return true; }
|
| +
|
| + virtual Range* InferRange() {
|
| + return new Range(0, String::kMaxLength);
|
| + }
|
| +};
|
| +
|
| +
|
| class HMaterializedLiteral: public HInstruction {
|
| public:
|
| HMaterializedLiteral(int index, int depth)
|
| @@ -2905,22 +3300,36 @@
|
|
|
| class HObjectLiteral: public HMaterializedLiteral {
|
| public:
|
| - HObjectLiteral(Handle<FixedArray> constant_properties,
|
| + HObjectLiteral(HValue* context,
|
| + Handle<FixedArray> constant_properties,
|
| bool fast_elements,
|
| int literal_index,
|
| int depth)
|
| : HMaterializedLiteral(literal_index, depth),
|
| + context_(NULL),
|
| constant_properties_(constant_properties),
|
| - fast_elements_(fast_elements) {}
|
| + fast_elements_(fast_elements) {
|
| + SetOperandAt(0, context);
|
| + }
|
|
|
| + HValue* context() const { return context_; }
|
| Handle<FixedArray> constant_properties() const {
|
| return constant_properties_;
|
| }
|
| bool fast_elements() const { return fast_elements_; }
|
|
|
| + virtual int OperandCount() const { return 1; }
|
| + virtual HValue* OperandAt(int index) const { return context_; }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
|
|
|
| + protected:
|
| + virtual void InternalSetOperandAt(int index, HValue* value) {
|
| + context_ = value;
|
| + }
|
| +
|
| private:
|
| + HValue* context_;
|
| Handle<FixedArray> constant_properties_;
|
| bool fast_elements_;
|
| };
|
| @@ -2970,6 +3379,10 @@
|
| set_representation(Representation::Tagged());
|
| }
|
|
|
| + virtual Representation RequiredInputRepresentation(int index) const {
|
| + return Representation::Tagged();
|
| + }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
|
| };
|
|
|
| @@ -2989,7 +3402,7 @@
|
| HDeleteProperty(HValue* obj, HValue* key)
|
| : HBinaryOperation(obj, key) {
|
| set_representation(Representation::Tagged());
|
| - SetFlagMask(AllSideEffects());
|
| + SetAllSideEffects();
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) const {
|
|
|