Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(431)

Unified Diff: src/hydrogen.cc

Issue 18209023: Hydrogen array accesses: switch from elements_kind to map based polymorphism (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index c90e5c5b7e09630f89205b9dbe03ef15312b8cc2..4b8f1636e1691330453dffe6dec0c06bb61966a3 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -5892,7 +5892,6 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
*has_side_effects = false;
BuildCheckHeapObject(object);
SmallMapList* maps = prop->GetReceiverTypes();
- bool todo_external_array = false;
if (!is_store) {
HInstruction* consolidated_load =
@@ -5906,12 +5905,6 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
}
}
- static const int kNumElementTypes = kElementsKindCount;
- bool type_todo[kNumElementTypes];
- for (int i = 0; i < kNumElementTypes; ++i) {
- type_todo[i] = false;
- }
-
// Elements_kind transition support.
MapHandleList transition_target(maps->length());
// Collect possible transition targets.
@@ -5932,8 +5925,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
transition_target.Add(transitioned_map);
}
- int num_untransitionable_maps = 0;
- Handle<Map> untransitionable_map;
+ MapHandleList untransitionable_maps(maps->length());
HTransitionElementsKind* transition = NULL;
for (int i = 0; i < maps->length(); ++i) {
Handle<Map> map = maps->at(i);
@@ -5946,19 +5938,15 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
transition = Add<HTransitionElementsKind>(context, object, map,
transition_target.at(i));
} else {
- type_todo[map->elements_kind()] = true;
- if (IsExternalArrayElementsKind(map->elements_kind())) {
- todo_external_array = true;
- }
- num_untransitionable_maps++;
- untransitionable_map = map;
+ untransitionable_maps.Add(map);
}
}
// If only one map is left after transitioning, handle this case
// monomorphically.
- ASSERT(num_untransitionable_maps >= 1);
- if (num_untransitionable_maps == 1) {
+ ASSERT(untransitionable_maps.length() >= 1);
+ if (untransitionable_maps.length() == 1) {
+ Handle<Map> untransitionable_map = untransitionable_maps[0];
HInstruction* instr = NULL;
if (untransitionable_map->has_slow_elements_kind()) {
instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
@@ -5977,113 +5965,63 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
HBasicBlock* join = graph()->CreateBasicBlock();
- HInstruction* elements_kind_instr = Add<HElementsKind>(object);
HInstruction* elements = AddLoadElements(object, checkspec);
- HLoadExternalArrayPointer* external_elements = NULL;
- HInstruction* checked_key = NULL;
-
- // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds
- // are handled before external arrays.
- STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
- STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
- STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
- STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
-
- for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND;
- elements_kind <= LAST_ELEMENTS_KIND;
- elements_kind = ElementsKind(elements_kind + 1)) {
- // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some
- // code that's executed for all external array cases.
- STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
- LAST_ELEMENTS_KIND);
- if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
- && todo_external_array) {
- HInstruction* length = AddLoadFixedArrayLength(elements);
- checked_key = Add<HBoundsCheck>(key, length);
- external_elements = Add<HLoadExternalArrayPointer>(elements);
- }
- if (type_todo[elements_kind]) {
- HBasicBlock* if_true = graph()->CreateBasicBlock();
- HBasicBlock* if_false = graph()->CreateBasicBlock();
- HCompareConstantEqAndBranch* elements_kind_branch =
- new(zone()) HCompareConstantEqAndBranch(
- elements_kind_instr, elements_kind, Token::EQ_STRICT);
- elements_kind_branch->SetSuccessorAt(0, if_true);
- elements_kind_branch->SetSuccessorAt(1, if_false);
- current_block()->Finish(elements_kind_branch);
- set_current_block(if_true);
- HInstruction* access;
- if (IsFastElementsKind(elements_kind)) {
- if (is_store && !IsFastDoubleElementsKind(elements_kind)) {
- AddInstruction(HCheckMaps::New(
- elements, isolate()->factory()->fixed_array_map(),
- zone(), elements_kind_branch));
- }
- // TODO(jkummerow): The need for these two blocks could be avoided
- // in one of two ways:
- // (1) Introduce ElementsKinds for JSArrays that are distinct from
- // those for fast objects.
- // (2) Put the common instructions into a third "join" block. This
- // requires additional AST IDs that we can deopt to from inside
- // that join block. They must be added to the Property class (when
- // it's a keyed property) and registered in the full codegen.
- HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
- HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
- HHasInstanceTypeAndBranch* typecheck =
- new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
- typecheck->SetSuccessorAt(0, if_jsarray);
- typecheck->SetSuccessorAt(1, if_fastobject);
- current_block()->Finish(typecheck);
-
- set_current_block(if_jsarray);
+ for (int i = 0; i < untransitionable_maps.length(); ++i) {
+ Handle<Map> map = untransitionable_maps[i];
+ ElementsKind elements_kind = map->elements_kind();
+ HBasicBlock* this_map = graph()->CreateBasicBlock();
+ HBasicBlock* other_map = graph()->CreateBasicBlock();
+ HCompareMap* mapcompare =
+ new(zone()) HCompareMap(object, map, this_map, other_map);
+ 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)) {
+ AddInstruction(HCheckMaps::New(
+ elements, isolate()->factory()->fixed_array_map(),
+ zone(), mapcompare));
+ }
+ if (map->IsJSArray()) {
HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(),
- typecheck, Representation::Smi());
+ mapcompare, Representation::Smi());
length->set_type(HType::Smi());
-
checked_key = Add<HBoundsCheck>(key, length);
- access = AddInstruction(BuildFastElementAccess(
- elements, checked_key, val, elements_kind_branch,
- elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
- if (!is_store) {
- Push(access);
- }
-
- *has_side_effects |= access->HasObservableSideEffects();
- // The caller will use has_side_effects and add correct Simulate.
- access->SetFlag(HValue::kHasNoObservableSideEffects);
- if (position != -1) {
- access->set_position(position);
- }
- if_jsarray->GotoNoSimulate(join);
-
- set_current_block(if_fastobject);
- length = AddLoadFixedArrayLength(elements);
+ } else {
+ HInstruction* length = AddLoadFixedArrayLength(elements);
checked_key = Add<HBoundsCheck>(key, length);
- access = AddInstruction(BuildFastElementAccess(
- elements, checked_key, val, elements_kind_branch,
- elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
- } else if (elements_kind == DICTIONARY_ELEMENTS) {
- if (is_store) {
- access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
- } else {
- access = AddInstruction(BuildLoadKeyedGeneric(object, key));
- }
- } else { // External array elements.
- access = AddInstruction(BuildExternalArrayElementAccess(
- external_elements, checked_key, val,
- elements_kind_branch, elements_kind, is_store));
}
- *has_side_effects |= access->HasObservableSideEffects();
- // The caller will use has_side_effects and add correct Simulate.
- access->SetFlag(HValue::kHasNoObservableSideEffects);
- if (position != RelocInfo::kNoPosition) access->set_position(position);
- if (!is_store) {
- Push(access);
+ access = AddInstruction(BuildFastElementAccess(
+ 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));
}
- current_block()->GotoNoSimulate(join);
- set_current_block(if_false);
- }
+ } else {
+ ASSERT(IsExternalArrayElementsKind(elements_kind));
+ HInstruction* length = AddLoadFixedArrayLength(elements);
+ checked_key = Add<HBoundsCheck>(key, length);
+ HLoadExternalArrayPointer* external_elements =
+ Add<HLoadExternalArrayPointer>(elements);
+ access = AddInstruction(BuildExternalArrayElementAccess(
+ external_elements, checked_key, val,
+ mapcompare, elements_kind, is_store));
+ }
+ *has_side_effects |= access->HasObservableSideEffects();
+ // The caller will use has_side_effects and add a correct Simulate.
+ access->SetFlag(HValue::kHasNoObservableSideEffects);
+ if (position != RelocInfo::kNoPosition) access->set_position(position);
+ if (!is_store) {
+ Push(access);
+ }
+ current_block()->GotoNoSimulate(join);
+ set_current_block(other_map);
}
// Deopt if none of the cases matched.
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698