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

Unified Diff: src/code-stub-assembler.cc

Issue 2303793002: Revert of [stubs] Port KeyedLoadIC_Generic stub to TurboFan (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 3 months 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
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/ic/handler-compiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/code-stub-assembler.cc
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index a9bb408048773244644c417279111be93ff571b6..3ff4ff9b192b4789b55f688b79355feba822b590 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -630,61 +630,69 @@
Goto(if_notequal);
}
-void CodeStubAssembler::BranchIfPrototypesHaveNoElements(
- Node* receiver_map, Label* definitely_no_elements,
- Label* possibly_elements) {
- Variable var_map(this, MachineRepresentation::kTagged);
- var_map.Bind(receiver_map);
- Label loop_body(this, &var_map);
- Node* empty_elements = LoadRoot(Heap::kEmptyFixedArrayRootIndex);
- Goto(&loop_body);
-
- Bind(&loop_body);
- {
- Node* map = var_map.value();
- Node* prototype = LoadMapPrototype(map);
- GotoIf(WordEqual(prototype, NullConstant()), definitely_no_elements);
- Node* prototype_map = LoadMap(prototype);
- // Pessimistically assume elements if a Proxy, Special API Object,
- // or JSValue wrapper is found on the prototype chain. After this
- // instance type check, it's not necessary to check for interceptors or
- // access checks.
- GotoIf(Int32LessThanOrEqual(LoadMapInstanceType(prototype_map),
- Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
- possibly_elements);
- GotoIf(WordNotEqual(LoadElements(prototype), empty_elements),
- possibly_elements);
- var_map.Bind(prototype_map);
- Goto(&loop_body);
- }
-}
-
void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context,
Label* if_true, Label* if_false) {
- // Bailout if receiver is a Smi.
+ Node* int32_zero = Int32Constant(0);
+ Node* int32_one = Int32Constant(1);
+
+ Node* empty_elements = LoadRoot(Heap::kEmptyFixedArrayRootIndex);
+
+ Variable last_map(this, MachineRepresentation::kTagged);
+ Label check_prototype(this);
+
+ // Bailout if Smi
GotoIf(WordIsSmi(object), if_false);
Node* map = LoadMap(object);
-
- // Bailout if instance type is not JS_ARRAY_TYPE.
+ last_map.Bind(map);
+
+ // Bailout if instance type is not JS_ARRAY_TYPE
GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)),
if_false);
Node* bit_field2 = LoadMapBitField2(map);
Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2);
- // Bailout if receiver has slow elements.
+ // Bailout if slow receiver elements
GotoIf(
Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
if_false);
- // Check prototype chain if receiver does not have packed elements.
STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1));
STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1));
STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1));
- Node* holey_elements = Word32And(elements_kind, Int32Constant(1));
- GotoIf(Word32Equal(holey_elements, Int32Constant(0)), if_true);
- BranchIfPrototypesHaveNoElements(map, if_true, if_false);
+
+ // Check prototype chain if receiver does not have packed elements
+ Node* holey_elements = Word32And(elements_kind, int32_one);
+ Branch(Word32Equal(holey_elements, int32_zero), if_true, &check_prototype);
+
+ Bind(&check_prototype);
+ {
+ Label loop_body(this, &last_map);
+ Goto(&loop_body);
+ Bind(&loop_body);
+ Node* current_map = last_map.value();
+ Node* proto = LoadObjectField(current_map, Map::kPrototypeOffset);
+
+ // End loop
+ GotoIf(WordEqual(proto, NullConstant()), if_true);
+
+ // ASSERT: proto->IsHeapObject()
+ Node* proto_map = LoadMap(proto);
+
+ // Bailout if a Proxy, API Object, or JSValue wrapper found in prototype
+ // Because of this bailout, it's not necessary to check for interceptors or
+ // access checks on the prototype chain.
+ GotoIf(Int32LessThanOrEqual(LoadMapInstanceType(proto_map),
+ Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
+ if_false);
+
+ // Bailout if prototype contains non-empty elements
+ GotoUnless(WordEqual(LoadElements(proto), empty_elements), if_false);
+
+ last_map.Bind(proto_map);
+ Goto(&loop_body);
+ }
}
Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes,
@@ -3481,14 +3489,13 @@
return var_intptr_key.value();
}
-void CodeStubAssembler::EmitFastElementsBoundsCheck(Node* object,
- Node* elements,
- Node* intptr_key,
- Node* is_jsarray_condition,
- Label* miss) {
+// |is_jsarray| should be non-zero for JSArrays.
+void CodeStubAssembler::EmitBoundsCheck(Node* object, Node* elements,
+ Node* intptr_key, Node* is_jsarray,
+ Label* miss) {
Variable var_length(this, MachineRepresentation::kTagged);
Label if_array(this), length_loaded(this, &var_length);
- GotoIf(is_jsarray_condition, &if_array);
+ GotoUnless(WordEqual(is_jsarray, IntPtrConstant(0)), &if_array);
{
var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements)));
Goto(&length_loaded);
@@ -3505,20 +3512,18 @@
// |key| should be untagged (int32).
void CodeStubAssembler::EmitElementLoad(Node* object, Node* elements,
Node* elements_kind, Node* key,
- Node* is_jsarray_condition,
Label* if_hole, Label* rebox_double,
Variable* var_double_value,
- Label* unimplemented_elements_kind,
- Label* out_of_bounds, Label* miss) {
+ Label* miss) {
Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this),
- if_fast_double(this), if_fast_holey_double(this), if_nonfast(this),
- if_dictionary(this), unreachable(this);
+ if_fast_double(this), if_fast_holey_double(this),
+ unimplemented_elements_kind(this);
+ STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
GotoIf(
- IntPtrGreaterThan(elements_kind, IntPtrConstant(LAST_FAST_ELEMENTS_KIND)),
- &if_nonfast);
-
- EmitFastElementsBoundsCheck(object, elements, key, is_jsarray_condition,
- out_of_bounds);
+ IntPtrGreaterThanOrEqual(
+ elements_kind, IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
+ &if_typed_array);
+
int32_t kinds[] = {// Handled by if_fast_packed.
FAST_SMI_ELEMENTS, FAST_ELEMENTS,
// Handled by if_fast_holey.
@@ -3535,8 +3540,14 @@
&if_fast_double,
// FAST_HOLEY_DOUBLE_ELEMENTS
&if_fast_holey_double};
- Switch(elements_kind, unimplemented_elements_kind, kinds, labels,
+ Switch(elements_kind, &unimplemented_elements_kind, kinds, labels,
arraysize(kinds));
+ Bind(&unimplemented_elements_kind);
+ {
+ // Crash if we get here.
+ DebugBreak();
+ Goto(miss);
+ }
Bind(&if_fast_packed);
{
@@ -3582,39 +3593,6 @@
Goto(rebox_double);
}
- Bind(&if_nonfast);
- {
- STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
- GotoIf(IntPtrGreaterThanOrEqual(
- elements_kind,
- IntPtrConstant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
- &if_typed_array);
- GotoIf(IntPtrEqual(elements_kind, IntPtrConstant(DICTIONARY_ELEMENTS)),
- &if_dictionary);
- Goto(unimplemented_elements_kind);
- }
-
- Bind(&if_dictionary);
- {
- Comment("dictionary elements");
- Variable var_entry(this, MachineRepresentation::kWord32);
- Label if_found(this);
- NumberDictionaryLookup<SeededNumberDictionary>(elements, key, &if_found,
- &var_entry, if_hole);
- Bind(&if_found);
- // Check that the value is a data property.
- Node* details_index = EntryToIndex<SeededNumberDictionary>(
- var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex);
- Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index));
- Node* kind = BitFieldDecode<PropertyDetails::KindField>(details);
- // TODO(jkummerow): Support accessors without missing?
- GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss);
- // Finally, load the value.
- Node* value_index = EntryToIndex<SeededNumberDictionary>(
- var_entry.value(), SeededNumberDictionary::kEntryValueIndex);
- Return(LoadFixedArrayElement(elements, value_index));
- }
-
Bind(&if_typed_array);
{
Comment("typed elements");
@@ -3625,12 +3603,6 @@
Node* neutered_bit =
Word32And(bitfield, Int32Constant(JSArrayBuffer::WasNeutered::kMask));
GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), miss);
-
- // Bounds check.
- Node* length =
- SmiUntag(LoadObjectField(object, JSTypedArray::kLengthOffset));
- GotoUnless(UintPtrLessThan(key, length), out_of_bounds);
-
// Backing store = external_pointer + base_pointer.
Node* external_pointer =
LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
@@ -3739,22 +3711,13 @@
Node* elements = LoadElements(p->receiver);
Node* is_jsarray =
WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask));
- Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0));
+ EmitBoundsCheck(p->receiver, elements, key, is_jsarray, miss);
+ Label if_hole(this);
+
Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word);
- Label if_hole(this), unimplemented_elements_kind(this);
- Label* out_of_bounds = miss;
- EmitElementLoad(p->receiver, elements, elements_kind, key,
- is_jsarray_condition, &if_hole, &rebox_double,
- &var_double_value, &unimplemented_elements_kind,
- out_of_bounds, miss);
-
- Bind(&unimplemented_elements_kind);
- {
- // Smi handlers should only be installed for supported elements kinds.
- // Crash if we get here.
- DebugBreak();
- Goto(miss);
- }
+
+ EmitElementLoad(p->receiver, elements, elements_kind, key, &if_hole,
+ &rebox_double, &var_double_value, miss);
Bind(&if_hole);
{
@@ -3933,166 +3896,6 @@
}
}
-void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
- Variable var_index(this, MachineType::PointerRepresentation());
- Label if_index(this), if_key_is_not_number(this), if_index_name(this),
- if_unique_name(this), if_element_hole(this), if_oob(this), slow(this),
- stub_cache_miss(this), if_property_dictionary(this);
-
- Node* receiver = p->receiver;
- GotoIf(WordIsSmi(receiver), &slow);
- Node* receiver_map = LoadMap(receiver);
- Node* instance_type = LoadMapInstanceType(receiver_map);
- // Receivers requiring non-standard element accesses (interceptors, access
- // checks, strings and string wrappers, proxies) are handled in the runtime.
- GotoIf(Int32LessThanOrEqual(instance_type,
- Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
- &slow);
-
- // Check what kind of key we have.
- Node* key = p->name;
- var_index.Bind(TryToIntptr(key, &if_key_is_not_number));
- Goto(&if_index);
-
- Node* hash = nullptr;
- // TODO(jkummerow): Unify this with CodeStubAssembler::TryToName().
- Bind(&if_key_is_not_number);
- {
- Node* key_map = LoadMap(key);
- Node* key_instance_type = LoadMapInstanceType(key_map);
- // Jump to the runtime if key is neither String nor Symbol.
- GotoIf(Int32GreaterThan(key_instance_type,
- Int32Constant(LAST_UNIQUE_NAME_TYPE)),
- &slow);
- // Symbols are always unique names.
- GotoIf(Word32Equal(key_instance_type, Int32Constant(LAST_UNIQUE_NAME_TYPE)),
- &if_unique_name);
- // |key| is a String. Check if it has a cached array index.
- hash = LoadNameHashField(key);
- Node* contains_index =
- Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask));
- GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_index_name);
- // Otherwise, jump to the runtime if the string is not internalized.
- STATIC_ASSERT(kNotInternalizedTag != 0);
- Node* not_internalized =
- Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask));
- GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), &slow);
- Goto(&if_unique_name);
- }
-
- Bind(&if_index_name);
- {
- Comment("string key with cached array index");
- var_index.Bind(BitFieldDecode<String::ArrayIndexValueBits>(hash));
- Goto(&if_index);
- }
-
- Bind(&if_index);
- {
- Comment("integer index");
- Node* index = var_index.value();
- Node* elements = LoadElements(receiver);
- Node* bitfield2 = LoadMapBitField2(receiver_map);
- Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bitfield2);
- Node* is_jsarray_condition =
- Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE));
- Variable var_double_value(this, MachineRepresentation::kFloat64);
- Label rebox_double(this, &var_double_value);
-
- // Unimplemented elements kinds fall back to a runtime call.
- Label* unimplemented_elements_kind = &slow;
- IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
- EmitElementLoad(receiver, elements, elements_kind, index,
- is_jsarray_condition, &if_element_hole, &rebox_double,
- &var_double_value, unimplemented_elements_kind, &if_oob,
- &slow);
-
- Bind(&rebox_double);
- Return(AllocateHeapNumberWithValue(var_double_value.value()));
- }
-
- Bind(&if_oob);
- {
- Comment("out of bounds");
- Node* index = var_index.value();
- // Negative keys can't take the fast OOB path.
- GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), &slow);
- // Positive OOB indices are effectively the same as hole loads.
- Goto(&if_element_hole);
- }
-
- Bind(&if_element_hole);
- {
- Comment("found the hole");
- Label return_undefined(this);
- BranchIfPrototypesHaveNoElements(receiver_map, &return_undefined, &slow);
-
- Bind(&return_undefined);
- Return(UndefinedConstant());
- }
-
- Node* properties = nullptr;
- Bind(&if_unique_name);
- {
- Comment("key is unique name");
- // Check if the receiver has fast or slow properties.
- properties = LoadProperties(receiver);
- Node* properties_map = LoadMap(properties);
- GotoIf(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)),
- &if_property_dictionary);
-
- Comment("stub cache probe for fast property load");
- Variable var_handler(this, MachineRepresentation::kTagged);
- Label found_handler(this, &var_handler), stub_cache_miss(this);
- TryProbeStubCache(isolate()->load_stub_cache(), receiver, key,
- &found_handler, &var_handler, &stub_cache_miss);
- Bind(&found_handler);
- { HandleLoadICHandlerCase(p, var_handler.value(), &slow); }
-
- Bind(&stub_cache_miss);
- {
- Comment("KeyedLoadGeneric_miss");
- TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
- p->name, p->slot, p->vector);
- }
- }
-
- Bind(&if_property_dictionary);
- {
- Comment("dictionary property load");
- // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out
- // seeing global objects here (which would need special handling).
-
- Variable var_name_index(this, MachineRepresentation::kWord32);
- Label dictionary_found(this, &var_name_index);
- NameDictionaryLookup<NameDictionary>(properties, key, &dictionary_found,
- &var_name_index, &slow);
- Bind(&dictionary_found);
- {
- Variable var_details(this, MachineRepresentation::kWord32);
- Variable var_value(this, MachineRepresentation::kTagged);
- LoadPropertyFromNameDictionary(properties, var_name_index.value(),
- &var_details, &var_value);
- Node* kind =
- BitFieldDecode<PropertyDetails::KindField>(var_details.value());
- // TODO(jkummerow): Support accessors without missing?
- GotoUnless(Word32Equal(kind, Int32Constant(kData)), &slow);
- IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(),
- 1);
- Return(var_value.value());
- }
- }
-
- Bind(&slow);
- {
- Comment("KeyedLoadGeneric_slow");
- IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1);
- // TODO(jkummerow): Should we use the GetProperty TF stub instead?
- TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver,
- p->name);
- }
-}
-
void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) {
Label try_handler(this), miss(this);
Node* weak_cell =
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/ic/handler-compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698