Chromium Code Reviews| Index: src/hydrogen-instructions.h |
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
| index 9d262fc811724c985c6ddc96697c218e6daab976..30b498e37f47aac11293b63b496bd17a1b58148b 100644 |
| --- a/src/hydrogen-instructions.h |
| +++ b/src/hydrogen-instructions.h |
| @@ -2083,28 +2083,21 @@ class HCheckMaps: public HTemplateInstruction<2> { |
| HCheckMaps* check_map = new HCheckMaps(object, map); |
| SmallMapList* map_set = check_map->map_set(); |
| - // If the map to check has the untransitioned elements, it can be hoisted |
| - // above TransitionElements instructions. |
| - if (map->has_fast_smi_only_elements()) { |
| - check_map->ClearGVNFlag(kDependsOnElementsKind); |
| - } |
| - |
| - Map* transitioned_fast_element_map = |
| - map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL); |
| - ASSERT(transitioned_fast_element_map == NULL || |
| - map->elements_kind() != FAST_ELEMENTS); |
| - if (transitioned_fast_element_map != NULL) { |
| - map_set->Add(Handle<Map>(transitioned_fast_element_map)); |
| - } |
| - Map* transitioned_double_map = |
| - map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL); |
| - ASSERT(transitioned_double_map == NULL || |
| - map->elements_kind() == FAST_SMI_ONLY_ELEMENTS); |
| - if (transitioned_double_map != NULL) { |
| - map_set->Add(Handle<Map>(transitioned_double_map)); |
| - } |
| + // Since transitioned elements maps of the initial map don't fail the map |
| + // check, the CheckMaps instruction doesn't need to depend on ElementsKinds. |
| + check_map->ClearGVNFlag(kDependsOnElementsKind); |
| + |
| + ElementsKind kind = map->elements_kind(); |
| + bool packed = IsFastPackedElementsKind(kind); |
| + while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) { |
| + kind = GetNextMoreGeneralFastElementsKind(kind, packed); |
| + Map* transitioned_map = |
| + map->LookupElementsTransitionMap(kind, NULL); |
| + if (transitioned_map) { |
| + map_set->Add(Handle<Map>(transitioned_map)); |
| + } |
| + }; |
| map_set->Sort(); |
| - |
| return check_map; |
| } |
| @@ -3947,10 +3940,11 @@ class HLoadFunctionPrototype: public HUnaryOperation { |
| }; |
| +enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK }; |
| + |
| + |
| class HLoadKeyedFastElement: public HTemplateInstruction<2> { |
| public: |
| - enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK }; |
| - |
| HLoadKeyedFastElement(HValue* obj, |
| HValue* key, |
| HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK) |
| @@ -3992,7 +3986,11 @@ class HLoadKeyedFastElement: public HTemplateInstruction<2> { |
| class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> { |
| public: |
| - HLoadKeyedFastDoubleElement(HValue* elements, HValue* key) { |
| + HLoadKeyedFastDoubleElement( |
| + HValue* elements, |
| + HValue* key, |
| + HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK) |
| + : hole_check_mode_(hole_check_mode) { |
| SetOperandAt(0, elements); |
| SetOperandAt(1, key); |
| set_representation(Representation::Double()); |
| @@ -4010,12 +4008,24 @@ class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> { |
| : Representation::Integer32(); |
| } |
| + bool RequiresHoleCheck() { |
| + return hole_check_mode_ == PERFORM_HOLE_CHECK; |
| + } |
| + |
| virtual void PrintDataTo(StringStream* stream); |
| DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement) |
| protected: |
| - virtual bool DataEquals(HValue* other) { return true; } |
| + virtual bool DataEquals(HValue* other) { |
| + if (!other->IsLoadKeyedFastDoubleElement()) return false; |
| + HLoadKeyedFastDoubleElement* other_load = |
| + HLoadKeyedFastDoubleElement::cast(other); |
| + return hole_check_mode_ == other_load->hole_check_mode_; |
| + } |
| + |
| + private: |
| + HoleCheckMode hole_check_mode_; |
| }; |
| @@ -4210,7 +4220,7 @@ class HStoreKeyedFastElement: public HTemplateInstruction<3> { |
| HValue* key() { return OperandAt(1); } |
| HValue* value() { return OperandAt(2); } |
| bool value_is_smi() { |
| - return elements_kind_ == FAST_SMI_ONLY_ELEMENTS; |
| + return IsFastSmiElementsKind(elements_kind_); |
| } |
| bool NeedsWriteBarrier() { |
| @@ -4352,9 +4362,19 @@ class HTransitionElementsKind: public HTemplateInstruction<1> { |
| transitioned_map_(transitioned_map) { |
| SetOperandAt(0, object); |
| SetFlag(kUseGVN); |
| + // Don't set GVN DependOn flags here. That would defeat GVN's detection of |
| + // congruent HTransitionElementsKind instructions. Instruction hoisting |
| + // handles HTransitionElementsKind instruction specially, explicitly adding |
| + // DependsOn flags during its dependency calculations. |
| SetGVNFlag(kChangesElementsKind); |
| - SetGVNFlag(kChangesElementsPointer); |
| - SetGVNFlag(kChangesNewSpacePromotion); |
| + if (original_map->has_fast_double_elements()) { |
|
Jakob Kummerow
2012/05/13 21:55:27
The bodies of these two if-blocks are the same; I'
danno
2012/05/22 11:05:21
Done.
|
| + SetGVNFlag(kChangesElementsPointer); |
| + SetGVNFlag(kChangesNewSpacePromotion); |
| + } |
| + if (transitioned_map->has_fast_double_elements()) { |
| + SetGVNFlag(kChangesElementsPointer); |
| + SetGVNFlag(kChangesNewSpacePromotion); |
| + } |
| set_representation(Representation::Tagged()); |
| } |
| @@ -4592,7 +4612,7 @@ class HArrayLiteral: public HMaterializedLiteral<1> { |
| HValue* context() { return OperandAt(0); } |
| ElementsKind boilerplate_elements_kind() const { |
| if (!boilerplate_object_->IsJSObject()) { |
| - return FAST_ELEMENTS; |
| + return TERMINAL_FAST_ELEMENTS_KIND; |
| } |
| return Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind(); |
| } |