Consolidate similar KeyedLoads to worst case instead of transitioning elements
R=jkummerow@chromium.org Review URL: https://chromiumcodereview.appspot.com/10692043 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11959 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
fc3c94535d
commit
ec65e4fe78
@ -5748,16 +5748,31 @@ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
|
|||||||
HValue* dependency,
|
HValue* dependency,
|
||||||
Handle<Map> map,
|
Handle<Map> map,
|
||||||
bool is_store) {
|
bool is_store) {
|
||||||
HInstruction* mapcheck =
|
HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map,
|
||||||
AddInstruction(new(zone()) HCheckMaps(object, map, zone(), dependency));
|
zone(), dependency);
|
||||||
|
AddInstruction(mapcheck);
|
||||||
|
if (dependency) {
|
||||||
|
mapcheck->ClearGVNFlag(kDependsOnElementsKind);
|
||||||
|
}
|
||||||
|
return BuildUncheckedMonomorphicElementAccess(object, key, val,
|
||||||
|
mapcheck, map, is_store);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
||||||
|
HValue* object,
|
||||||
|
HValue* key,
|
||||||
|
HValue* val,
|
||||||
|
HCheckMaps* mapcheck,
|
||||||
|
Handle<Map> map,
|
||||||
|
bool is_store) {
|
||||||
// No GVNFlag is necessary for ElementsKind if there is an explicit dependency
|
// No GVNFlag is necessary for ElementsKind if there is an explicit dependency
|
||||||
// on a HElementsTransition instruction. The flag can also be removed if the
|
// on a HElementsTransition instruction. The flag can also be removed if the
|
||||||
// map to check has FAST_HOLEY_ELEMENTS, since there can be no further
|
// map to check has FAST_HOLEY_ELEMENTS, since there can be no further
|
||||||
// ElementsKind transitions. Finally, the dependency can be removed for stores
|
// ElementsKind transitions. Finally, the dependency can be removed for stores
|
||||||
// for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
|
// for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
|
||||||
// generated store code.
|
// generated store code.
|
||||||
if (dependency ||
|
if ((map->elements_kind() == FAST_HOLEY_ELEMENTS) ||
|
||||||
(map->elements_kind() == FAST_HOLEY_ELEMENTS) ||
|
|
||||||
(map->elements_kind() == FAST_ELEMENTS && is_store)) {
|
(map->elements_kind() == FAST_ELEMENTS && is_store)) {
|
||||||
mapcheck->ClearGVNFlag(kDependsOnElementsKind);
|
mapcheck->ClearGVNFlag(kDependsOnElementsKind);
|
||||||
}
|
}
|
||||||
@ -5796,6 +5811,59 @@ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HInstruction* HGraphBuilder::TryBuildConsolidatedElementLoad(
|
||||||
|
HValue* object,
|
||||||
|
HValue* key,
|
||||||
|
HValue* val,
|
||||||
|
SmallMapList* maps) {
|
||||||
|
// For polymorphic loads of similar elements kinds (i.e. all tagged or all
|
||||||
|
// double), always use the "worst case" code without a transition. This is
|
||||||
|
// much faster than transitioning the elements to the worst case, trading a
|
||||||
|
// HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
|
||||||
|
bool has_double_maps = false;
|
||||||
|
bool has_smi_or_object_maps = false;
|
||||||
|
bool has_js_array_access = false;
|
||||||
|
bool has_non_js_array_access = false;
|
||||||
|
Handle<Map> most_general_consolidated_map;
|
||||||
|
for (int i = 0; i < maps->length(); ++i) {
|
||||||
|
Handle<Map> map = maps->at(i);
|
||||||
|
// Don't allow mixing of JSArrays with JSObjects.
|
||||||
|
if (map->instance_type() == JS_ARRAY_TYPE) {
|
||||||
|
if (has_non_js_array_access) return NULL;
|
||||||
|
has_js_array_access = true;
|
||||||
|
} else if (has_js_array_access) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
has_non_js_array_access = true;
|
||||||
|
}
|
||||||
|
// Don't allow mixed, incompatible elements kinds.
|
||||||
|
if (map->has_fast_double_elements()) {
|
||||||
|
if (has_smi_or_object_maps) return NULL;
|
||||||
|
has_double_maps = true;
|
||||||
|
} else if (map->has_fast_smi_or_object_elements()) {
|
||||||
|
if (has_double_maps) return NULL;
|
||||||
|
has_smi_or_object_maps = true;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Remember the most general elements kind, the code for its load will
|
||||||
|
// properly handle all of the more specific cases.
|
||||||
|
if ((i == 0) || IsMoreGeneralElementsKindTransition(
|
||||||
|
most_general_consolidated_map->elements_kind(),
|
||||||
|
map->elements_kind())) {
|
||||||
|
most_general_consolidated_map = map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!has_double_maps && !has_smi_or_object_maps) return NULL;
|
||||||
|
|
||||||
|
HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone());
|
||||||
|
AddInstruction(check_maps);
|
||||||
|
HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
|
||||||
|
object, key, val, check_maps, most_general_consolidated_map, false);
|
||||||
|
return instr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
|
HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
|
||||||
HValue* key,
|
HValue* key,
|
||||||
HValue* val,
|
HValue* val,
|
||||||
@ -5809,6 +5877,17 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
|
|||||||
SmallMapList* maps = prop->GetReceiverTypes();
|
SmallMapList* maps = prop->GetReceiverTypes();
|
||||||
bool todo_external_array = false;
|
bool todo_external_array = false;
|
||||||
|
|
||||||
|
if (!is_store) {
|
||||||
|
HInstruction* consolidated_load =
|
||||||
|
TryBuildConsolidatedElementLoad(object, key, val, maps);
|
||||||
|
if (consolidated_load != NULL) {
|
||||||
|
AddInstruction(consolidated_load);
|
||||||
|
*has_side_effects |= consolidated_load->HasObservableSideEffects();
|
||||||
|
consolidated_load->set_position(position);
|
||||||
|
return consolidated_load;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const int kNumElementTypes = kElementsKindCount;
|
static const int kNumElementTypes = kElementsKindCount;
|
||||||
bool type_todo[kNumElementTypes];
|
bool type_todo[kNumElementTypes];
|
||||||
for (int i = 0; i < kNumElementTypes; ++i) {
|
for (int i = 0; i < kNumElementTypes; ++i) {
|
||||||
|
@ -1101,12 +1101,25 @@ class HGraphBuilder: public AstVisitor {
|
|||||||
ElementsKind elements_kind,
|
ElementsKind elements_kind,
|
||||||
bool is_store);
|
bool is_store);
|
||||||
|
|
||||||
|
HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
|
||||||
|
HValue* key,
|
||||||
|
HValue* val,
|
||||||
|
SmallMapList* maps);
|
||||||
|
|
||||||
|
HInstruction* BuildUncheckedMonomorphicElementAccess(HValue* object,
|
||||||
|
HValue* key,
|
||||||
|
HValue* val,
|
||||||
|
HCheckMaps* mapcheck,
|
||||||
|
Handle<Map> map,
|
||||||
|
bool is_store);
|
||||||
|
|
||||||
HInstruction* BuildMonomorphicElementAccess(HValue* object,
|
HInstruction* BuildMonomorphicElementAccess(HValue* object,
|
||||||
HValue* key,
|
HValue* key,
|
||||||
HValue* val,
|
HValue* val,
|
||||||
HValue* dependency,
|
HValue* dependency,
|
||||||
Handle<Map> map,
|
Handle<Map> map,
|
||||||
bool is_store);
|
bool is_store);
|
||||||
|
|
||||||
HValue* HandlePolymorphicElementAccess(HValue* object,
|
HValue* HandlePolymorphicElementAccess(HValue* object,
|
||||||
HValue* key,
|
HValue* key,
|
||||||
HValue* val,
|
HValue* val,
|
||||||
|
Loading…
Reference in New Issue
Block a user