diff options
Diffstat (limited to 'deps/v8/src/builtins/builtins-handler-gen.cc')
-rw-r--r-- | deps/v8/src/builtins/builtins-handler-gen.cc | 389 |
1 files changed, 387 insertions, 2 deletions
diff --git a/deps/v8/src/builtins/builtins-handler-gen.cc b/deps/v8/src/builtins/builtins-handler-gen.cc index 8b5dc182cf..aeaa804856 100644 --- a/deps/v8/src/builtins/builtins-handler-gen.cc +++ b/deps/v8/src/builtins/builtins-handler-gen.cc @@ -12,6 +12,35 @@ namespace v8 { namespace internal { +class HandlerBuiltinsAssembler : public CodeStubAssembler { + public: + explicit HandlerBuiltinsAssembler(compiler::CodeAssemblerState* state) + : CodeStubAssembler(state) {} + + 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 + // 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) { Node* string = Parameter(Descriptor::kReceiver); Return(LoadStringLengthAsSmi(string)); @@ -41,7 +70,8 @@ void Builtins::Generate_StoreIC_Uninitialized( StoreICUninitializedGenerator::Generate(state); } -TF_BUILTIN(KeyedStoreIC_Slow, CodeStubAssembler) { +void HandlerBuiltinsAssembler::Generate_KeyedStoreIC_Slow() { + typedef StoreWithVectorDescriptor Descriptor; Node* receiver = Parameter(Descriptor::kReceiver); Node* name = Parameter(Descriptor::kName); Node* value = Parameter(Descriptor::kValue); @@ -55,7 +85,29 @@ TF_BUILTIN(KeyedStoreIC_Slow, CodeStubAssembler) { receiver, name); } -TF_BUILTIN(StoreInArrayLiteralIC_Slow, CodeStubAssembler) { +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() { + typedef StoreWithVectorDescriptor Descriptor; Node* array = Parameter(Descriptor::kReceiver); Node* index = Parameter(Descriptor::kName); Node* value = Parameter(Descriptor::kValue); @@ -64,6 +116,253 @@ TF_BUILTIN(StoreInArrayLiteralIC_Slow, CodeStubAssembler) { 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) \ + 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=", 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=", 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); @@ -109,5 +408,91 @@ TF_BUILTIN(StoreGlobalIC_Slow, CodeStubAssembler) { receiver, name); } +TF_BUILTIN(KeyedLoadIC_SloppyArguments, CodeStubAssembler) { + Node* receiver = Parameter(Descriptor::kReceiver); + Node* key = Parameter(Descriptor::kName); + Node* slot = Parameter(Descriptor::kSlot); + Node* vector = Parameter(Descriptor::kVector); + Node* context = Parameter(Descriptor::kContext); + + Label miss(this); + + Node* result = LoadKeyedSloppyArguments(receiver, key, &miss); + Return(result); + + BIND(&miss); + { + Comment("Miss"); + TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, slot, + vector); + } +} + +void HandlerBuiltinsAssembler::Generate_KeyedStoreIC_SloppyArguments() { + 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); + + Label miss(this); + + StoreKeyedSloppyArguments(receiver, key, value, &miss); + Return(value); + + BIND(&miss); + TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector, + receiver, key); +} + +TF_BUILTIN(KeyedStoreIC_SloppyArguments_Standard, HandlerBuiltinsAssembler) { + Generate_KeyedStoreIC_SloppyArguments(); +} + +TF_BUILTIN(KeyedStoreIC_SloppyArguments_GrowNoTransitionHandleCOW, + HandlerBuiltinsAssembler) { + Generate_KeyedStoreIC_SloppyArguments(); +} + +TF_BUILTIN(KeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB, + HandlerBuiltinsAssembler) { + Generate_KeyedStoreIC_SloppyArguments(); +} + +TF_BUILTIN(KeyedStoreIC_SloppyArguments_NoTransitionHandleCOW, + HandlerBuiltinsAssembler) { + Generate_KeyedStoreIC_SloppyArguments(); +} + +TF_BUILTIN(StoreInterceptorIC, CodeStubAssembler) { + 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); + TailCallRuntime(Runtime::kStorePropertyWithInterceptor, context, value, slot, + vector, receiver, name); +} + +TF_BUILTIN(LoadIndexedInterceptorIC, CodeStubAssembler) { + Node* receiver = Parameter(Descriptor::kReceiver); + Node* key = Parameter(Descriptor::kName); + Node* slot = Parameter(Descriptor::kSlot); + Node* vector = Parameter(Descriptor::kVector); + Node* context = Parameter(Descriptor::kContext); + + Label if_keyispositivesmi(this), if_keyisinvalid(this); + Branch(TaggedIsPositiveSmi(key), &if_keyispositivesmi, &if_keyisinvalid); + BIND(&if_keyispositivesmi); + TailCallRuntime(Runtime::kLoadElementWithInterceptor, context, receiver, key); + + BIND(&if_keyisinvalid); + TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, slot, + vector); +} + } // namespace internal } // namespace v8 |