Commit ac96607b authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[nojit] Move remaining IC stubs to builtins

This CL moves the two remaining IC stubs to builtins, generating a
dedicated builtin for each KeyedAccessStoreMode variant.

Bug: v8:7777
Change-Id: I540b3c3437adb94094771a19713e71ec8a349553
Reviewed-on: https://chromium-review.googlesource.com/c/1346095Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57719}
parent 9f19d97d
......@@ -222,6 +222,10 @@ namespace internal {
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) \
......@@ -229,6 +233,10 @@ namespace internal {
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) \
TFH(ElementsTransitionAndStore_NoTransitionHandleCOW, StoreTransition) \
\
/* Microtask helpers */ \
TFS(EnqueueMicrotask, kMicrotask) \
......
......@@ -21,6 +21,24 @@ class HandlerBuiltinsAssembler : public CodeStubAssembler {
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
// emitting a specialized copy of the given case function for each elements
// kind. Use with caution. This produces a *lot* of code.
typedef std::function<void(ElementsKind)> ElementsKindSwitchCase;
void DispatchByElementsKind(TNode<Int32T> elements_kind,
const ElementsKindSwitchCase& case_function);
// Dispatches over all possible combinations of {from,to} elements kinds.
typedef std::function<void(ElementsKind, ElementsKind)>
ElementsKindTransitionSwitchCase;
void DispatchForElementsKindTransition(
TNode<Int32T> from_kind, TNode<Int32T> to_kind,
const ElementsKindTransitionSwitchCase& case_function);
void Generate_ElementsTransitionAndStore(KeyedAccessStoreMode store_mode);
void Generate_StoreFastElementIC(KeyedAccessStoreMode store_mode);
};
TF_BUILTIN(LoadIC_StringLength, CodeStubAssembler) {
......@@ -121,6 +139,230 @@ TF_BUILTIN(StoreInArrayLiteralIC_Slow_NoTransitionHandleCOW,
Generate_StoreInArrayLiteralIC_Slow();
}
// All possible fast-to-fast transitions. Transitions to dictionary mode are not
// handled by ElementsTransitionAndStore.
#define ELEMENTS_KIND_TRANSITIONS(V) \
V(PACKED_SMI_ELEMENTS, HOLEY_SMI_ELEMENTS) \
V(PACKED_SMI_ELEMENTS, PACKED_DOUBLE_ELEMENTS) \
V(PACKED_SMI_ELEMENTS, HOLEY_DOUBLE_ELEMENTS) \
V(PACKED_SMI_ELEMENTS, PACKED_ELEMENTS) \
V(PACKED_SMI_ELEMENTS, HOLEY_ELEMENTS) \
V(HOLEY_SMI_ELEMENTS, HOLEY_DOUBLE_ELEMENTS) \
V(HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS) \
V(PACKED_DOUBLE_ELEMENTS, HOLEY_DOUBLE_ELEMENTS) \
V(PACKED_DOUBLE_ELEMENTS, PACKED_ELEMENTS) \
V(PACKED_DOUBLE_ELEMENTS, HOLEY_ELEMENTS) \
V(HOLEY_DOUBLE_ELEMENTS, HOLEY_ELEMENTS) \
V(PACKED_ELEMENTS, HOLEY_ELEMENTS)
void HandlerBuiltinsAssembler::DispatchForElementsKindTransition(
TNode<Int32T> from_kind, TNode<Int32T> to_kind,
const ElementsKindTransitionSwitchCase& case_function) {
STATIC_ASSERT(sizeof(ElementsKind) == sizeof(uint8_t));
Label next(this), if_unknown_type(this, Label::kDeferred);
int32_t combined_elements_kinds[] = {
#define ELEMENTS_KINDS_CASE(FROM, TO) (FROM << kBitsPerByte) | TO,
ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
};
#define ELEMENTS_KINDS_CASE(FROM, TO) Label if_##FROM##_##TO(this);
ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
Label* elements_kind_labels[] = {
#define ELEMENTS_KINDS_CASE(FROM, TO) &if_##FROM##_##TO,
ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
};
STATIC_ASSERT(arraysize(combined_elements_kinds) ==
arraysize(elements_kind_labels));
TNode<Word32T> combined_elements_kind =
Word32Or(Word32Shl(from_kind, Int32Constant(kBitsPerByte)), to_kind);
Switch(combined_elements_kind, &if_unknown_type, combined_elements_kinds,
elements_kind_labels, arraysize(combined_elements_kinds));
#define ELEMENTS_KINDS_CASE(FROM, TO) \
BIND(&if_##FROM##_##TO); \
{ \
case_function(FROM, TO); \
Goto(&next); \
}
ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
BIND(&if_unknown_type);
Unreachable();
BIND(&next);
}
#undef ELEMENTS_KIND_TRANSITIONS
void HandlerBuiltinsAssembler::Generate_ElementsTransitionAndStore(
KeyedAccessStoreMode store_mode) {
typedef StoreTransitionDescriptor Descriptor;
Node* receiver = Parameter(Descriptor::kReceiver);
Node* key = Parameter(Descriptor::kName);
Node* value = Parameter(Descriptor::kValue);
Node* map = Parameter(Descriptor::kMap);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* context = Parameter(Descriptor::kContext);
Comment("ElementsTransitionAndStore: store_mode=%d", store_mode);
Label miss(this);
if (FLAG_trace_elements_transitions) {
// Tracing elements transitions is the job of the runtime.
Goto(&miss);
} else {
// TODO(v8:8481): Pass from_kind and to_kind in feedback vector slots.
DispatchForElementsKindTransition(
LoadElementsKind(receiver), LoadMapElementsKind(map),
[=, &miss](ElementsKind from_kind, ElementsKind to_kind) {
TransitionElementsKind(receiver, map, from_kind, to_kind, &miss);
EmitElementStore(receiver, key, value, to_kind, store_mode, &miss,
context);
});
Return(value);
}
BIND(&miss);
TailCallRuntime(Runtime::kElementsTransitionAndStoreIC_Miss, context,
receiver, key, value, map, slot, vector);
}
TF_BUILTIN(ElementsTransitionAndStore_Standard, HandlerBuiltinsAssembler) {
Generate_ElementsTransitionAndStore(STANDARD_STORE);
}
TF_BUILTIN(ElementsTransitionAndStore_GrowNoTransitionHandleCOW,
HandlerBuiltinsAssembler) {
Generate_ElementsTransitionAndStore(STORE_AND_GROW_NO_TRANSITION_HANDLE_COW);
}
TF_BUILTIN(ElementsTransitionAndStore_NoTransitionIgnoreOOB,
HandlerBuiltinsAssembler) {
Generate_ElementsTransitionAndStore(STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS);
}
TF_BUILTIN(ElementsTransitionAndStore_NoTransitionHandleCOW,
HandlerBuiltinsAssembler) {
Generate_ElementsTransitionAndStore(STORE_NO_TRANSITION_HANDLE_COW);
}
// All elements kinds handled by EmitElementStore. Specifically, this includes
// fast elements and fixed typed array elements.
#define ELEMENTS_KINDS(V) \
V(PACKED_SMI_ELEMENTS) \
V(HOLEY_SMI_ELEMENTS) \
V(PACKED_ELEMENTS) \
V(HOLEY_ELEMENTS) \
V(PACKED_DOUBLE_ELEMENTS) \
V(HOLEY_DOUBLE_ELEMENTS) \
V(UINT8_ELEMENTS) \
V(INT8_ELEMENTS) \
V(UINT16_ELEMENTS) \
V(INT16_ELEMENTS) \
V(UINT32_ELEMENTS) \
V(INT32_ELEMENTS) \
V(FLOAT32_ELEMENTS) \
V(FLOAT64_ELEMENTS) \
V(UINT8_CLAMPED_ELEMENTS) \
V(BIGUINT64_ELEMENTS) \
V(BIGINT64_ELEMENTS)
void HandlerBuiltinsAssembler::DispatchByElementsKind(
TNode<Int32T> elements_kind, const ElementsKindSwitchCase& case_function) {
Label next(this), if_unknown_type(this, Label::kDeferred);
int32_t elements_kinds[] = {
#define ELEMENTS_KINDS_CASE(KIND) KIND,
ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
};
#define ELEMENTS_KINDS_CASE(KIND) Label if_##KIND(this);
ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
Label* elements_kind_labels[] = {
#define ELEMENTS_KINDS_CASE(KIND) &if_##KIND,
ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
};
STATIC_ASSERT(arraysize(elements_kinds) == arraysize(elements_kind_labels));
Switch(elements_kind, &if_unknown_type, elements_kinds, elements_kind_labels,
arraysize(elements_kinds));
#define ELEMENTS_KINDS_CASE(KIND) \
BIND(&if_##KIND); \
{ \
case_function(KIND); \
Goto(&next); \
}
ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
BIND(&if_unknown_type);
Unreachable();
BIND(&next);
}
#undef ELEMENTS_KINDS
void HandlerBuiltinsAssembler::Generate_StoreFastElementIC(
KeyedAccessStoreMode store_mode) {
typedef StoreWithVectorDescriptor Descriptor;
Node* receiver = Parameter(Descriptor::kReceiver);
Node* key = Parameter(Descriptor::kName);
Node* value = Parameter(Descriptor::kValue);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* context = Parameter(Descriptor::kContext);
Comment("StoreFastElementStub: store_mode=%d", store_mode);
Label miss(this);
// TODO(v8:8481): Pass elements_kind in feedback vector slots.
DispatchByElementsKind(LoadElementsKind(receiver),
[=, &miss](ElementsKind elements_kind) {
EmitElementStore(receiver, key, value, elements_kind,
store_mode, &miss, context);
});
Return(value);
BIND(&miss);
TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector,
receiver, key);
}
TF_BUILTIN(StoreFastElementIC_Standard, HandlerBuiltinsAssembler) {
Generate_StoreFastElementIC(STANDARD_STORE);
}
TF_BUILTIN(StoreFastElementIC_GrowNoTransitionHandleCOW,
HandlerBuiltinsAssembler) {
Generate_StoreFastElementIC(STORE_AND_GROW_NO_TRANSITION_HANDLE_COW);
}
TF_BUILTIN(StoreFastElementIC_NoTransitionIgnoreOOB, HandlerBuiltinsAssembler) {
Generate_StoreFastElementIC(STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS);
}
TF_BUILTIN(StoreFastElementIC_NoTransitionHandleCOW, HandlerBuiltinsAssembler) {
Generate_StoreFastElementIC(STORE_NO_TRANSITION_HANDLE_COW);
}
TF_BUILTIN(LoadGlobalIC_Slow, CodeStubAssembler) {
Node* name = Parameter(Descriptor::kName);
Node* slot = Parameter(Descriptor::kSlot);
......
......@@ -192,6 +192,53 @@ Callable CodeFactory::StoreInArrayLiteralIC_Slow(Isolate* isolate,
return isolate->builtins()->CallableFor(isolate, builtin_index);
}
Callable CodeFactory::ElementsTransitionAndStore(Isolate* isolate,
KeyedAccessStoreMode mode) {
Builtins::Name builtin_index;
switch (mode) {
case STANDARD_STORE:
builtin_index = Builtins::kElementsTransitionAndStore_Standard;
break;
case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW:
builtin_index =
Builtins::kElementsTransitionAndStore_GrowNoTransitionHandleCOW;
break;
case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
builtin_index =
Builtins::kElementsTransitionAndStore_NoTransitionIgnoreOOB;
break;
case STORE_NO_TRANSITION_HANDLE_COW:
builtin_index =
Builtins::kElementsTransitionAndStore_NoTransitionHandleCOW;
break;
default:
UNREACHABLE();
}
return isolate->builtins()->CallableFor(isolate, builtin_index);
}
Callable CodeFactory::StoreFastElementIC(Isolate* isolate,
KeyedAccessStoreMode mode) {
Builtins::Name builtin_index;
switch (mode) {
case STANDARD_STORE:
builtin_index = Builtins::kStoreFastElementIC_Standard;
break;
case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW:
builtin_index = Builtins::kStoreFastElementIC_GrowNoTransitionHandleCOW;
break;
case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
builtin_index = Builtins::kStoreFastElementIC_NoTransitionIgnoreOOB;
break;
case STORE_NO_TRANSITION_HANDLE_COW:
builtin_index = Builtins::kStoreFastElementIC_NoTransitionHandleCOW;
break;
default:
UNREACHABLE();
}
return isolate->builtins()->CallableFor(isolate, builtin_index);
}
// static
Callable CodeFactory::BinaryOperation(Isolate* isolate, Operation op) {
switch (op) {
......
......@@ -46,6 +46,10 @@ class V8_EXPORT_PRIVATE CodeFactory final {
KeyedAccessStoreMode mode);
static Callable StoreInArrayLiteralIC_Slow(Isolate* isolate,
KeyedAccessStoreMode mode);
static Callable ElementsTransitionAndStore(Isolate* isolate,
KeyedAccessStoreMode mode);
static Callable StoreFastElementIC(Isolate* isolate,
KeyedAccessStoreMode mode);
static Callable ResumeGenerator(Isolate* isolate);
......
......@@ -266,234 +266,12 @@ Handle<Code> TurboFanCodeStub::GenerateCode() {
&state, AssemblerOptions::Default(isolate()));
}
namespace {
class HandlerStubAssembler : public CodeStubAssembler {
public:
explicit HandlerStubAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
protected:
// Essentially turns runtime elements kinds (TNode<Int32T>) into
// compile-time types (int) by dispatching over the runtime type and
// emitting a specialized copy of the given case function for each elements
// kind. Use with caution. This produces a *lot* of code.
typedef std::function<void(ElementsKind)> ElementsKindSwitchCase;
void DispatchByElementsKind(TNode<Int32T> elements_kind,
const ElementsKindSwitchCase& case_function);
// Dispatches over all possible combinations of {from,to} elements kinds.
typedef std::function<void(ElementsKind, ElementsKind)>
ElementsKindTransitionSwitchCase;
void DispatchForElementsKindTransition(
TNode<Int32T> from_kind, TNode<Int32T> to_kind,
const ElementsKindTransitionSwitchCase& case_function);
};
// All possible fast-to-fast transitions. Transitions to dictionary mode are not
// handled by ElementsTransitionAndStore.
#define ELEMENTS_KIND_TRANSITIONS(V) \
V(PACKED_SMI_ELEMENTS, HOLEY_SMI_ELEMENTS) \
V(PACKED_SMI_ELEMENTS, PACKED_DOUBLE_ELEMENTS) \
V(PACKED_SMI_ELEMENTS, HOLEY_DOUBLE_ELEMENTS) \
V(PACKED_SMI_ELEMENTS, PACKED_ELEMENTS) \
V(PACKED_SMI_ELEMENTS, HOLEY_ELEMENTS) \
V(HOLEY_SMI_ELEMENTS, HOLEY_DOUBLE_ELEMENTS) \
V(HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS) \
V(PACKED_DOUBLE_ELEMENTS, HOLEY_DOUBLE_ELEMENTS) \
V(PACKED_DOUBLE_ELEMENTS, PACKED_ELEMENTS) \
V(PACKED_DOUBLE_ELEMENTS, HOLEY_ELEMENTS) \
V(HOLEY_DOUBLE_ELEMENTS, HOLEY_ELEMENTS) \
V(PACKED_ELEMENTS, HOLEY_ELEMENTS)
void HandlerStubAssembler::DispatchForElementsKindTransition(
TNode<Int32T> from_kind, TNode<Int32T> to_kind,
const ElementsKindTransitionSwitchCase& case_function) {
STATIC_ASSERT(sizeof(ElementsKind) == sizeof(uint8_t));
Label next(this), if_unknown_type(this, Label::kDeferred);
int32_t combined_elements_kinds[] = {
#define ELEMENTS_KINDS_CASE(FROM, TO) (FROM << kBitsPerByte) | TO,
ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
};
#define ELEMENTS_KINDS_CASE(FROM, TO) Label if_##FROM##_##TO(this);
ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
Label* elements_kind_labels[] = {
#define ELEMENTS_KINDS_CASE(FROM, TO) &if_##FROM##_##TO,
ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
};
STATIC_ASSERT(arraysize(combined_elements_kinds) ==
arraysize(elements_kind_labels));
TNode<Word32T> combined_elements_kind =
Word32Or(Word32Shl(from_kind, Int32Constant(kBitsPerByte)), to_kind);
Switch(combined_elements_kind, &if_unknown_type, combined_elements_kinds,
elements_kind_labels, arraysize(combined_elements_kinds));
#define ELEMENTS_KINDS_CASE(FROM, TO) \
BIND(&if_##FROM##_##TO); \
{ \
case_function(FROM, TO); \
Goto(&next); \
}
ELEMENTS_KIND_TRANSITIONS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
BIND(&if_unknown_type);
Unreachable();
BIND(&next);
}
#undef ELEMENTS_KIND_TRANSITIONS
} // namespace
TF_STUB(ElementsTransitionAndStoreStub, HandlerStubAssembler) {
Node* receiver = Parameter(Descriptor::kReceiver);
Node* key = Parameter(Descriptor::kName);
Node* value = Parameter(Descriptor::kValue);
Node* map = Parameter(Descriptor::kMap);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* context = Parameter(Descriptor::kContext);
Comment("ElementsTransitionAndStoreStub: store_mode=%d", stub->store_mode());
Label miss(this);
if (FLAG_trace_elements_transitions) {
// Tracing elements transitions is the job of the runtime.
Goto(&miss);
} else {
// TODO(v8:8481): Pass from_kind and to_kind in feedback vector slots.
DispatchForElementsKindTransition(
LoadElementsKind(receiver), LoadMapElementsKind(map),
[=, &miss](ElementsKind from_kind, ElementsKind to_kind) {
TransitionElementsKind(receiver, map, from_kind, to_kind, &miss);
EmitElementStore(receiver, key, value, to_kind, stub->store_mode(),
&miss, context);
});
Return(value);
}
BIND(&miss);
TailCallRuntime(Runtime::kElementsTransitionAndStoreIC_Miss, context,
receiver, key, value, map, slot, vector);
}
int JSEntryStub::GenerateHandlerTable(MacroAssembler* masm) {
int handler_table_offset = HandlerTable::EmitReturnTableStart(masm, 1);
HandlerTable::EmitReturnEntry(masm, 0, handler_offset_);
return handler_table_offset;
}
namespace {
// All elements kinds handled by EmitElementStore. Specifically, this includes
// fast elements and fixed typed array elements.
#define ELEMENTS_KINDS(V) \
V(PACKED_SMI_ELEMENTS) \
V(HOLEY_SMI_ELEMENTS) \
V(PACKED_ELEMENTS) \
V(HOLEY_ELEMENTS) \
V(PACKED_DOUBLE_ELEMENTS) \
V(HOLEY_DOUBLE_ELEMENTS) \
V(UINT8_ELEMENTS) \
V(INT8_ELEMENTS) \
V(UINT16_ELEMENTS) \
V(INT16_ELEMENTS) \
V(UINT32_ELEMENTS) \
V(INT32_ELEMENTS) \
V(FLOAT32_ELEMENTS) \
V(FLOAT64_ELEMENTS) \
V(UINT8_CLAMPED_ELEMENTS) \
V(BIGUINT64_ELEMENTS) \
V(BIGINT64_ELEMENTS)
void HandlerStubAssembler::DispatchByElementsKind(
TNode<Int32T> elements_kind, const ElementsKindSwitchCase& case_function) {
Label next(this), if_unknown_type(this, Label::kDeferred);
int32_t elements_kinds[] = {
#define ELEMENTS_KINDS_CASE(KIND) KIND,
ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
};
#define ELEMENTS_KINDS_CASE(KIND) Label if_##KIND(this);
ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
Label* elements_kind_labels[] = {
#define ELEMENTS_KINDS_CASE(KIND) &if_##KIND,
ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
};
STATIC_ASSERT(arraysize(elements_kinds) == arraysize(elements_kind_labels));
Switch(elements_kind, &if_unknown_type, elements_kinds, elements_kind_labels,
arraysize(elements_kinds));
#define ELEMENTS_KINDS_CASE(KIND) \
BIND(&if_##KIND); \
{ \
case_function(KIND); \
Goto(&next); \
}
ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
BIND(&if_unknown_type);
Unreachable();
BIND(&next);
}
#undef ELEMENTS_KINDS
} // namespace
TF_STUB(StoreFastElementStub, HandlerStubAssembler) {
Comment("StoreFastElementStub: store_mode=%d", stub->store_mode());
Node* receiver = Parameter(Descriptor::kReceiver);
Node* key = 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);
// TODO(v8:8481): Pass elements_kind in feedback vector slots.
DispatchByElementsKind(LoadElementsKind(receiver),
[=, &miss](ElementsKind elements_kind) {
EmitElementStore(receiver, key, value, elements_kind,
stub->store_mode(), &miss, context);
});
Return(value);
BIND(&miss);
TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector,
receiver, key);
}
// static
void StoreFastElementStub::GenerateAheadOfTime(Isolate* isolate) {
StoreFastElementStub(isolate, STANDARD_STORE).GetCode();
StoreFastElementStub(isolate, STORE_AND_GROW_NO_TRANSITION_HANDLE_COW)
.GetCode();
}
void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
intptr_t stack_pointer,
Isolate* isolate) {
......@@ -502,9 +280,5 @@ void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
entry_hook(function, stack_pointer);
}
void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
StoreFastElementStub::GenerateAheadOfTime(isolate);
}
} // namespace internal
} // namespace v8
......@@ -27,10 +27,7 @@ class CodeAssemblerState;
V(CallApiCallback) \
V(CallApiGetter) \
V(JSEntry) \
V(ProfileEntryHook) \
/* --- TurboFanCodeStubs --- */ \
V(ElementsTransitionAndStore) \
V(StoreFastElement)
V(ProfileEntryHook)
// List of code stubs only used on ARM 32 bits platforms.
#if V8_TARGET_ARCH_ARM
......@@ -114,8 +111,6 @@ class CodeStub : public ZoneObject {
explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
virtual ~CodeStub() = default;
static void GenerateStubsAheadOfTime(Isolate* isolate);
// Some stubs put untagged junk on the stack that cannot be scanned by the
// GC. This means that we must be statically sure that no GC can occur while
// they are running. If that is the case they should override this to return
......@@ -501,41 +496,6 @@ class JSEntryStub : public PlatformCodeStub {
DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
};
class StoreFastElementStub : public TurboFanCodeStub {
public:
StoreFastElementStub(Isolate* isolate, KeyedAccessStoreMode mode)
: TurboFanCodeStub(isolate) {
minor_key_ = CommonStoreModeBits::encode(mode);
}
static void GenerateAheadOfTime(Isolate* isolate);
KeyedAccessStoreMode store_mode() const {
return CommonStoreModeBits::decode(minor_key_);
}
private:
DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
DEFINE_TURBOFAN_CODE_STUB(StoreFastElement, TurboFanCodeStub);
};
class ElementsTransitionAndStoreStub : public TurboFanCodeStub {
public:
ElementsTransitionAndStoreStub(Isolate* isolate,
KeyedAccessStoreMode store_mode)
: TurboFanCodeStub(isolate) {
minor_key_ = CommonStoreModeBits::encode(store_mode);
}
KeyedAccessStoreMode store_mode() const {
return CommonStoreModeBits::decode(minor_key_);
}
private:
DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition);
DEFINE_TURBOFAN_CODE_STUB(ElementsTransitionAndStore, TurboFanCodeStub);
};
// TODO(jgruber): Convert this stub into a builtin.
class ProfileEntryHookStub : public PlatformCodeStub {
public:
......
......@@ -1091,6 +1091,10 @@ bool BuiltinHasKeyedAccessStoreMode(int builtin_index) {
case Builtins::kKeyedStoreIC_SloppyArguments_GrowNoTransitionHandleCOW:
case Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB:
case Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionHandleCOW:
case Builtins::kStoreFastElementIC_Standard:
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:
......@@ -1099,6 +1103,10 @@ bool BuiltinHasKeyedAccessStoreMode(int builtin_index) {
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:
case Builtins::kElementsTransitionAndStore_NoTransitionHandleCOW:
return true;
default:
return false;
......@@ -1112,18 +1120,26 @@ KeyedAccessStoreMode KeyedAccessStoreModeForBuiltin(int 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_NO_TRANSITION_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_NO_TRANSITION_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_NO_TRANSITION_HANDLE_COW;
default:
UNREACHABLE();
......@@ -1167,16 +1183,8 @@ KeyedAccessStoreMode FeedbackNexus::GetKeyedAccessStoreMode() const {
mode = KeyedAccessStoreModeForBuiltin(builtin_index);
break;
} else {
CodeStub::Major major_key =
CodeStub::MajorKeyFromKey(handler->stub_key());
uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
CHECK(major_key == CodeStub::StoreFastElement ||
major_key == CodeStub::ElementsTransitionAndStore ||
major_key == CodeStub::NoCache);
if (major_key != CodeStub::NoCache) {
mode = CommonStoreModeBits::decode(minor_key);
break;
}
CHECK(CodeStub::MajorKeyFromKey(handler->stub_key()) ==
CodeStub::NoCache);
}
}
......
......@@ -2420,13 +2420,6 @@ void Heap::CreateFixedStubs() {
// Canonicalize handles, so that we can share constant pool entries pointing
// to code targets without dereferencing their handles.
CanonicalHandleScope canonical(isolate());
// Create stubs that should be there, so we don't unexpectedly have to
// create them if we need them during the creation of another stub.
// Stub creation mixes raw pointers and handles in an unsafe manner so
// we cannot create stubs while we are creating stubs.
CodeStub::GenerateStubsAheadOfTime(isolate());
// gcc-4.4 has problem generating correct code of following snippet:
// { JSEntryStub stub;
// js_entry_code_ = *stub.GetCode();
......
......@@ -4,7 +4,7 @@
#include "src/ic/handler-configuration.h"
#include "src/code-stubs.h"
#include "src/code-factory.h"
#include "src/ic/handler-configuration-inl.h"
#include "src/objects/data-handler-inl.h"
#include "src/objects/maybe-object.h"
......@@ -183,7 +183,7 @@ Handle<Object> StoreHandler::StoreElementTransition(
Isolate* isolate, Handle<Map> receiver_map, Handle<Map> transition,
KeyedAccessStoreMode store_mode) {
Handle<Code> stub =
ElementsTransitionAndStoreStub(isolate, store_mode).GetCode();
CodeFactory::ElementsTransitionAndStore(isolate, store_mode).code();
Handle<Object> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
Handle<StoreHandler> handler = isolate->factory()->NewStoreHandler(1);
......
......@@ -1843,40 +1843,40 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
}
// TODO(ishell): move to StoreHandler::StoreElement().
Handle<Code> stub;
Handle<Code> code;
if (receiver_map->has_sloppy_arguments_elements()) {
// TODO(jgruber): Update counter name.
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_KeyedStoreSloppyArgumentsStub);
stub =
code =
CodeFactory::KeyedStoreIC_SloppyArguments(isolate(), store_mode).code();
} else if (receiver_map->has_fast_elements() ||
receiver_map->has_fixed_typed_array_elements()) {
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
stub = StoreFastElementStub(isolate(), store_mode).GetCode();
if (receiver_map->has_fixed_typed_array_elements()) return stub;
code = CodeFactory::StoreFastElementIC(isolate(), store_mode).code();
if (receiver_map->has_fixed_typed_array_elements()) return code;
} else if (IsStoreInArrayLiteralICKind(kind())) {
// TODO(jgruber): Update counter name.
TRACE_HANDLER_STATS(isolate(), StoreInArrayLiteralIC_SlowStub);
stub =
code =
CodeFactory::StoreInArrayLiteralIC_Slow(isolate(), store_mode).code();
} else {
// TODO(jgruber): Update counter name.
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
DCHECK_EQ(DICTIONARY_ELEMENTS, receiver_map->elements_kind());
stub = CodeFactory::KeyedStoreIC_Slow(isolate(), store_mode).code();
code = CodeFactory::KeyedStoreIC_Slow(isolate(), store_mode).code();
}
if (IsStoreInArrayLiteralICKind(kind())) return stub;
if (IsStoreInArrayLiteralICKind(kind())) return code;
Handle<Object> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (validity_cell->IsSmi()) {
// There's no prototype validity cell to check, so we can just use the stub.
return stub;
return code;
}
Handle<StoreHandler> handler = isolate()->factory()->NewStoreHandler(0);
handler->set_validity_cell(*validity_cell);
handler->set_smi_handler(*stub);
handler->set_smi_handler(*code);
return handler;
}
......
......@@ -2558,16 +2558,10 @@ TEST(CheckCodeNames) {
const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const char* stub_path[] = {"::(GC roots)", "::(Strong roots)",
"code_stubs::", "::(StoreFastElementStub code)"};
const v8::HeapGraphNode* node = GetNodeByPath(
env->GetIsolate(), snapshot, stub_path, arraysize(stub_path));
CHECK(node);
const char* builtin_path1[] = {"::(GC roots)", "::(Builtins)",
"::(KeyedLoadIC_Slow builtin)"};
node = GetNodeByPath(env->GetIsolate(), snapshot, builtin_path1,
arraysize(builtin_path1));
const v8::HeapGraphNode* node = GetNodeByPath(
env->GetIsolate(), snapshot, builtin_path1, arraysize(builtin_path1));
CHECK(node);
const char* builtin_path2[] = {"::(GC roots)", "::(Builtins)",
......
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