Commit d46bd852 authored by Suraj Sharma's avatar Suraj Sharma Committed by Commit Bot

[ic] Migrate Code-based handlers to use data driven handler.

All usage of KeyedLoadIC_Slow, HasIC_Slow, StoreInArrayLiteralIC_Slow
and KeyedStoreIC_Slow now use data driven handlers

Bug: v8:9779
Change-Id: Idd888c5c10b462a5fe155ba0add36f95169bd76d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1895988Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Commit-Queue: Suraj Sharma <surshar@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#64918}
parent e6acd1ae
......@@ -215,9 +215,7 @@ namespace internal {
\
/* Handlers */ \
TFH(KeyedLoadIC_PolymorphicName, LoadWithVector) \
TFH(KeyedLoadIC_Slow, LoadWithVector) \
TFH(KeyedStoreIC_Megamorphic, Store) \
TFH(KeyedStoreIC_Slow, StoreWithVector) \
TFH(LoadGlobalIC_NoFeedback, LoadGlobalNoFeedback) \
TFH(LoadIC_FunctionPrototype, LoadWithVector) \
TFH(LoadIC_StringLength, LoadWithVector) \
......@@ -225,25 +223,16 @@ namespace internal {
TFH(LoadIC_NoFeedback, LoadNoFeedback) \
TFH(StoreGlobalIC_Slow, StoreWithVector) \
TFH(StoreIC_NoFeedback, Store) \
TFH(StoreInArrayLiteralIC_Slow, StoreWithVector) \
TFH(KeyedLoadIC_SloppyArguments, LoadWithVector) \
TFH(LoadIndexedInterceptorIC, LoadWithVector) \
TFH(KeyedStoreIC_SloppyArguments_Standard, StoreWithVector) \
TFH(KeyedStoreIC_SloppyArguments_GrowNoTransitionHandleCOW, StoreWithVector) \
TFH(KeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB, StoreWithVector) \
TFH(KeyedStoreIC_SloppyArguments_NoTransitionHandleCOW, StoreWithVector) \
TFH(StoreInArrayLiteralIC_Slow_Standard, StoreWithVector) \
TFH(StoreFastElementIC_Standard, StoreWithVector) \
TFH(StoreFastElementIC_GrowNoTransitionHandleCOW, StoreWithVector) \
TFH(StoreFastElementIC_NoTransitionIgnoreOOB, StoreWithVector) \
TFH(StoreFastElementIC_NoTransitionHandleCOW, StoreWithVector) \
TFH(StoreInArrayLiteralIC_Slow_GrowNoTransitionHandleCOW, StoreWithVector) \
TFH(StoreInArrayLiteralIC_Slow_NoTransitionIgnoreOOB, StoreWithVector) \
TFH(StoreInArrayLiteralIC_Slow_NoTransitionHandleCOW, StoreWithVector) \
TFH(KeyedStoreIC_Slow_Standard, StoreWithVector) \
TFH(KeyedStoreIC_Slow_GrowNoTransitionHandleCOW, StoreWithVector) \
TFH(KeyedStoreIC_Slow_NoTransitionIgnoreOOB, StoreWithVector) \
TFH(KeyedStoreIC_Slow_NoTransitionHandleCOW, StoreWithVector) \
TFH(ElementsTransitionAndStore_Standard, StoreTransition) \
TFH(ElementsTransitionAndStore_GrowNoTransitionHandleCOW, StoreTransition) \
TFH(ElementsTransitionAndStore_NoTransitionIgnoreOOB, StoreTransition) \
......@@ -251,7 +240,6 @@ namespace internal {
TFH(KeyedHasIC_PolymorphicName, LoadWithVector) \
TFH(KeyedHasIC_SloppyArguments, LoadWithVector) \
TFH(HasIndexedInterceptorIC, LoadWithVector) \
TFH(HasIC_Slow, LoadWithVector) \
\
/* Microtask helpers */ \
TFS(EnqueueMicrotask, kMicrotask) \
......
......@@ -20,8 +20,6 @@ class HandlerBuiltinsAssembler : public CodeStubAssembler {
protected:
void Generate_KeyedStoreIC_SloppyArguments();
void Generate_KeyedStoreIC_Slow();
void Generate_StoreInArrayLiteralIC_Slow();
// Essentially turns runtime elements kinds (TNode<Int32T>) into
// compile-time types (int) by dispatching over the runtime type and
......@@ -202,14 +200,6 @@ TF_BUILTIN(LoadIC_StringWrapperLength, CodeStubAssembler) {
Return(LoadStringLengthAsSmi(string));
}
TF_BUILTIN(KeyedLoadIC_Slow, CodeStubAssembler) {
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
TNode<Object> name = CAST(Parameter(Descriptor::kName));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
}
void Builtins::Generate_KeyedStoreIC_Megamorphic(
compiler::CodeAssemblerState* state) {
KeyedStoreGenericGenerator::Generate(state);
......@@ -220,74 +210,6 @@ void Builtins::Generate_StoreIC_NoFeedback(
StoreICNoFeedbackGenerator::Generate(state);
}
// TODO(mythria): Create a Descriptor without feedback vector and slot
// parameters.
void HandlerBuiltinsAssembler::Generate_KeyedStoreIC_Slow() {
using Descriptor = StoreWithVectorDescriptor;
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
TNode<Object> name = CAST(Parameter(Descriptor::kName));
TNode<Object> value = CAST(Parameter(Descriptor::kValue));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
// The slow case calls into the runtime to complete the store without causing
// an IC miss that would otherwise cause a transition to the generic stub.
TailCallRuntime(Runtime::kKeyedStoreIC_Slow, context, value, receiver, name);
}
TF_BUILTIN(KeyedStoreIC_Slow, HandlerBuiltinsAssembler) {
Generate_KeyedStoreIC_Slow();
}
TF_BUILTIN(KeyedStoreIC_Slow_Standard, HandlerBuiltinsAssembler) {
Generate_KeyedStoreIC_Slow();
}
TF_BUILTIN(KeyedStoreIC_Slow_GrowNoTransitionHandleCOW,
HandlerBuiltinsAssembler) {
Generate_KeyedStoreIC_Slow();
}
TF_BUILTIN(KeyedStoreIC_Slow_NoTransitionIgnoreOOB, HandlerBuiltinsAssembler) {
Generate_KeyedStoreIC_Slow();
}
TF_BUILTIN(KeyedStoreIC_Slow_NoTransitionHandleCOW, HandlerBuiltinsAssembler) {
Generate_KeyedStoreIC_Slow();
}
void HandlerBuiltinsAssembler::Generate_StoreInArrayLiteralIC_Slow() {
using Descriptor = StoreWithVectorDescriptor;
TNode<JSArray> array = CAST(Parameter(Descriptor::kReceiver));
TNode<Object> index = CAST(Parameter(Descriptor::kName));
TNode<Object> value = CAST(Parameter(Descriptor::kValue));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TailCallRuntime(Runtime::kStoreInArrayLiteralIC_Slow, context, value, array,
index);
}
TF_BUILTIN(StoreInArrayLiteralIC_Slow, HandlerBuiltinsAssembler) {
Generate_StoreInArrayLiteralIC_Slow();
}
TF_BUILTIN(StoreInArrayLiteralIC_Slow_Standard, HandlerBuiltinsAssembler) {
Generate_StoreInArrayLiteralIC_Slow();
}
TF_BUILTIN(StoreInArrayLiteralIC_Slow_GrowNoTransitionHandleCOW,
HandlerBuiltinsAssembler) {
Generate_StoreInArrayLiteralIC_Slow();
}
TF_BUILTIN(StoreInArrayLiteralIC_Slow_NoTransitionIgnoreOOB,
HandlerBuiltinsAssembler) {
Generate_StoreInArrayLiteralIC_Slow();
}
TF_BUILTIN(StoreInArrayLiteralIC_Slow_NoTransitionHandleCOW,
HandlerBuiltinsAssembler) {
Generate_StoreInArrayLiteralIC_Slow();
}
// All possible fast-to-fast transitions. Transitions to dictionary mode are not
// handled by ElementsTransitionAndStore.
#define ELEMENTS_KIND_TRANSITIONS(V) \
......@@ -676,13 +598,5 @@ TF_BUILTIN(HasIndexedInterceptorIC, CodeStubAssembler) {
vector);
}
TF_BUILTIN(HasIC_Slow, CodeStubAssembler) {
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
TNode<Object> name = CAST(Parameter(Descriptor::kName));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TailCallRuntime(Runtime::kHasProperty, context, receiver, name);
}
} // namespace internal
} // namespace v8
......@@ -122,53 +122,6 @@ Callable CodeFactory::KeyedStoreIC_SloppyArguments(Isolate* isolate,
return isolate->builtins()->CallableFor(isolate, builtin_index);
}
Callable CodeFactory::KeyedStoreIC_Slow(Isolate* isolate,
KeyedAccessStoreMode mode) {
Builtins::Name builtin_index;
switch (mode) {
case STANDARD_STORE:
builtin_index = Builtins::kKeyedStoreIC_Slow_Standard;
break;
case STORE_AND_GROW_HANDLE_COW:
builtin_index = Builtins::kKeyedStoreIC_Slow_GrowNoTransitionHandleCOW;
break;
case STORE_IGNORE_OUT_OF_BOUNDS:
builtin_index = Builtins::kKeyedStoreIC_Slow_NoTransitionIgnoreOOB;
break;
case STORE_HANDLE_COW:
builtin_index = Builtins::kKeyedStoreIC_Slow_NoTransitionHandleCOW;
break;
default:
UNREACHABLE();
}
return isolate->builtins()->CallableFor(isolate, builtin_index);
}
Callable CodeFactory::StoreInArrayLiteralIC_Slow(Isolate* isolate,
KeyedAccessStoreMode mode) {
Builtins::Name builtin_index;
switch (mode) {
case STANDARD_STORE:
builtin_index = Builtins::kStoreInArrayLiteralIC_Slow_Standard;
break;
case STORE_AND_GROW_HANDLE_COW:
builtin_index =
Builtins::kStoreInArrayLiteralIC_Slow_GrowNoTransitionHandleCOW;
break;
case STORE_IGNORE_OUT_OF_BOUNDS:
builtin_index =
Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionIgnoreOOB;
break;
case STORE_HANDLE_COW:
builtin_index =
Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionHandleCOW;
break;
default:
UNREACHABLE();
}
return isolate->builtins()->CallableFor(isolate, builtin_index);
}
Callable CodeFactory::ElementsTransitionAndStore(Isolate* isolate,
KeyedAccessStoreMode mode) {
Builtins::Name builtin_index;
......
......@@ -42,10 +42,6 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable KeyedStoreIC_SloppyArguments(Isolate* isolate,
KeyedAccessStoreMode mode);
static Callable KeyedStoreIC_Slow(Isolate* isolate,
KeyedAccessStoreMode mode);
static Callable StoreInArrayLiteralIC_Slow(Isolate* isolate,
KeyedAccessStoreMode mode);
static Callable ElementsTransitionAndStore(Isolate* isolate,
KeyedAccessStoreMode mode);
static Callable StoreFastElementIC(Isolate* isolate,
......
......@@ -1564,6 +1564,9 @@ void AccessorAssembler::HandleStoreICProtoHandler(
GotoIf(Word32Equal(handler_kind, Int32Constant(StoreHandler::kNormal)),
&if_add_normal);
GotoIf(Word32Equal(handler_kind, Int32Constant(StoreHandler::kSlow)),
&if_slow);
TNode<MaybeObject> maybe_holder = LoadHandlerDataField(handler, 1);
CSA_ASSERT(this, IsWeakOrCleared(maybe_holder));
TNode<HeapObject> holder = GetHeapObjectAssumeWeak(maybe_holder, miss);
......@@ -1581,9 +1584,6 @@ void AccessorAssembler::HandleStoreICProtoHandler(
GotoIf(Word32Equal(handler_kind, Int32Constant(StoreHandler::kApiSetter)),
&if_api_setter);
GotoIf(Word32Equal(handler_kind, Int32Constant(StoreHandler::kSlow)),
&if_slow);
GotoIf(Word32Equal(handler_kind, Int32Constant(StoreHandler::kInterceptor)),
&if_interceptor);
......
......@@ -137,8 +137,10 @@ Handle<Smi> StoreHandler::StoreInterceptor(Isolate* isolate) {
return handle(Smi::FromInt(config), isolate);
}
Handle<Smi> StoreHandler::StoreSlow(Isolate* isolate) {
int config = KindBits::encode(kSlow);
Handle<Smi> StoreHandler::StoreSlow(Isolate* isolate,
KeyedAccessStoreMode store_mode) {
int config =
KindBits::encode(kSlow) | KeyedAccessStoreModeBits::encode(store_mode);
return handle(Smi::FromInt(config), isolate);
}
......
......@@ -176,6 +176,19 @@ KeyedAccessLoadMode LoadHandler::GetKeyedAccessLoadMode(MaybeObject handler) {
return STANDARD_LOAD;
}
// static
KeyedAccessStoreMode StoreHandler::GetKeyedAccessStoreMode(
MaybeObject handler) {
DisallowHeapAllocation no_gc;
if (handler->IsSmi()) {
int const raw_handler = handler.ToSmi().value();
KeyedAccessStoreMode store_mode =
KeyedAccessStoreModeBits::decode(raw_handler);
return store_mode;
}
return STANDARD_STORE;
}
// static
Handle<Object> StoreHandler::StoreElementTransition(
Isolate* isolate, Handle<Map> receiver_map, Handle<Map> transition,
......
......@@ -224,6 +224,13 @@ class StoreHandler final : public DataHandler {
// Index of a value entry in the descriptor array.
using DescriptorBits =
LookupOnReceiverBits::Next<unsigned, kDescriptorIndexBitCount>;
//
// Encodes the bits when StoreSlow contains KeyedAccessStoreMode.
//
using KeyedAccessStoreModeBits =
DescriptorBits::Next<KeyedAccessStoreMode, 2>;
//
// Encoding when KindBits contains kTransitionToConstant.
//
......@@ -291,11 +298,15 @@ class StoreHandler final : public DataHandler {
static inline Handle<Smi> StoreInterceptor(Isolate* isolate);
// Creates a Smi-handler for storing a property.
static inline Handle<Smi> StoreSlow(Isolate* isolate);
static inline Handle<Smi> StoreSlow(
Isolate* isolate, KeyedAccessStoreMode store_mode = STANDARD_STORE);
// Creates a Smi-handler for storing a property on a proxy.
static inline Handle<Smi> StoreProxy(Isolate* isolate);
// Decodes the KeyedAccessStoreMode from a {handler}.
static KeyedAccessStoreMode GetKeyedAccessStoreMode(MaybeObject handler);
private:
static inline Handle<Smi> StoreField(Isolate* isolate, Kind kind,
int descriptor, FieldIndex field_index,
......
......@@ -1133,13 +1133,12 @@ Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map,
InstanceType instance_type = receiver_map->instance_type();
if (instance_type < FIRST_NONSTRING_TYPE) {
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedStringDH);
if (IsAnyHas()) return BUILTIN_CODE(isolate(), HasIC_Slow);
if (IsAnyHas()) return LoadHandler::LoadSlow(isolate());
return LoadHandler::LoadIndexedString(isolate(), load_mode);
}
if (instance_type < FIRST_JS_RECEIVER_TYPE) {
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_SlowStub);
return IsAnyHas() ? BUILTIN_CODE(isolate(), HasIC_Slow)
: BUILTIN_CODE(isolate(), KeyedLoadIC_Slow);
return LoadHandler::LoadSlow(isolate());
}
if (instance_type == JS_PROXY_TYPE) {
return LoadHandler::LoadProxy(isolate());
......@@ -1871,7 +1870,7 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
}
// TODO(ishell): move to StoreHandler::StoreElement().
Handle<Code> code;
Handle<Object> code;
if (receiver_map->has_sloppy_arguments_elements()) {
// TODO(jgruber): Update counter name.
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_KeyedStoreSloppyArgumentsStub);
......@@ -1887,18 +1886,16 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
} else if (IsStoreInArrayLiteralICKind(kind())) {
// TODO(jgruber): Update counter name.
TRACE_HANDLER_STATS(isolate(), StoreInArrayLiteralIC_SlowStub);
code =
CodeFactory::StoreInArrayLiteralIC_Slow(isolate(), store_mode).code();
return StoreHandler::StoreSlow(isolate(), store_mode);
} else {
// TODO(jgruber): Update counter name.
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
DCHECK(DICTIONARY_ELEMENTS == receiver_map->elements_kind() ||
receiver_map->has_frozen_elements());
code = CodeFactory::KeyedStoreIC_Slow(isolate(), store_mode).code();
code = StoreHandler::StoreSlow(isolate(), store_mode);
}
if (IsStoreInArrayLiteralICKind(kind())) return code;
Handle<Object> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (validity_cell->IsSmi()) {
......
......@@ -1105,14 +1105,6 @@ bool BuiltinHasKeyedAccessStoreMode(int builtin_index) {
case Builtins::kStoreFastElementIC_GrowNoTransitionHandleCOW:
case Builtins::kStoreFastElementIC_NoTransitionIgnoreOOB:
case Builtins::kStoreFastElementIC_NoTransitionHandleCOW:
case Builtins::kStoreInArrayLiteralIC_Slow_Standard:
case Builtins::kStoreInArrayLiteralIC_Slow_GrowNoTransitionHandleCOW:
case Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionIgnoreOOB:
case Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionHandleCOW:
case Builtins::kKeyedStoreIC_Slow_Standard:
case Builtins::kKeyedStoreIC_Slow_GrowNoTransitionHandleCOW:
case Builtins::kKeyedStoreIC_Slow_NoTransitionIgnoreOOB:
case Builtins::kKeyedStoreIC_Slow_NoTransitionHandleCOW:
case Builtins::kElementsTransitionAndStore_Standard:
case Builtins::kElementsTransitionAndStore_GrowNoTransitionHandleCOW:
case Builtins::kElementsTransitionAndStore_NoTransitionIgnoreOOB:
......@@ -1128,26 +1120,18 @@ KeyedAccessStoreMode KeyedAccessStoreModeForBuiltin(int builtin_index) {
DCHECK(BuiltinHasKeyedAccessStoreMode(builtin_index));
switch (builtin_index) {
case Builtins::kKeyedStoreIC_SloppyArguments_Standard:
case Builtins::kStoreInArrayLiteralIC_Slow_Standard:
case Builtins::kKeyedStoreIC_Slow_Standard:
case Builtins::kStoreFastElementIC_Standard:
case Builtins::kElementsTransitionAndStore_Standard:
return STANDARD_STORE;
case Builtins::kKeyedStoreIC_SloppyArguments_GrowNoTransitionHandleCOW:
case Builtins::kStoreInArrayLiteralIC_Slow_GrowNoTransitionHandleCOW:
case Builtins::kKeyedStoreIC_Slow_GrowNoTransitionHandleCOW:
case Builtins::kStoreFastElementIC_GrowNoTransitionHandleCOW:
case Builtins::kElementsTransitionAndStore_GrowNoTransitionHandleCOW:
return STORE_AND_GROW_HANDLE_COW;
case Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB:
case Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionIgnoreOOB:
case Builtins::kKeyedStoreIC_Slow_NoTransitionIgnoreOOB:
case Builtins::kStoreFastElementIC_NoTransitionIgnoreOOB:
case Builtins::kElementsTransitionAndStore_NoTransitionIgnoreOOB:
return STORE_IGNORE_OUT_OF_BOUNDS;
case Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionHandleCOW:
case Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionHandleCOW:
case Builtins::kKeyedStoreIC_Slow_NoTransitionHandleCOW:
case Builtins::kStoreFastElementIC_NoTransitionHandleCOW:
case Builtins::kElementsTransitionAndStore_NoTransitionHandleCOW:
return STORE_HANDLE_COW;
......@@ -1174,14 +1158,29 @@ KeyedAccessStoreMode FeedbackNexus::GetKeyedAccessStoreMode() const {
if (maybe_code_handler.object()->IsStoreHandler()) {
Handle<StoreHandler> data_handler =
Handle<StoreHandler>::cast(maybe_code_handler.object());
handler = handle(Code::cast(data_handler->smi_handler()),
vector().GetIsolate());
if ((data_handler->smi_handler()).IsSmi()) {
// Decode the KeyedAccessStoreMode information from the Handler.
mode = StoreHandler::GetKeyedAccessStoreMode(
MaybeObject::FromObject(data_handler->smi_handler()));
if (mode != STANDARD_STORE) return mode;
continue;
} else {
handler = handle(Code::cast(data_handler->smi_handler()),
vector().GetIsolate());
}
} else if (maybe_code_handler.object()->IsSmi()) {
// Skip proxy handlers and the slow handler.
// Skip for Proxy Handlers.
if (*(maybe_code_handler.object()) ==
*StoreHandler::StoreProxy(GetIsolate()))
continue;
// Verify it is Slow handler
DCHECK(*(maybe_code_handler.object()) ==
*StoreHandler::StoreProxy(GetIsolate()) ||
*(maybe_code_handler.object()) ==
*StoreHandler::StoreSlow(GetIsolate()));
// Decode the KeyedAccessStoreMode information from the Handler.
mode = StoreHandler::GetKeyedAccessStoreMode(*maybe_code_handler);
if (mode != STANDARD_STORE) return mode;
continue;
} else {
// Element store without prototype chain check.
......
......@@ -2723,7 +2723,7 @@ TEST(CheckCodeNames) {
CHECK(ValidateSnapshot(snapshot));
const char* builtin_path1[] = {"::(GC roots)", "::(Builtins)",
"::(KeyedLoadIC_Slow builtin)"};
"::(KeyedLoadIC_PolymorphicName builtin)"};
const v8::HeapGraphNode* node = GetNodeByPath(
env->GetIsolate(), snapshot, builtin_path1, arraysize(builtin_path1));
CHECK(node);
......
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