| Index: src/code-stubs-hydrogen.cc
|
| diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
|
| index e423ed39db917318b642a86d2730c225eff05776..a162681c93359f58641e4398c81f87145e4bfb2c 100644
|
| --- a/src/code-stubs-hydrogen.cc
|
| +++ b/src/code-stubs-hydrogen.cc
|
| @@ -1204,253 +1204,5 @@ Handle<Code> RegExpConstructResultStub::GenerateCode() {
|
| return DoGenerateCode(this);
|
| }
|
|
|
| -
|
| -template <>
|
| -class CodeStubGraphBuilder<KeyedLoadGenericStub>
|
| - : public CodeStubGraphBuilderBase {
|
| - public:
|
| - explicit CodeStubGraphBuilder(CompilationInfo* info, CodeStub* stub)
|
| - : CodeStubGraphBuilderBase(info, stub) {}
|
| -
|
| - typedef KeyedLoadGenericStub::Descriptor Descriptor;
|
| -
|
| - protected:
|
| - virtual HValue* BuildCodeStub();
|
| -
|
| - void BuildElementsKindLimitCheck(HGraphBuilder::IfBuilder* if_builder,
|
| - HValue* bit_field2,
|
| - ElementsKind kind);
|
| -
|
| - void BuildFastElementLoad(HGraphBuilder::IfBuilder* if_builder,
|
| - HValue* receiver,
|
| - HValue* key,
|
| - HValue* instance_type,
|
| - HValue* bit_field2,
|
| - ElementsKind kind);
|
| -
|
| - KeyedLoadGenericStub* casted_stub() {
|
| - return static_cast<KeyedLoadGenericStub*>(stub());
|
| - }
|
| -};
|
| -
|
| -
|
| -void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildElementsKindLimitCheck(
|
| - HGraphBuilder::IfBuilder* if_builder, HValue* bit_field2,
|
| - ElementsKind kind) {
|
| - ElementsKind next_kind = static_cast<ElementsKind>(kind + 1);
|
| - HValue* kind_limit = Add<HConstant>(
|
| - static_cast<int>(Map::ElementsKindBits::encode(next_kind)));
|
| -
|
| - if_builder->If<HCompareNumericAndBranch>(bit_field2, kind_limit, Token::LT);
|
| - if_builder->Then();
|
| -}
|
| -
|
| -
|
| -void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildFastElementLoad(
|
| - HGraphBuilder::IfBuilder* if_builder, HValue* receiver, HValue* key,
|
| - HValue* instance_type, HValue* bit_field2, ElementsKind kind) {
|
| - BuildElementsKindLimitCheck(if_builder, bit_field2, kind);
|
| -
|
| - IfBuilder js_array_check(this);
|
| - js_array_check.If<HCompareNumericAndBranch>(
|
| - instance_type, Add<HConstant>(JS_ARRAY_TYPE), Token::EQ);
|
| - js_array_check.Then();
|
| - Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL,
|
| - true, kind,
|
| - LOAD, NEVER_RETURN_HOLE,
|
| - STANDARD_STORE));
|
| - js_array_check.Else();
|
| - Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL,
|
| - false, kind,
|
| - LOAD, NEVER_RETURN_HOLE,
|
| - STANDARD_STORE));
|
| - js_array_check.End();
|
| -}
|
| -
|
| -
|
| -HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
|
| - HValue* receiver = GetParameter(Descriptor::kReceiver);
|
| - HValue* key = GetParameter(Descriptor::kName);
|
| - // Split into a smi/integer case and unique string case.
|
| - HIfContinuation index_name_split_continuation(graph()->CreateBasicBlock(),
|
| - graph()->CreateBasicBlock());
|
| -
|
| - BuildKeyedIndexCheck(key, &index_name_split_continuation);
|
| -
|
| - IfBuilder index_name_split(this, &index_name_split_continuation);
|
| - index_name_split.Then();
|
| - {
|
| - // Key is an index (number)
|
| - key = Pop();
|
| -
|
| - int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) |
|
| - (1 << Map::kHasIndexedInterceptor);
|
| - BuildJSObjectCheck(receiver, bit_field_mask);
|
| -
|
| - HValue* map =
|
| - Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
|
| -
|
| - HValue* instance_type =
|
| - Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
|
| -
|
| - HValue* bit_field2 =
|
| - Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
|
| -
|
| - IfBuilder kind_if(this);
|
| - BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
|
| - FAST_HOLEY_ELEMENTS);
|
| -
|
| - kind_if.Else();
|
| - {
|
| - BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
|
| - FAST_HOLEY_DOUBLE_ELEMENTS);
|
| - }
|
| - kind_if.Else();
|
| -
|
| - // The DICTIONARY_ELEMENTS check generates a "kind_if.Then"
|
| - BuildElementsKindLimitCheck(&kind_if, bit_field2, DICTIONARY_ELEMENTS);
|
| - {
|
| - HValue* elements = AddLoadElements(receiver);
|
| -
|
| - HValue* hash = BuildElementIndexHash(key);
|
| -
|
| - Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash));
|
| - }
|
| - kind_if.Else();
|
| -
|
| - // The SLOW_SLOPPY_ARGUMENTS_ELEMENTS check generates a "kind_if.Then"
|
| - STATIC_ASSERT(FAST_SLOPPY_ARGUMENTS_ELEMENTS <
|
| - SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
|
| - BuildElementsKindLimitCheck(&kind_if, bit_field2,
|
| - SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
|
| - // Non-strict elements are not handled.
|
| - Add<HDeoptimize>(DeoptimizeReason::kNonStrictElementsInKeyedLoadGenericStub,
|
| - Deoptimizer::EAGER);
|
| - Push(graph()->GetConstant0());
|
| -
|
| - kind_if.ElseDeopt(
|
| - DeoptimizeReason::kElementsKindUnhandledInKeyedLoadGenericStub);
|
| -
|
| - kind_if.End();
|
| - }
|
| - index_name_split.Else();
|
| - {
|
| - // Key is a unique string.
|
| - key = Pop();
|
| -
|
| - int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) |
|
| - (1 << Map::kHasNamedInterceptor);
|
| - BuildJSObjectCheck(receiver, bit_field_mask);
|
| -
|
| - HIfContinuation continuation;
|
| - BuildTestForDictionaryProperties(receiver, &continuation);
|
| - IfBuilder if_dict_properties(this, &continuation);
|
| - if_dict_properties.Then();
|
| - {
|
| - // Key is string, properties are dictionary mode
|
| - BuildNonGlobalObjectCheck(receiver);
|
| -
|
| - HValue* properties = Add<HLoadNamedField>(
|
| - receiver, nullptr, HObjectAccess::ForPropertiesPointer());
|
| -
|
| - HValue* hash =
|
| - Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForNameHashField());
|
| -
|
| - hash = AddUncasted<HShr>(hash, Add<HConstant>(Name::kHashShift));
|
| -
|
| - HValue* value =
|
| - BuildUncheckedDictionaryElementLoad(receiver, properties, key, hash);
|
| - Push(value);
|
| - }
|
| - if_dict_properties.Else();
|
| - {
|
| - // TODO(dcarney): don't use keyed lookup cache, but convert to use
|
| - // megamorphic stub cache.
|
| - UNREACHABLE();
|
| - // Key is string, properties are fast mode
|
| - HValue* hash = BuildKeyedLookupCacheHash(receiver, key);
|
| -
|
| - ExternalReference cache_keys_ref =
|
| - ExternalReference::keyed_lookup_cache_keys(isolate());
|
| - HValue* cache_keys = Add<HConstant>(cache_keys_ref);
|
| -
|
| - HValue* map =
|
| - Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
|
| - HValue* base_index = AddUncasted<HMul>(hash, Add<HConstant>(2));
|
| - base_index->ClearFlag(HValue::kCanOverflow);
|
| -
|
| - 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, nullptr, nullptr,
|
| - 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, nullptr, nullptr,
|
| - 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, nullptr, cache_keys,
|
| - 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);
|
| - }
|
| - }
|
| -
|
| - 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>(
|
| - Runtime::FunctionForId(Runtime::kKeyedGetProperty), 2));
|
| - }
|
| - inline_or_runtime.End();
|
| - }
|
| - if_dict_properties.End();
|
| - }
|
| - index_name_split.End();
|
| -
|
| - return Pop();
|
| -}
|
| -
|
| -
|
| -Handle<Code> KeyedLoadGenericStub::GenerateCode() {
|
| - return DoGenerateCode(this);
|
| -}
|
| -
|
| } // namespace internal
|
| } // namespace v8
|
|
|