Index: src/code-stubs-hydrogen.cc |
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc |
index 6f86778f997e33a09a223d8b955908b765674937..c6705c3e2d6caef555ec361048bf971d9fd467f9 100644 |
--- a/src/code-stubs-hydrogen.cc |
+++ b/src/code-stubs-hydrogen.cc |
@@ -1654,50 +1654,67 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericElementStub>::BuildCodeStub() { |
HValue* base_index = AddUncasted<HMul>(hash, Add<HConstant>(2)); |
base_index->ClearFlag(HValue::kCanOverflow); |
- IfBuilder lookup_if(this); |
- for (int probe = 0; probe < KeyedLookupCache::kEntriesPerBucket; |
- ++probe) { |
- int probe_base = probe * KeyedLookupCache::kEntryLength; |
- HValue* map_index = AddUncasted<HAdd>(base_index, |
- Add<HConstant>(probe_base + KeyedLookupCache::kMapIndex)); |
- map_index->ClearFlag(HValue::kCanOverflow); |
- HValue* key_index = AddUncasted<HAdd>(base_index, |
- Add<HConstant>(probe_base + KeyedLookupCache::kKeyIndex)); |
- key_index->ClearFlag(HValue::kCanOverflow); |
- HValue* map_to_check = Add<HLoadKeyed>(cache_keys, |
- map_index, |
- static_cast<HValue*>(NULL), |
- FAST_ELEMENTS, |
- NEVER_RETURN_HOLE, 0); |
- lookup_if.If<HCompareObjectEqAndBranch>(map_to_check, map); |
- lookup_if.And(); |
- HValue* key_to_check = Add<HLoadKeyed>(cache_keys, |
- key_index, |
- static_cast<HValue*>(NULL), |
- FAST_ELEMENTS, |
- NEVER_RETURN_HOLE, 0); |
- lookup_if.If<HCompareObjectEqAndBranch>(key_to_check, key); |
- lookup_if.Then(); |
- { |
- ExternalReference cache_field_offsets_ref = |
- ExternalReference::keyed_lookup_cache_field_offsets(isolate()); |
- HValue* cache_field_offsets = Add<HConstant>(cache_field_offsets_ref); |
- HValue* index = AddUncasted<HAdd>(hash, |
- Add<HConstant>(probe)); |
- index->ClearFlag(HValue::kCanOverflow); |
- HValue* property_index = Add<HLoadKeyed>(cache_field_offsets, |
- index, |
- static_cast<HValue*>(NULL), |
- EXTERNAL_INT32_ELEMENTS, |
- NEVER_RETURN_HOLE, 0); |
- Push(property_index); |
+ HIfContinuation inline_or_runtime_continuation( |
+ graph()->CreateBasicBlock(), graph()->CreateBasicBlock()); |
+ { |
+ IfBuilder lookup_ifs[KeyedLookupCache::kEntriesPerBucket]; |
+ for (int probe = 0; probe < KeyedLookupCache::kEntriesPerBucket; |
+ ++probe) { |
+ IfBuilder* lookup_if = &lookup_ifs[probe]; |
+ lookup_if->Initialize(this); |
+ int probe_base = probe * KeyedLookupCache::kEntryLength; |
+ HValue* map_index = AddUncasted<HAdd>( |
+ base_index, |
+ Add<HConstant>(probe_base + KeyedLookupCache::kMapIndex)); |
+ map_index->ClearFlag(HValue::kCanOverflow); |
+ HValue* key_index = AddUncasted<HAdd>( |
+ base_index, |
+ Add<HConstant>(probe_base + KeyedLookupCache::kKeyIndex)); |
+ key_index->ClearFlag(HValue::kCanOverflow); |
+ HValue* map_to_check = |
+ Add<HLoadKeyed>(cache_keys, map_index, static_cast<HValue*>(NULL), |
+ FAST_ELEMENTS, NEVER_RETURN_HOLE, 0); |
+ lookup_if->If<HCompareObjectEqAndBranch>(map_to_check, map); |
+ lookup_if->And(); |
+ HValue* key_to_check = |
+ Add<HLoadKeyed>(cache_keys, key_index, static_cast<HValue*>(NULL), |
+ FAST_ELEMENTS, NEVER_RETURN_HOLE, 0); |
+ lookup_if->If<HCompareObjectEqAndBranch>(key_to_check, key); |
+ lookup_if->Then(); |
+ { |
+ ExternalReference cache_field_offsets_ref = |
+ ExternalReference::keyed_lookup_cache_field_offsets(isolate()); |
+ HValue* cache_field_offsets = |
+ Add<HConstant>(cache_field_offsets_ref); |
+ HValue* index = AddUncasted<HAdd>(hash, Add<HConstant>(probe)); |
+ index->ClearFlag(HValue::kCanOverflow); |
+ HValue* property_index = Add<HLoadKeyed>( |
+ cache_field_offsets, index, static_cast<HValue*>(NULL), |
+ EXTERNAL_INT32_ELEMENTS, NEVER_RETURN_HOLE, 0); |
+ Push(property_index); |
+ } |
+ lookup_if->Else(); |
+ } |
+ for (int i = 0; i < KeyedLookupCache::kEntriesPerBucket; ++i) { |
+ lookup_ifs[i].JoinContinuation(&inline_or_runtime_continuation); |
} |
- lookup_if.Else(); |
} |
- Add<HDeoptimize>("KeyedLoad fall-back", Deoptimizer::EAGER); |
- Push(graph()->GetConstant0()); |
- lookup_if.End(); |
- Push(Add<HLoadFieldByIndex>(receiver, Pop())); |
+ |
+ IfBuilder inline_or_runtime(this, &inline_or_runtime_continuation); |
+ inline_or_runtime.Then(); |
+ { |
+ // Found a cached index, load property inline. |
+ Push(Add<HLoadFieldByIndex>(receiver, Pop())); |
+ } |
+ inline_or_runtime.Else(); |
+ { |
+ // KeyedLookupCache miss; call runtime. |
+ Add<HPushArguments>(receiver, key); |
+ Push(Add<HCallRuntime>( |
+ isolate()->factory()->empty_string(), |
+ Runtime::FunctionForId(Runtime::kKeyedGetProperty), 2)); |
+ } |
+ inline_or_runtime.End(); |
} |
if_dict_properties.End(); |
} |