| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 3450115eb873bf5bce0d9721f6adb40736ae4932..bfe22e56dba06f33c14cfc15f4f66abbd63ff960 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1405,6 +1405,138 @@ void HGraphBuilder::BuildTransitionElementsKind(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
|
| + : 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 = 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 = 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* HGraphBuilder::BuildElementIndexHash(HValue* index) {
|
| + int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
|
| + HValue* seed = Add<HConstant>(seed_value);
|
| + HValue* hash = Add<HBitwise>(Token::BIT_XOR, index, seed);
|
| +
|
| + // hash = ~hash + (hash << 15);
|
| + HValue* shifted_hash = Add<HShl>(hash, Add<HConstant>(15));
|
| + HValue* not_hash = Add<HBitwise>(Token::BIT_XOR, hash,
|
| + graph()->GetConstantMinus1());
|
| + hash = Add<HAdd>(shifted_hash, not_hash);
|
| +
|
| + // hash = hash ^ (hash >> 12);
|
| + shifted_hash = Add<HShr>(hash, Add<HConstant>(12));
|
| + hash = Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
|
| +
|
| + // hash = hash + (hash << 2);
|
| + shifted_hash = Add<HShl>(hash, Add<HConstant>(2));
|
| + hash = Add<HAdd>(hash, shifted_hash);
|
| +
|
| + // hash = hash ^ (hash >> 4);
|
| + shifted_hash = Add<HShr>(hash, Add<HConstant>(4));
|
| + hash = Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
|
| +
|
| + // hash = hash * 2057;
|
| + hash = Add<HMul>(hash, Add<HConstant>(2057));
|
| + hash->ClearFlag(HValue::kCanOverflow);
|
| +
|
| + // hash = hash ^ (hash >> 16);
|
| + shifted_hash = Add<HShr>(hash, Add<HConstant>(16));
|
| + return Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
|
| +}
|
| +
|
| +
|
| +HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
|
| + HValue* key) {
|
| + HValue* elements = AddLoadElements(receiver);
|
| +
|
| + 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 BuildUncheckedDictionaryElementLoadHelper(elements, key,
|
| + hash, mask, 0);
|
| +}
|
| +
|
| +
|
| HValue* HGraphBuilder::BuildNumberToString(HValue* object,
|
| Handle<Type> type) {
|
| NoObservableSideEffectsScope scope(this);
|
|
|