Index: src/code-stubs-hydrogen.cc |
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc |
index d65026b843ca4ec6d70947c7e03e39e18ccc5e18..45974d2cfb1961447c6438fa284ada83cf725084 100644 |
--- a/src/code-stubs-hydrogen.cc |
+++ b/src/code-stubs-hydrogen.cc |
@@ -1303,4 +1303,139 @@ Handle<Code> FastNewClosureStub::GenerateCode(Isolate* isolate) { |
} |
+template <> |
+class CodeStubGraphBuilder<KeyedLoadDictionaryElementStub> |
+ : public CodeStubGraphBuilderBase { |
+ public: |
+ explicit CodeStubGraphBuilder(Isolate* isolate, |
+ KeyedLoadDictionaryElementStub* stub) |
+ : CodeStubGraphBuilderBase(isolate, stub) {} |
+ |
+ protected: |
+ HValue* BuildCodeStubHelper(HValue* dictionary, |
+ HValue* key, |
+ HValue* hash, |
+ HValue* mask, |
+ int current_probe); |
+ |
+ virtual HValue* BuildCodeStub(); |
+ |
+ KeyedLoadDictionaryElementStub* casted_stub() { |
+ return static_cast<KeyedLoadDictionaryElementStub*>(stub()); |
+ } |
+}; |
+ |
+ |
+HValue* CodeStubGraphBuilder<KeyedLoadDictionaryElementStub>:: |
+ BuildCodeStubHelper( |
+ 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 |
+ : Add<HAdd>(hash, Add<HConstant>(offset)); |
+ raw_index = Add<HBitwise>(Token::BIT_AND, raw_index, mask); |
+ int32_t entry_size = SeededNumberDictionary::kEntrySize; |
+ raw_index = Add<HMul>(raw_index, Add<HConstant>(entry_size)); |
+ raw_index->ClearFlag(HValue::kCanOverflow); |
+ |
+ int32_t base_offset = SeededNumberDictionary::kElementsStartIndex; |
+ HValue* key_index = Add<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_SMI_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 = BuildCodeStubHelper(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 = Add<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_SMI_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 = Add<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* CodeStubGraphBuilder<KeyedLoadDictionaryElementStub>::BuildCodeStub() { |
+ KeyedLoadDictionaryElementStub* stub = casted_stub(); |
+ |
+ HValue* dictionary = GetParameter(0); |
+ HValue* key = GetParameter(1); |
+ USE(stub); |
+ USE(dictionary); |
+ |
+ HValue* elements = AddLoadElements(dictionary); |
+ |
+ Add<HCheckSmi>(key); |
+ |
+ HValue* hash = BuildElementIndexHash(key); |
+ |
+ HValue* capacity = Add<HLoadKeyed>( |
+ elements, |
+ Add<HConstant>(NameDictionary::kCapacityIndex), |
+ static_cast<HValue*>(NULL), |
+ FAST_SMI_ELEMENTS); |
+ |
+ HValue* mask = Add<HSub>(capacity, graph()->GetConstant1()); |
+ mask->ChangeRepresentation(Representation::Integer32()); |
+ mask->ClearFlag(HValue::kCanOverflow); |
+ |
+ return BuildCodeStubHelper(elements, key, hash, mask, 0); |
+} |
+ |
+ |
+Handle<Code> KeyedLoadDictionaryElementStub::GenerateCode(Isolate* isolate) { |
+ return DoGenerateCode(isolate, this); |
+} |
+ |
+ |
} } // namespace v8::internal |