Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Unified Diff: src/code-stubs-hydrogen.cc

Issue 57123002: Reland 21774: Generate KeyedLoadGeneric with Hydrogen (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Turn off by default Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/code-stubs-hydrogen.cc
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index f717d75c192423425453b25f4da792b281e83662..16a94527a6cffefb5f0ab7adc91d626f969f1563 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -1328,7 +1328,11 @@ HValue* CodeStubGraphBuilder<KeyedLoadDictionaryElementStub>::BuildCodeStub() {
Add<HCheckSmi>(key);
- return BuildUncheckedDictionaryElementLoad(receiver, key);
+ HValue* elements = AddLoadElements(receiver);
Toon Verwaest 2013/12/04 17:29:26 We need at least a BuildCheckHeapObject(receiver)
danno 2014/06/06 15:43:50 Why is that needed? We already did a map check in
+
+ HValue* hash = BuildElementIndexHash(key);
+
+ return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash);
}
@@ -1337,4 +1341,275 @@ Handle<Code> KeyedLoadDictionaryElementStub::GenerateCode(Isolate* isolate) {
}
+template <>
+class CodeStubGraphBuilder<KeyedLoadGenericElementStub>
+ : public CodeStubGraphBuilderBase {
+ public:
+ CodeStubGraphBuilder(Isolate* isolate,
+ KeyedLoadGenericElementStub* stub)
Toon Verwaest 2013/12/04 17:29:26 nit: Weird indentation
danno 2014/06/06 15:43:50 Done.
+ : CodeStubGraphBuilderBase(isolate, stub) {}
+
+ protected:
+ virtual HValue* BuildCodeStub();
+
+ void BuildFastElementLoad(HGraphBuilder::IfBuilder* if_builder,
+ HValue* receiver,
+ HValue* key,
+ HValue* instance_type,
+ HValue* bit_field2,
+ ElementsKind next_kind,
+ ElementsKind handle_as_kind);
+
+ KeyedLoadGenericElementStub* casted_stub() {
+ return static_cast<KeyedLoadGenericElementStub*>(stub());
+ }
+};
+
+
+void CodeStubGraphBuilder<KeyedLoadGenericElementStub>::BuildFastElementLoad(
+ HGraphBuilder::IfBuilder* if_builder,
+ HValue* receiver,
+ HValue* key,
+ HValue* instance_type,
+ HValue* bit_field2,
+ ElementsKind next_kind,
+ ElementsKind handle_as_kind) {
Toon Verwaest 2013/12/04 17:29:26 In isolation it's very hard to see what this metho
danno 2014/06/06 15:43:50 Done.
+ HValue* next_kind_value =
+ Add<HConstant>(next_kind << Map::kElementsKindShift);
+ if_builder->If<HCompareNumericAndBranch>(bit_field2, next_kind_value,
+ Token::LT);
+ if_builder->Then();
+
+ IfBuilder js_array_check(this);
+
+ if (!IsExternalArrayElementsKind(handle_as_kind)) {
+ js_array_check.If<HCompareNumericAndBranch>(
+ instance_type, Add<HConstant>(JS_ARRAY_TYPE), Token::EQ);
+ }
+
+ js_array_check.Then();
+ if (!IsExternalArrayElementsKind(handle_as_kind)) {
Toon Verwaest 2013/12/04 17:29:26 It's hard to understand what kind of graph is crea
danno 2014/06/06 15:43:50 Done.
+ Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL,
+ true, handle_as_kind,
+ false, NEVER_RETURN_HOLE,
+ STANDARD_STORE));
+ } else {
+ Push(graph()->GetConstant0());
+ }
+
+ js_array_check.Else();
+ Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL,
+ false, handle_as_kind,
+ false, NEVER_RETURN_HOLE,
+ STANDARD_STORE));
+}
+
+
+HValue* CodeStubGraphBuilder<KeyedLoadGenericElementStub>::BuildCodeStub() {
+ HValue* receiver = GetParameter(0);
+ HValue* key = GetParameter(1);
+
+ // 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);
+ BuildReceiverCheck(receiver, bit_field_mask);
Toon Verwaest 2013/12/04 17:29:26 Can we pull these 2 checks out of the continuation
danno 2014/06/06 15:43:50 No, these can't be moved since they are different
+
+ HValue* map = Add<HLoadNamedField>(receiver, HObjectAccess::ForMap());
+
+ HValue* instance_type =
+ Add<HLoadNamedField>(map, HObjectAccess::ForMapInstanceType());
+
+ HValue* bit_field2 = Add<HLoadNamedField>(map,
+ HObjectAccess::ForMapBitField2());
+
+ IfBuilder kind_if(this);
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ FAST_DOUBLE_ELEMENTS, FAST_HOLEY_ELEMENTS);
+
+ kind_if.Else();
+ {
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ DICTIONARY_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS);
+ }
+ kind_if.Else();
+ {
+ int non_strict_elements_kind =
+ NON_STRICT_ARGUMENTS_ELEMENTS << Map::kElementsKindShift;
+ HValue* dictionary_limit = Add<HConstant>(non_strict_elements_kind);
+ kind_if.If<HCompareNumericAndBranch>(bit_field2, dictionary_limit,
+ Token::LT);
+ }
+ kind_if.Then();
+ {
+ HValue* elements = AddLoadElements(receiver);
+
+ HValue* hash = BuildElementIndexHash(key);
+
+ Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash));
+ }
+ // Non-strict elements are not handled.
+ kind_if.Else();
+
+ HValue* non_strict_limit =
+ Add<HConstant>(EXTERNAL_BYTE_ELEMENTS << Map::kElementsKindShift);
+ DeoptimizeIf<HCompareNumericAndBranch>(
+ bit_field2, non_strict_limit, Token::LT,
+ "non-strict argument elements in KeyedLoadGenericElementStub");
+
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
+ EXTERNAL_BYTE_ELEMENTS);
+
+ kind_if.Else();
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ EXTERNAL_SHORT_ELEMENTS,
+ EXTERNAL_UNSIGNED_BYTE_ELEMENTS);
+
+ kind_if.Else();
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
+ EXTERNAL_SHORT_ELEMENTS);
+
+ kind_if.Else();
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ EXTERNAL_INT_ELEMENTS,
+ EXTERNAL_UNSIGNED_SHORT_ELEMENTS);
+
+ kind_if.Else();
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ EXTERNAL_UNSIGNED_INT_ELEMENTS,
+ EXTERNAL_INT_ELEMENTS);
+
+ kind_if.Else();
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ EXTERNAL_FLOAT_ELEMENTS,
+ EXTERNAL_UNSIGNED_INT_ELEMENTS);
+
+ kind_if.Else();
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ EXTERNAL_DOUBLE_ELEMENTS, EXTERNAL_FLOAT_ELEMENTS);
+
+ kind_if.Else();
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ EXTERNAL_PIXEL_ELEMENTS, EXTERNAL_DOUBLE_ELEMENTS);
+
+ kind_if.Else();
+ BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+ static_cast<ElementsKind>(EXTERNAL_PIXEL_ELEMENTS + 1),
+ EXTERNAL_PIXEL_ELEMENTS);
+
+ kind_if.ElseDeopt("ElementsKind unhandled in KeyedLoadGenericElementStub");
+
+ kind_if.End();
+ }
+ index_name_split.Else();
+ {
+ // Key is a unique string.
+ key = Pop();
+
+ int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) |
+ (1 << Map::kHasNamedInterceptor);
+ BuildReceiverCheck(receiver, bit_field_mask);
+
+ HIfContinuation continuation;
+ BuildCheckForDictionaryProperties(receiver, &continuation);
+ IfBuilder if_dict_properties(this, &continuation);
+ if_dict_properties.Then();
+ {
+ // Key is string, properties are dictionary mode
+ BuildGlobalInstanceTypeCheck(receiver);
+
+ HValue* properties = Add<HLoadNamedField>(
+ receiver, HObjectAccess::ForPropertiesPointer());
+
+ HValue* hash =
+ Add<HLoadNamedField>(key, HObjectAccess::ForNameHashField());
+
+ HValue* value = BuildUncheckedDictionaryElementLoad(receiver,
+ properties,
+ key,
+ hash);
+ Push(value);
+ }
+ if_dict_properties.Else();
+ {
+ // 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, HObjectAccess::ForMap());
+ 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) {
+ HValue* map_index = AddUncasted<HAdd>(base_index,
+ Add<HConstant>(probe * 2));
+ map_index->ClearFlag(HValue::kCanOverflow);
+ HValue* key_index = AddUncasted<HAdd>(base_index,
+ Add<HConstant>(probe * 2 + 1));
+ 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_INT_ELEMENTS,
+ NEVER_RETURN_HOLE, 0);
+ Push(property_index);
+ }
+ lookup_if.Else();
+ }
+ Add<HDeoptimize>("KeyedLoad fall-back", Deoptimizer::EAGER);
+ Push(graph()->GetConstant0());
+ lookup_if.End();
+ Push(Add<HLoadFieldByIndex>(receiver, Pop()));
+ }
+ if_dict_properties.End();
+ }
+ index_name_split.End();
+
+ return Pop();
+}
+
+
+Handle<Code> KeyedLoadGenericElementStub::GenerateCode(Isolate* isolate) {
+ return DoGenerateCode(isolate, this);
+}
+
+
} } // namespace v8::internal

Powered by Google App Engine
This is Rietveld 408576698