Chromium Code Reviews| 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(); |
| } |