| Index: src/ic/keyed-store-generic.cc
|
| diff --git a/src/ic/keyed-store-generic.cc b/src/ic/keyed-store-generic.cc
|
| index 6d9b5cb538b996ec52fbfffe8693d6c765989d1b..165aa14a342e101179c5e2e48545f67815f557a2 100644
|
| --- a/src/ic/keyed-store-generic.cc
|
| +++ b/src/ic/keyed-store-generic.cc
|
| @@ -24,6 +24,8 @@ class KeyedStoreGenericAssembler : public AccessorAssembler {
|
|
|
| void KeyedStoreGeneric(LanguageMode language_mode);
|
|
|
| + void StoreIC_Uninitialized(LanguageMode language_mode);
|
| +
|
| private:
|
| enum UpdateLength {
|
| kDontChangeLength,
|
| @@ -31,13 +33,16 @@ class KeyedStoreGenericAssembler : public AccessorAssembler {
|
| kBumpLengthWithGap
|
| };
|
|
|
| + enum UseStubCache { kUseStubCache, kDontUseStubCache };
|
| +
|
| void EmitGenericElementStore(Node* receiver, Node* receiver_map,
|
| Node* instance_type, Node* intptr_index,
|
| Node* value, Node* context, Label* slow);
|
|
|
| void EmitGenericPropertyStore(Node* receiver, Node* receiver_map,
|
| const StoreICParameters* p, Label* slow,
|
| - LanguageMode language_mode);
|
| + LanguageMode language_mode,
|
| + UseStubCache use_stub_cache = kUseStubCache);
|
|
|
| void BranchIfPrototypesHaveNonFastElements(Node* receiver_map,
|
| Label* non_fast_elements,
|
| @@ -87,6 +92,12 @@ void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state,
|
| assembler.KeyedStoreGeneric(language_mode);
|
| }
|
|
|
| +void StoreICUninitializedGenerator::Generate(
|
| + compiler::CodeAssemblerState* state, LanguageMode language_mode) {
|
| + KeyedStoreGenericAssembler assembler(state);
|
| + assembler.StoreIC_Uninitialized(language_mode);
|
| +}
|
| +
|
| void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements(
|
| Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) {
|
| Variable var_map(this, MachineRepresentation::kTagged);
|
| @@ -738,7 +749,7 @@ void KeyedStoreGenericAssembler::OverwriteExistingFastProperty(
|
|
|
| void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
|
| Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow,
|
| - LanguageMode language_mode) {
|
| + LanguageMode language_mode, UseStubCache use_stub_cache) {
|
| Variable var_accessor_pair(this, MachineRepresentation::kTagged);
|
| Variable var_accessor_holder(this, MachineRepresentation::kTagged);
|
| Label stub_cache(this), fast_properties(this), dictionary_properties(this),
|
| @@ -756,7 +767,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
|
| Label descriptor_found(this);
|
| Variable var_name_index(this, MachineType::PointerRepresentation());
|
| // TODO(jkummerow): Maybe look for existing map transitions?
|
| - Label* notfound = &stub_cache;
|
| + Label* notfound = use_stub_cache == kUseStubCache ? &stub_cache : slow;
|
| DescriptorLookup(p->name, descriptors, bitfield3, &descriptor_found,
|
| &var_name_index, notfound);
|
|
|
| @@ -819,6 +830,13 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
|
|
|
| Bind(¬_found);
|
| {
|
| + Label extensible(this);
|
| + GotoIf(IsPrivateSymbol(p->name), &extensible);
|
| + Node* bitfield2 = LoadMapBitField2(receiver_map);
|
| + Branch(IsSetWord32(bitfield2, 1 << Map::kIsExtensible), &extensible,
|
| + slow);
|
| +
|
| + Bind(&extensible);
|
| LookupPropertyOnPrototypeChain(receiver_map, p->name, &accessor,
|
| &var_accessor_pair, &var_accessor_holder,
|
| &readonly, slow);
|
| @@ -871,8 +889,8 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
|
| }
|
| }
|
|
|
| - Bind(&stub_cache);
|
| - {
|
| + if (use_stub_cache == kUseStubCache) {
|
| + Bind(&stub_cache);
|
| Comment("stub cache probe");
|
| Variable var_handler(this, MachineRepresentation::kTagged);
|
| Label found_handler(this, &var_handler), stub_cache_miss(this);
|
| @@ -941,5 +959,47 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) {
|
| }
|
| }
|
|
|
| +void KeyedStoreGenericAssembler::StoreIC_Uninitialized(
|
| + LanguageMode language_mode) {
|
| + typedef StoreWithVectorDescriptor Descriptor;
|
| +
|
| + Node* receiver = Parameter(Descriptor::kReceiver);
|
| + Node* name = Parameter(Descriptor::kName);
|
| + Node* value = Parameter(Descriptor::kValue);
|
| + Node* slot = Parameter(Descriptor::kSlot);
|
| + Node* vector = Parameter(Descriptor::kVector);
|
| + Node* context = Parameter(Descriptor::kContext);
|
| +
|
| + Label miss(this);
|
| +
|
| + GotoIf(TaggedIsSmi(receiver), &miss);
|
| + 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_SPECIAL_RECEIVER_TYPE)),
|
| + &miss);
|
| +
|
| + // Optimistically write the state transition to the vector.
|
| + StoreFixedArrayElement(vector, slot,
|
| + LoadRoot(Heap::kpremonomorphic_symbolRootIndex),
|
| + SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
|
| +
|
| + StoreICParameters p(context, receiver, name, value, slot, vector);
|
| + EmitGenericPropertyStore(receiver, receiver_map, &p, &miss, language_mode,
|
| + kDontUseStubCache);
|
| +
|
| + Bind(&miss);
|
| + {
|
| + // Undo the optimistic state transition.
|
| + StoreFixedArrayElement(vector, slot,
|
| + LoadRoot(Heap::kuninitialized_symbolRootIndex),
|
| + SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
|
| + TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector,
|
| + receiver, name);
|
| + }
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace v8
|
|
|