| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index fd4cc351af8b07d7fad9c547bfce99f04586b708..95090d5160ca096a9391e6d39d10548a37ea193a 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1219,10 +1219,9 @@ void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
|
|
|
|
|
| HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| - HValue* object,
|
| + HValue* checked_object,
|
| HValue* key,
|
| HValue* val,
|
| - HCheckMaps* checked_object,
|
| bool is_js_array,
|
| ElementsKind elements_kind,
|
| bool is_store,
|
| @@ -1237,14 +1236,12 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| // generated store code.
|
| if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
|
| (elements_kind == FAST_ELEMENTS && is_store)) {
|
| - if (checked_object != NULL) {
|
| - checked_object->ClearGVNFlag(kDependsOnElementsKind);
|
| - }
|
| + checked_object->ClearGVNFlag(kDependsOnElementsKind);
|
| }
|
| - if (checked_object != NULL) object = checked_object;
|
| +
|
| bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
|
| bool fast_elements = IsFastObjectElementsKind(elements_kind);
|
| - HValue* elements = AddLoadElements(object);
|
| + HValue* elements = AddLoadElements(checked_object);
|
| if (is_store && (fast_elements || fast_smi_only_elements) &&
|
| store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
|
| HCheckMaps* check_cow_map = Add<HCheckMaps>(
|
| @@ -1254,7 +1251,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| HInstruction* length = NULL;
|
| if (is_js_array) {
|
| length = Add<HLoadNamedField>(
|
| - object, HObjectAccess::ForArrayLength(elements_kind));
|
| + checked_object, HObjectAccess::ForArrayLength(elements_kind));
|
| } else {
|
| length = AddLoadFixedArrayLength(elements);
|
| }
|
| @@ -1301,8 +1298,9 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
|
|
| if (IsGrowStoreMode(store_mode)) {
|
| NoObservableSideEffectsScope no_effects(this);
|
| - elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
|
| - length, key, is_js_array);
|
| + elements = BuildCheckForCapacityGrow(checked_object, elements,
|
| + elements_kind, length, key,
|
| + is_js_array);
|
| checked_key = key;
|
| } else {
|
| checked_key = Add<HBoundsCheck>(key, length);
|
| @@ -1310,9 +1308,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| if (is_store && (fast_elements || fast_smi_only_elements)) {
|
| if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
|
| NoObservableSideEffectsScope no_effects(this);
|
| -
|
| - elements = BuildCopyElementsOnWrite(object, elements, elements_kind,
|
| - length);
|
| + elements = BuildCopyElementsOnWrite(checked_object, elements,
|
| + elements_kind, length);
|
| } else {
|
| HCheckMaps* check_cow_map = Add<HCheckMaps>(
|
| elements, isolate()->factory()->fixed_array_map(),
|
| @@ -5501,19 +5498,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
|
| }
|
|
|
|
|
| -HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
|
| - HValue* object,
|
| - HValue* key,
|
| - HValue* val,
|
| - HValue* dependency,
|
| - Handle<Map> map,
|
| - bool is_store,
|
| - KeyedAccessStoreMode store_mode) {
|
| - HCheckMaps* mapcheck = Add<HCheckMaps>(object, map, top_info(), dependency);
|
| - if (dependency) {
|
| - mapcheck->ClearGVNFlag(kDependsOnElementsKind);
|
| - }
|
| -
|
| +LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
|
| // Loads from a "stock" fast holey double arrays can elide the hole check.
|
| LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
|
| if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
|
| @@ -5525,10 +5510,30 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
|
| graph()->MarkDependsOnEmptyArrayProtoElements();
|
| }
|
|
|
| + return load_mode;
|
| +}
|
| +
|
| +
|
| +HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
|
| + HValue* object,
|
| + HValue* key,
|
| + HValue* val,
|
| + HValue* dependency,
|
| + Handle<Map> map,
|
| + bool is_store,
|
| + KeyedAccessStoreMode store_mode) {
|
| + HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(),
|
| + dependency);
|
| + if (dependency) {
|
| + checked_object->ClearGVNFlag(kDependsOnElementsKind);
|
| + }
|
| +
|
| + LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
|
| return BuildUncheckedMonomorphicElementAccess(
|
| - object, key, val,
|
| - mapcheck, map->instance_type() == JS_ARRAY_TYPE,
|
| - map->elements_kind(), is_store, load_mode, store_mode);
|
| + checked_object, key, val,
|
| + map->instance_type() == JS_ARRAY_TYPE,
|
| + map->elements_kind(), is_store,
|
| + load_mode, store_mode);
|
| }
|
|
|
|
|
| @@ -5582,14 +5587,14 @@ HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
|
| }
|
| if (!has_double_maps && !has_smi_or_object_maps) return NULL;
|
|
|
| - HCheckMaps* check_maps = Add<HCheckMaps>(object, maps);
|
| + HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
|
| // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
|
| // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
|
| ElementsKind consolidated_elements_kind = has_seen_holey_elements
|
| ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
|
| : most_general_consolidated_map->elements_kind();
|
| HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
|
| - object, key, val, check_maps,
|
| + checked_object, key, val,
|
| most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
|
| consolidated_elements_kind,
|
| false, NEVER_RETURN_HOLE, STANDARD_STORE);
|
| @@ -5678,12 +5683,8 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| return is_store ? NULL : instr;
|
| }
|
|
|
| - HInstruction* checked_object =
|
| - AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
|
| HBasicBlock* join = graph()->CreateBasicBlock();
|
|
|
| - HInstruction* elements = AddLoadElements(checked_object);
|
| -
|
| for (int i = 0; i < untransitionable_maps.length(); ++i) {
|
| Handle<Map> map = untransitionable_maps[i];
|
| ElementsKind elements_kind = map->elements_kind();
|
| @@ -5694,40 +5695,22 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
| current_block()->Finish(mapcompare);
|
|
|
| set_current_block(this_map);
|
| - HInstruction* checked_key = NULL;
|
| HInstruction* access = NULL;
|
| - if (IsFastElementsKind(elements_kind)) {
|
| - if (is_store && !IsFastDoubleElementsKind(elements_kind)) {
|
| - Add<HCheckMaps>(
|
| - elements, isolate()->factory()->fixed_array_map(),
|
| - top_info(), mapcompare);
|
| - }
|
| - if (map->instance_type() == JS_ARRAY_TYPE) {
|
| - HInstruction* length = Add<HLoadNamedField>(
|
| - mapcompare, HObjectAccess::ForArrayLength(elements_kind));
|
| - checked_key = Add<HBoundsCheck>(key, length);
|
| - } else {
|
| - HInstruction* length = AddLoadFixedArrayLength(elements);
|
| - checked_key = Add<HBoundsCheck>(key, length);
|
| - }
|
| - access = AddFastElementAccess(
|
| - elements, checked_key, val, mapcompare,
|
| - elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE);
|
| - } else if (IsDictionaryElementsKind(elements_kind)) {
|
| - if (is_store) {
|
| - access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
|
| - } else {
|
| - access = AddInstruction(BuildLoadKeyedGeneric(object, key));
|
| - }
|
| + if (IsDictionaryElementsKind(elements_kind)) {
|
| + access = is_store
|
| + ? AddInstruction(BuildStoreKeyedGeneric(object, key, val))
|
| + : AddInstruction(BuildLoadKeyedGeneric(object, key));
|
| } else {
|
| - ASSERT(IsExternalArrayElementsKind(elements_kind));
|
| - HInstruction* length = AddLoadFixedArrayLength(elements);
|
| - checked_key = Add<HBoundsCheck>(key, length);
|
| - HLoadExternalArrayPointer* external_elements =
|
| - Add<HLoadExternalArrayPointer>(elements);
|
| - access = AddExternalArrayElementAccess(
|
| - external_elements, checked_key, val,
|
| - mapcompare, elements_kind, is_store);
|
| + ASSERT(IsFastElementsKind(elements_kind) ||
|
| + IsExternalArrayElementsKind(elements_kind));
|
| + LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
|
| + // Happily, mapcompare is a checked object.
|
| + access = BuildUncheckedMonomorphicElementAccess(
|
| + mapcompare, key, val,
|
| + map->instance_type() == JS_ARRAY_TYPE,
|
| + elements_kind, is_store,
|
| + load_mode,
|
| + store_mode);
|
| }
|
| *has_side_effects |= access->HasObservableSideEffects();
|
| // The caller will use has_side_effects and add a correct Simulate.
|
|
|