Commit 391c967c authored by jkummerow's avatar jkummerow Committed by Commit bot

[StoreIC] Use StoreIC_Uninitialized for 0->PRE transitions

Avoiding runtime call overhead.

BUG=v8:5269

Review-Url: https://codereview.chromium.org/2717203002
Cr-Commit-Position: refs/heads/master@{#43799}
parent c92f41d0
......@@ -70,6 +70,16 @@ void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict(
KeyedStoreGenericGenerator::Generate(state, STRICT);
}
void Builtins::Generate_StoreIC_Uninitialized(
compiler::CodeAssemblerState* state) {
StoreICUninitializedGenerator::Generate(state, SLOPPY);
}
void Builtins::Generate_StoreICStrict_Uninitialized(
compiler::CodeAssemblerState* state) {
StoreICUninitializedGenerator::Generate(state, STRICT);
}
TF_BUILTIN(KeyedStoreIC_Miss, CodeStubAssembler) {
typedef StoreWithVectorDescriptor Descriptor;
......
......@@ -247,6 +247,9 @@ class Isolate;
TFS(LoadIC_Uninitialized, BUILTIN, kNoExtraICState, LoadWithVector, 1) \
TFS(StoreIC_Miss, BUILTIN, kNoExtraICState, StoreWithVector, 1) \
ASH(StoreIC_Setter_ForDeopt, BUILTIN, kNoExtraICState) \
TFS(StoreIC_Uninitialized, BUILTIN, kNoExtraICState, StoreWithVector, 1) \
TFS(StoreICStrict_Uninitialized, BUILTIN, kNoExtraICState, StoreWithVector, \
1) \
\
/* Built-in functions for Javascript */ \
/* Special internal builtins */ \
......
......@@ -123,6 +123,15 @@ Callable CodeFactory::StoreICInOptimizedCode(Isolate* isolate,
StoreWithVectorDescriptor(isolate));
}
// static
Callable CodeFactory::StoreIC_Uninitialized(Isolate* isolate,
LanguageMode language_mode) {
return Callable(language_mode == STRICT
? isolate->builtins()->StoreICStrict_Uninitialized()
: isolate->builtins()->StoreIC_Uninitialized(),
StoreWithVectorDescriptor(isolate));
}
Callable CodeFactory::StoreOwnIC(Isolate* isolate) {
// TODO(ishell): Currently we use StoreOwnIC only for storing properties that
// already exist in the boilerplate therefore we can use StoreIC.
......
......@@ -56,6 +56,7 @@ class V8_EXPORT_PRIVATE CodeFactory final {
TailCallMode tail_call_mode = TailCallMode::kDisallow);
static Callable StoreIC(Isolate* isolate, LanguageMode mode);
static Callable StoreICInOptimizedCode(Isolate* isolate, LanguageMode mode);
static Callable StoreIC_Uninitialized(Isolate* isolate, LanguageMode mode);
static Callable StoreOwnIC(Isolate* isolate);
static Callable StoreOwnICInOptimizedCode(Isolate* isolate);
static Callable KeyedStoreIC(Isolate* isolate, LanguageMode mode);
......
......@@ -2041,10 +2041,12 @@ void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
}
}
void AccessorAssembler::StoreIC(const StoreICParameters* p) {
void AccessorAssembler::StoreIC(const StoreICParameters* p,
LanguageMode language_mode) {
Variable var_handler(this, MachineRepresentation::kTagged);
Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred),
try_megamorphic(this, Label::kDeferred), miss(this, Label::kDeferred);
try_megamorphic(this, Label::kDeferred),
try_uninitialized(this, Label::kDeferred), miss(this, Label::kDeferred);
Node* receiver_map = LoadReceiverMap(p->receiver);
GotoIf(IsDeprecatedMap(receiver_map), &miss);
......@@ -2074,11 +2076,21 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
{
// Check megamorphic case.
GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
&miss);
&try_uninitialized);
TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name,
&if_handler, &var_handler, &miss);
}
Bind(&try_uninitialized);
{
// Check uninitialized case.
GotoIfNot(
WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
&miss);
TailCallStub(CodeFactory::StoreIC_Uninitialized(isolate(), language_mode),
p->context, p->receiver, p->name, p->value, p->slot,
p->vector);
}
Bind(&miss);
{
TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot,
......@@ -2376,8 +2388,7 @@ void AccessorAssembler::GenerateStoreIC(LanguageMode language_mode) {
Node* context = Parameter(Descriptor::kContext);
StoreICParameters p(context, receiver, name, value, slot, vector);
// Current StoreIC dispatcher does not depend on the language mode.
StoreIC(&p);
StoreIC(&p, language_mode);
}
void AccessorAssembler::GenerateStoreICTrampoline(LanguageMode language_mode) {
......
......@@ -112,7 +112,7 @@ class AccessorAssembler : public CodeStubAssembler {
void LoadGlobalIC(const LoadICParameters* p, TypeofMode typeof_mode);
void KeyedLoadIC(const LoadICParameters* p);
void KeyedLoadICGeneric(const LoadICParameters* p);
void StoreIC(const StoreICParameters* p);
void StoreIC(const StoreICParameters* p, LanguageMode language_mode);
void KeyedStoreIC(const StoreICParameters* p, LanguageMode language_mode);
// IC dispatcher behavior.
......
......@@ -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(&not_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
......@@ -20,6 +20,12 @@ class KeyedStoreGenericGenerator {
LanguageMode language_mode);
};
class StoreICUninitializedGenerator {
public:
static void Generate(compiler::CodeAssemblerState* state,
LanguageMode language_mode);
};
} // namespace internal
} // namespace v8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment