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

Unified Diff: src/hydrogen.cc

Issue 369893004: Hydrogenized KeyedLoadGeneric stub: exhaustively search dictionary properties. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 6 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 | « src/hydrogen.h ('k') | 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 a2cf0dc93c8e771f200125ca69e1afc94c5b4687..cfe2f5ea62700027adb6f23c171ef8b3c202a5f2 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1530,8 +1530,8 @@ void HGraphBuilder::BuildKeyedIndexCheck(HValue* key,
}
string_index_if.Else();
{
- // Key is a non-index String, check for uniqueness/internalization. If
- // it's not, deopt.
+ // Key is a non-index String, check for uniqueness/internalization.
+ // If it's not internalized yet, internalize it now.
HValue* not_internalized_bit = AddUncasted<HBitwise>(
Token::BIT_AND,
instance_type,
@@ -1631,84 +1631,6 @@ HValue* HGraphBuilder::BuildKeyedLookupCacheHash(HValue* object,
}
-HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoadHelper(
- HValue* elements,
- HValue* key,
- HValue* hash,
- HValue* mask,
- int current_probe) {
- if (current_probe == kNumberDictionaryProbes) {
- return NULL;
- }
-
- int32_t offset = SeededNumberDictionary::GetProbeOffset(current_probe);
- HValue* raw_index = (current_probe == 0)
- ? hash
- : AddUncasted<HAdd>(hash, Add<HConstant>(offset));
- raw_index = AddUncasted<HBitwise>(Token::BIT_AND, raw_index, mask);
- int32_t entry_size = SeededNumberDictionary::kEntrySize;
- raw_index = AddUncasted<HMul>(raw_index, Add<HConstant>(entry_size));
- raw_index->ClearFlag(HValue::kCanOverflow);
-
- int32_t base_offset = SeededNumberDictionary::kElementsStartIndex;
- HValue* key_index = AddUncasted<HAdd>(raw_index, Add<HConstant>(base_offset));
- key_index->ClearFlag(HValue::kCanOverflow);
-
- HValue* candidate_key = Add<HLoadKeyed>(elements, key_index,
- static_cast<HValue*>(NULL),
- FAST_ELEMENTS);
-
- IfBuilder key_compare(this);
- key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key);
- key_compare.Then();
- {
- // Key at the current probe doesn't match, try at the next probe.
- HValue* result = BuildUncheckedDictionaryElementLoadHelper(
- elements, key, hash, mask, current_probe + 1);
- if (result == NULL) {
- key_compare.Deopt("probes exhausted in keyed load dictionary lookup");
- result = graph()->GetConstantUndefined();
- } else {
- Push(result);
- }
- }
- key_compare.Else();
- {
- // Key at current probe matches. Details must be zero, otherwise the
- // dictionary element requires special handling.
- HValue* details_index = AddUncasted<HAdd>(
- raw_index, Add<HConstant>(base_offset + 2));
- details_index->ClearFlag(HValue::kCanOverflow);
-
- HValue* details = Add<HLoadKeyed>(elements, details_index,
- static_cast<HValue*>(NULL),
- FAST_ELEMENTS);
- IfBuilder details_compare(this);
- details_compare.If<HCompareNumericAndBranch>(details,
- graph()->GetConstant0(),
- Token::NE);
- details_compare.ThenDeopt("keyed load dictionary element not fast case");
-
- details_compare.Else();
- {
- // Key matches and details are zero --> fast case. Load and return the
- // value.
- HValue* result_index = AddUncasted<HAdd>(
- raw_index, Add<HConstant>(base_offset + 1));
- result_index->ClearFlag(HValue::kCanOverflow);
-
- Push(Add<HLoadKeyed>(elements, result_index,
- static_cast<HValue*>(NULL),
- FAST_ELEMENTS));
- }
- details_compare.End();
- }
- key_compare.End();
-
- return Pop();
-}
-
-
HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
HValue* seed = Add<HConstant>(seed_value);
@@ -1756,8 +1678,129 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
mask->ChangeRepresentation(Representation::Integer32());
mask->ClearFlag(HValue::kCanOverflow);
- return BuildUncheckedDictionaryElementLoadHelper(elements, key,
- hash, mask, 0);
+ HValue* entry = hash;
+ HValue* count = graph()->GetConstant1();
+ Push(entry);
+ Push(count);
+
+ HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
+ graph()->CreateBasicBlock());
+ HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
+ graph()->CreateBasicBlock());
+ LoopBuilder probe_loop(this);
+ probe_loop.BeginBody(2); // Drop entry, count from last environment to
danno 2014/07/07 08:10:26 This makes me gag, but I guess there is no other w
Jakob Kummerow 2014/07/07 11:40:43 I don't like it either, but don't see a way around
+ // appease live range building without simulates.
+
+ count = Pop();
+ entry = Pop();
+ entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
+ int entry_size = SeededNumberDictionary::kEntrySize;
+ HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size));
+ base_index->ClearFlag(HValue::kCanOverflow);
+ int start_offset = SeededNumberDictionary::kElementsStartIndex;
+ HValue* key_index =
+ AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
+ key_index->ClearFlag(HValue::kCanOverflow);
+
+ HValue* candidate_key = Add<HLoadKeyed>(
+ elements, key_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+ IfBuilder if_undefined(this);
+ if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
+ graph()->GetConstantUndefined());
+ if_undefined.Then();
+ {
+ // element == undefined means "not found". Call the runtime.
+ // TODO(jkummerow): walk the prototype chain instead.
+ Add<HPushArguments>(receiver, key);
+ Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
+ Runtime::FunctionForId(Runtime::kKeyedGetProperty),
+ 2));
+ }
+ if_undefined.Else();
+ {
+ IfBuilder if_match(this);
+ if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
+ if_match.Then();
+ if_match.Else();
+
+ // Update non-internalized string in the dictionary with internalized key?
+ IfBuilder if_update_with_internalized(this);
+ HValue* smi_check =
+ if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
+ if_update_with_internalized.And();
+ HValue* map = AddLoadMap(candidate_key, smi_check);
+ HValue* instance_type = Add<HLoadNamedField>(
+ map, static_cast<HValue*>(NULL), HObjectAccess::ForMapInstanceType());
+ HValue* not_internalized_bit = AddUncasted<HBitwise>(
+ Token::BIT_AND, instance_type,
+ Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
+ if_update_with_internalized.If<HCompareNumericAndBranch>(
+ not_internalized_bit, graph()->GetConstant0(), Token::NE);
+ if_update_with_internalized.And();
+ if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
+ candidate_key, graph()->GetConstantHole());
+ if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
+ key, Token::EQ);
+ if_update_with_internalized.Then();
+ // Replace a key that is a non-internalized string by the equivalent
+ // internalized string for faster further lookups.
+ Add<HStoreKeyed>(elements, key_index, key, FAST_ELEMENTS);
+ if_update_with_internalized.Else();
+
+ if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
+ if_match.JoinContinuation(&found_key_match_continuation);
+
+ IfBuilder found_key_match(this, &found_key_match_continuation);
+ found_key_match.Then();
+ // Key at current probe matches. Relevant bits in the |details| field must
+ // be zero, otherwise the dictionary element requires special handling.
+ HValue* details_index =
+ AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
+ details_index->ClearFlag(HValue::kCanOverflow);
+ HValue* details = Add<HLoadKeyed>(
+ elements, details_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+ int details_mask = PropertyDetails::TypeField::kMask |
+ PropertyDetails::DeletedField::kMask;
+ details = AddUncasted<HBitwise>(Token::BIT_AND, details,
+ Add<HConstant>(details_mask));
+ IfBuilder details_compare(this);
+ details_compare.If<HCompareNumericAndBranch>(
+ details, graph()->GetConstant0(), Token::EQ);
+ details_compare.Then();
+ HValue* result_index =
+ AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
+ result_index->ClearFlag(HValue::kCanOverflow);
+ Push(Add<HLoadKeyed>(elements, result_index, static_cast<HValue*>(NULL),
+ FAST_ELEMENTS));
+ details_compare.Else();
+ Add<HPushArguments>(receiver, key);
+ Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
+ Runtime::FunctionForId(Runtime::kKeyedGetProperty),
+ 2));
+ details_compare.End();
+
+ found_key_match.Else();
+ found_key_match.JoinContinuation(&return_or_loop_continuation);
+ }
+ if_undefined.JoinContinuation(&return_or_loop_continuation);
+
+ IfBuilder return_or_loop(this, &return_or_loop_continuation);
+ return_or_loop.Then();
+ probe_loop.Break();
+
+ return_or_loop.Else();
+ entry = AddUncasted<HAdd>(entry, count);
+ entry->ClearFlag(HValue::kCanOverflow);
+ count = AddUncasted<HAdd>(count, graph()->GetConstant1());
+ count->ClearFlag(HValue::kCanOverflow);
+ Push(entry);
+ Push(count);
+
+ probe_loop.EndBody();
+
+ return_or_loop.End();
+
+ return Pop();
}
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698