| Index: src/hydrogen-instructions.h
|
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
|
| index e71b7cdf41a1b483e22320eecddd5a569fe0a541..40bbc902458cd70ae79d79cb73f9f3cb85447e98 100644
|
| --- a/src/hydrogen-instructions.h
|
| +++ b/src/hydrogen-instructions.h
|
| @@ -211,7 +211,7 @@ class LChunkBuilder;
|
| V(GlobalVars) \
|
| V(InobjectFields) \
|
| V(OsrEntries) \
|
| - V(ExternalMemory)
|
| + V(SpecializedArrayElements)
|
|
|
|
|
| #define DECLARE_ABSTRACT_INSTRUCTION(type) \
|
| @@ -350,7 +350,8 @@ class UniqueValueId {
|
|
|
| class HType {
|
| public:
|
| - static HType None() { return HType(kNone); }
|
| + HType() : type_(kUninitialized) { }
|
| +
|
| static HType Tagged() { return HType(kTagged); }
|
| static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
|
| static HType TaggedNumber() { return HType(kTaggedNumber); }
|
| @@ -361,6 +362,7 @@ class HType {
|
| static HType NonPrimitive() { return HType(kNonPrimitive); }
|
| static HType JSArray() { return HType(kJSArray); }
|
| static HType JSObject() { return HType(kJSObject); }
|
| + static HType Uninitialized() { return HType(kUninitialized); }
|
|
|
| // Return the weakest (least precise) common type.
|
| HType Combine(HType other) {
|
| @@ -376,26 +378,32 @@ class HType {
|
| }
|
|
|
| bool IsTagged() const {
|
| + ASSERT(type_ != kUninitialized);
|
| return ((type_ & kTagged) == kTagged);
|
| }
|
|
|
| bool IsTaggedPrimitive() const {
|
| + ASSERT(type_ != kUninitialized);
|
| return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
|
| }
|
|
|
| bool IsTaggedNumber() const {
|
| + ASSERT(type_ != kUninitialized);
|
| return ((type_ & kTaggedNumber) == kTaggedNumber);
|
| }
|
|
|
| bool IsSmi() const {
|
| + ASSERT(type_ != kUninitialized);
|
| return ((type_ & kSmi) == kSmi);
|
| }
|
|
|
| bool IsHeapNumber() const {
|
| + ASSERT(type_ != kUninitialized);
|
| return ((type_ & kHeapNumber) == kHeapNumber);
|
| }
|
|
|
| bool IsString() const {
|
| + ASSERT(type_ != kUninitialized);
|
| return ((type_ & kString) == kString);
|
| }
|
|
|
| @@ -405,41 +413,32 @@ class HType {
|
| }
|
|
|
| bool IsBoolean() const {
|
| + ASSERT(type_ != kUninitialized);
|
| return ((type_ & kBoolean) == kBoolean);
|
| }
|
|
|
| bool IsNonPrimitive() const {
|
| + ASSERT(type_ != kUninitialized);
|
| return ((type_ & kNonPrimitive) == kNonPrimitive);
|
| }
|
|
|
| bool IsJSArray() const {
|
| + ASSERT(type_ != kUninitialized);
|
| return ((type_ & kJSArray) == kJSArray);
|
| }
|
|
|
| bool IsJSObject() const {
|
| + ASSERT(type_ != kUninitialized);
|
| return ((type_ & kJSObject) == kJSObject);
|
| }
|
|
|
| - bool IsHeapObject() const {
|
| - return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive();
|
| + bool IsUninitialized() const {
|
| + return type_ == kUninitialized;
|
| }
|
|
|
| - bool ToStringOrToNumberCanBeObserved(Representation representation) {
|
| - switch (type_) {
|
| - case kTaggedPrimitive: // fallthru
|
| - case kTaggedNumber: // fallthru
|
| - case kSmi: // fallthru
|
| - case kHeapNumber: // fallthru
|
| - case kString: // fallthru
|
| - case kBoolean:
|
| - return false;
|
| - case kJSArray: // fallthru
|
| - case kJSObject:
|
| - return true;
|
| - case kTagged:
|
| - break;
|
| - }
|
| - return !representation.IsSmiOrInteger32() && !representation.IsDouble();
|
| + bool IsHeapObject() const {
|
| + ASSERT(type_ != kUninitialized);
|
| + return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive();
|
| }
|
|
|
| static HType TypeFromValue(Handle<Object> value);
|
| @@ -448,7 +447,6 @@ class HType {
|
|
|
| private:
|
| enum Type {
|
| - kNone = 0x0, // 0000 0000 0000 0000
|
| kTagged = 0x1, // 0000 0000 0000 0001
|
| kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
|
| kTaggedNumber = 0xd, // 0000 0000 0000 1101
|
| @@ -458,11 +456,12 @@ class HType {
|
| kBoolean = 0x85, // 0000 0000 1000 0101
|
| kNonPrimitive = 0x101, // 0000 0001 0000 0001
|
| kJSObject = 0x301, // 0000 0011 0000 0001
|
| - kJSArray = 0x701 // 0000 0111 0000 0001
|
| + kJSArray = 0x701, // 0000 0111 0000 0001
|
| + kUninitialized = 0x1fff // 0001 1111 1111 1111
|
| };
|
|
|
| // Make sure type fits in int16.
|
| - STATIC_ASSERT(kJSArray < (1 << (2 * kBitsPerByte)));
|
| + STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
|
|
|
| explicit HType(Type t) : type_(t) { }
|
|
|
| @@ -1146,18 +1145,6 @@ class HValue: public ZoneObject {
|
| }
|
| }
|
|
|
| - // Returns true conservatively if the program might be able to observe a
|
| - // ToString() operation on this value.
|
| - bool ToStringCanBeObserved() const {
|
| - return type().ToStringOrToNumberCanBeObserved(representation());
|
| - }
|
| -
|
| - // Returns true conservatively if the program might be able to observe a
|
| - // ToNumber() operation on this value.
|
| - bool ToNumberCanBeObserved() const {
|
| - return type().ToStringOrToNumberCanBeObserved(representation());
|
| - }
|
| -
|
| protected:
|
| void TryGuaranteeRangeRecursive(RangeEvaluationContext* context);
|
|
|
| @@ -2695,10 +2682,6 @@ class HLoadExternalArrayPointer: public HUnaryOperation {
|
| return Representation::Tagged();
|
| }
|
|
|
| - virtual HType CalculateInferredType() {
|
| - return HType::None();
|
| - }
|
| -
|
| DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
|
|
|
| protected:
|
| @@ -2954,7 +2937,11 @@ class HCheckHeapObject: public HUnaryOperation {
|
| #endif
|
|
|
| virtual HValue* Canonicalize() {
|
| - return value()->type().IsHeapObject() ? NULL : this;
|
| + HType value_type = value()->type();
|
| + if (!value_type.IsUninitialized() && value_type.IsHeapObject()) {
|
| + return NULL;
|
| + }
|
| + return this;
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
|
| @@ -3356,6 +3343,9 @@ class HPhi: public HValue {
|
|
|
| void SimplifyConstantInputs();
|
|
|
| + // TODO(titzer): we can't eliminate the receiver for generating backtraces
|
| + virtual bool IsDeletable() const { return !IsReceiver(); }
|
| +
|
| protected:
|
| virtual void DeleteFromGraph();
|
| virtual void InternalSetOperandAt(int index, HValue* value) {
|
| @@ -3375,9 +3365,6 @@ class HPhi: public HValue {
|
| int indirect_uses_[Representation::kNumRepresentations];
|
| int phi_id_;
|
| InductionVariableData* induction_variable_data_;
|
| -
|
| - // TODO(titzer): we can't eliminate the receiver for generating backtraces
|
| - virtual bool IsDeletable() const { return !IsReceiver(); }
|
| };
|
|
|
|
|
| @@ -3484,7 +3471,6 @@ class HConstant: public HTemplateInstruction<0> {
|
| bool is_not_in_new_space,
|
| bool is_cell,
|
| bool boolean_value);
|
| - explicit HConstant(ExternalReference reference);
|
|
|
| Handle<Object> handle() {
|
| if (handle_.is_null()) {
|
| @@ -3549,12 +3535,12 @@ class HConstant: public HTemplateInstruction<0> {
|
| if (HasSmiValue() && kSmiValueSize == 31) return Representation::Smi();
|
| if (HasInteger32Value()) return Representation::Integer32();
|
| if (HasNumberValue()) return Representation::Double();
|
| - if (HasExternalReferenceValue()) return Representation::External();
|
| return Representation::Tagged();
|
| }
|
|
|
| virtual bool EmitAtUses();
|
| virtual void PrintDataTo(StringStream* stream);
|
| + virtual HType CalculateInferredType();
|
| bool IsInteger() { return handle()->IsSmi(); }
|
| HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
|
| Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
|
| @@ -3591,7 +3577,7 @@ class HConstant: public HTemplateInstruction<0> {
|
| bool HasStringValue() const {
|
| if (has_double_value_ || has_int32_value_) return false;
|
| ASSERT(!handle_.is_null());
|
| - return type_.IsString();
|
| + return type_from_value_.IsString();
|
| }
|
| Handle<String> StringValue() const {
|
| ASSERT(HasStringValue());
|
| @@ -3601,13 +3587,6 @@ class HConstant: public HTemplateInstruction<0> {
|
| return HasStringValue() && is_internalized_string_;
|
| }
|
|
|
| - bool HasExternalReferenceValue() const {
|
| - return has_external_reference_value_;
|
| - }
|
| - ExternalReference ExternalReferenceValue() const {
|
| - return external_reference_value_;
|
| - }
|
| -
|
| bool BooleanValue() const { return boolean_value_; }
|
|
|
| virtual intptr_t Hashcode() {
|
| @@ -3615,8 +3594,6 @@ class HConstant: public HTemplateInstruction<0> {
|
| return static_cast<intptr_t>(int32_value_);
|
| } else if (has_double_value_) {
|
| return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
|
| - } else if (has_external_reference_value_) {
|
| - return reinterpret_cast<intptr_t>(external_reference_value_.address());
|
| } else {
|
| ASSERT(!handle_.is_null());
|
| return unique_id_.Hashcode();
|
| @@ -3624,15 +3601,14 @@ class HConstant: public HTemplateInstruction<0> {
|
| }
|
|
|
| virtual void FinalizeUniqueValueId() {
|
| - if (!has_double_value_ && !has_external_reference_value_) {
|
| + if (!has_double_value_) {
|
| ASSERT(!handle_.is_null());
|
| unique_id_ = UniqueValueId(handle_);
|
| }
|
| }
|
|
|
| bool UniqueValueIdsMatch(UniqueValueId other) {
|
| - return !has_double_value_ && !has_external_reference_value_ &&
|
| - unique_id_ == other;
|
| + return !has_double_value_ && unique_id_ == other;
|
| }
|
|
|
| #ifdef DEBUG
|
| @@ -3653,10 +3629,6 @@ class HConstant: public HTemplateInstruction<0> {
|
| return other_constant->has_double_value_ &&
|
| BitCast<int64_t>(double_value_) ==
|
| BitCast<int64_t>(other_constant->double_value_);
|
| - } else if (has_external_reference_value_) {
|
| - return other_constant->has_external_reference_value_ &&
|
| - external_reference_value_ ==
|
| - other_constant->external_reference_value_;
|
| } else {
|
| ASSERT(!handle_.is_null());
|
| return !other_constant->handle_.is_null() &&
|
| @@ -3684,14 +3656,13 @@ class HConstant: public HTemplateInstruction<0> {
|
| bool has_smi_value_ : 1;
|
| bool has_int32_value_ : 1;
|
| bool has_double_value_ : 1;
|
| - bool has_external_reference_value_ : 1;
|
| bool is_internalized_string_ : 1; // TODO(yangguo): make this part of HType.
|
| bool is_not_in_new_space_ : 1;
|
| bool is_cell_ : 1;
|
| bool boolean_value_ : 1;
|
| int32_t int32_value_;
|
| double double_value_;
|
| - ExternalReference external_reference_value_;
|
| + HType type_from_value_;
|
| };
|
|
|
|
|
| @@ -3707,9 +3678,9 @@ class HBinaryOperation: public HTemplateInstruction<3> {
|
| observed_input_representation_[1] = Representation::None();
|
| }
|
|
|
| - HValue* context() const { return OperandAt(0); }
|
| - HValue* left() const { return OperandAt(1); }
|
| - HValue* right() const { return OperandAt(2); }
|
| + HValue* context() { return OperandAt(0); }
|
| + HValue* left() { return OperandAt(1); }
|
| + HValue* right() { return OperandAt(2); }
|
|
|
| // True if switching left and right operands likely generates better code.
|
| bool AreOperandsBetterSwitched() {
|
| @@ -3963,6 +3934,9 @@ class HBoundsCheck: public HTemplateInstruction<2> {
|
| virtual Representation RequiredInputRepresentation(int arg_index) {
|
| return representation();
|
| }
|
| + virtual bool IsDeletable() const {
|
| + return skip_check() && !FLAG_debug_code;
|
| + }
|
|
|
| virtual bool IsRelationTrueInternal(NumericRelation relation,
|
| HValue* related_value,
|
| @@ -3999,11 +3973,6 @@ class HBoundsCheck: public HTemplateInstruction<2> {
|
| int scale_;
|
| RangeGuaranteeDirection responsibility_direction_;
|
| bool allow_equality_;
|
| -
|
| - private:
|
| - virtual bool IsDeletable() const {
|
| - return skip_check() && !FLAG_debug_code;
|
| - }
|
| };
|
|
|
|
|
| @@ -4823,7 +4792,8 @@ class HMathMinMax: public HArithmeticBinaryOperation {
|
| virtual Representation RepresentationFromInputs() {
|
| Representation left_rep = left()->representation();
|
| Representation right_rep = right()->representation();
|
| - Representation result = Representation::Smi();
|
| + // TODO(verwaest): Initialize to Smi once lithium-codegen has been fixed.
|
| + Representation result = Representation::Integer32();
|
| result = result.generalize(left_rep);
|
| result = result.generalize(right_rep);
|
| if (result.IsTagged()) return Representation::Double();
|
| @@ -4921,11 +4891,7 @@ class HShl: public HBitwiseBinaryOperation {
|
| virtual void UpdateRepresentation(Representation new_rep,
|
| HInferRepresentationPhase* h_infer,
|
| const char* reason) {
|
| - if (new_rep.IsSmi() &&
|
| - !(right()->IsInteger32Constant() &&
|
| - right()->GetInteger32Constant() >= 0)) {
|
| - new_rep = Representation::Integer32();
|
| - }
|
| + if (new_rep.IsSmi()) new_rep = Representation::Integer32();
|
| HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
|
| }
|
|
|
| @@ -5588,11 +5554,7 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
|
| class HObjectAccess {
|
| public:
|
| inline bool IsInobject() const {
|
| - return portion() != kBackingStore && portion() != kExternalMemory;
|
| - }
|
| -
|
| - inline bool IsExternalMemory() const {
|
| - return portion() == kExternalMemory;
|
| + return portion() != kBackingStore;
|
| }
|
|
|
| inline int offset() const {
|
| @@ -5622,11 +5584,9 @@ class HObjectAccess {
|
|
|
| static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
|
| return HObjectAccess(
|
| - kArrayLengths,
|
| - JSArray::kLengthOffset,
|
| - IsFastElementsKind(elements_kind) &&
|
| - FLAG_track_fields
|
| - ? Representation::Smi() : Representation::Tagged());
|
| + kArrayLengths, JSArray::kLengthOffset,
|
| + IsFastElementsKind(elements_kind) && FLAG_track_fields ?
|
| + Representation::Smi() : Representation::Tagged());
|
| }
|
|
|
| static HObjectAccess ForAllocationSiteTransitionInfo() {
|
| @@ -5639,9 +5599,9 @@ class HObjectAccess {
|
|
|
| static HObjectAccess ForFixedArrayLength() {
|
| return HObjectAccess(
|
| - kArrayLengths,
|
| - FixedArray::kLengthOffset,
|
| - FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
|
| + kArrayLengths, FixedArray::kLengthOffset,
|
| + FLAG_track_fields ?
|
| + Representation::Smi() : Representation::Tagged());
|
| }
|
|
|
| static HObjectAccess ForPropertiesPointer() {
|
| @@ -5668,10 +5628,6 @@ class HObjectAccess {
|
| return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
|
| }
|
|
|
| - static HObjectAccess ForCounter() {
|
| - return HObjectAccess(kExternalMemory, 0, Representation::Integer32());
|
| - }
|
| -
|
| // Create an access to an offset in a fixed array header.
|
| static HObjectAccess ForFixedArrayHeader(int offset);
|
|
|
| @@ -5710,8 +5666,7 @@ class HObjectAccess {
|
| kElementsPointer, // elements pointer
|
| kBackingStore, // some field in the backing store
|
| kDouble, // some double field
|
| - kInobject, // some other in-object field
|
| - kExternalMemory // some field in external memory
|
| + kInobject // some other in-object field
|
| };
|
|
|
| HObjectAccess(Portion portion, int offset,
|
| @@ -5789,9 +5744,7 @@ class HLoadNamedField: public HTemplateInstruction<2> {
|
| if (representation.IsSmi()) {
|
| set_type(HType::Smi());
|
| set_representation(representation);
|
| - } else if (representation.IsDouble() ||
|
| - representation.IsExternal() ||
|
| - representation.IsInteger32()) {
|
| + } else if (representation.IsDouble()) {
|
| set_representation(representation);
|
| } else if (FLAG_track_heap_object_fields &&
|
| representation.IsHeapObject()) {
|
| @@ -5817,10 +5770,6 @@ class HLoadNamedField: public HTemplateInstruction<2> {
|
|
|
| virtual bool HasEscapingOperandAt(int index) { return false; }
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| - if (index == 0 && access().IsExternalMemory()) {
|
| - // object must be external in case of external memory access
|
| - return Representation::External();
|
| - }
|
| return Representation::Tagged();
|
| }
|
| virtual void PrintDataTo(StringStream* stream);
|
| @@ -5994,7 +5943,7 @@ class HLoadKeyed
|
| set_representation(Representation::Integer32());
|
| }
|
|
|
| - SetGVNFlag(kDependsOnExternalMemory);
|
| + SetGVNFlag(kDependsOnSpecializedArrayElements);
|
| // Native code could change the specialized array.
|
| SetGVNFlag(kDependsOnCalls);
|
| }
|
| @@ -6151,13 +6100,9 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
|
|
| virtual bool HasEscapingOperandAt(int index) { return index == 1; }
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| - if (index == 0 && access().IsExternalMemory()) {
|
| - // object must be external in case of external memory access
|
| - return Representation::External();
|
| - } else if (index == 1 &&
|
| - (field_representation().IsDouble() ||
|
| - field_representation().IsSmi() ||
|
| - field_representation().IsInteger32())) {
|
| + if (index == 1 && field_representation().IsDouble()) {
|
| + return field_representation();
|
| + } else if (index == 1 && field_representation().IsSmi()) {
|
| return field_representation();
|
| }
|
| return Representation::Tagged();
|
| @@ -6195,7 +6140,6 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
| if (IsSkipWriteBarrier()) return false;
|
| if (field_representation().IsDouble()) return false;
|
| if (field_representation().IsSmi()) return false;
|
| - if (field_representation().IsInteger32()) return false;
|
| return StoringValueNeedsWriteBarrier(value()) &&
|
| ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
|
| }
|
| @@ -6276,7 +6220,7 @@ class HStoreKeyed
|
| SetGVNFlag(kDependsOnNewSpacePromotion);
|
| }
|
| if (is_external()) {
|
| - SetGVNFlag(kChangesExternalMemory);
|
| + SetGVNFlag(kChangesSpecializedArrayElements);
|
| SetFlag(kAllowUndefinedAsNaN);
|
| } else if (IsFastDoubleElementsKind(elements_kind)) {
|
| SetGVNFlag(kChangesDoubleArrayElements);
|
| @@ -6527,9 +6471,8 @@ class HStringAdd: public HBinaryOperation {
|
| SetGVNFlag(kChangesNewSpacePromotion);
|
| }
|
|
|
| - // No side-effects except possible allocation.
|
| - // NOTE: this instruction _does not_ call ToString() on its inputs.
|
| - virtual bool IsDeletable() const { return true; }
|
| + // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
|
| + // virtual bool IsDeletable() const { return true; }
|
|
|
| const StringAddFlags flags_;
|
| };
|
| @@ -6554,9 +6497,9 @@ class HStringCharCodeAt: public HTemplateInstruction<3> {
|
| : Representation::Tagged();
|
| }
|
|
|
| - HValue* context() const { return OperandAt(0); }
|
| - HValue* string() const { return OperandAt(1); }
|
| - HValue* index() const { return OperandAt(2); }
|
| + HValue* context() { return OperandAt(0); }
|
| + HValue* string() { return OperandAt(1); }
|
| + HValue* index() { return OperandAt(2); }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
|
|
|
| @@ -6567,9 +6510,9 @@ class HStringCharCodeAt: public HTemplateInstruction<3> {
|
| return new(zone) Range(0, String::kMaxUtf16CodeUnit);
|
| }
|
|
|
| - private:
|
| - // No side effects: runtime function assumes string + number inputs.
|
| - virtual bool IsDeletable() const { return true; }
|
| + // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
|
| + // private:
|
| + // virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
|
|
| @@ -6584,10 +6527,10 @@ class HStringCharFromCode: public HTemplateInstruction<2> {
|
| ? Representation::Tagged()
|
| : Representation::Integer32();
|
| }
|
| - virtual HType CalculateInferredType() { return HType::String(); }
|
| + virtual HType CalculateInferredType();
|
|
|
| - HValue* context() const { return OperandAt(0); }
|
| - HValue* value() const { return OperandAt(1); }
|
| + HValue* context() { return OperandAt(0); }
|
| + HValue* value() { return OperandAt(1); }
|
|
|
| virtual bool DataEquals(HValue* other) { return true; }
|
|
|
| @@ -6602,9 +6545,8 @@ class HStringCharFromCode: public HTemplateInstruction<2> {
|
| SetGVNFlag(kChangesNewSpacePromotion);
|
| }
|
|
|
| - virtual bool IsDeletable() const {
|
| - return !value()->ToNumberCanBeObserved();
|
| - }
|
| + // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
|
| + // virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
|
|
|
|