Commit 1e1d4d82 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm] Introduce a TableCopy builtin

This CL introduces a CSA builtin for the TableCopy instruction. This
builtin allows to generate smaller code for both TurboFan and Liftoff,
and easier code generation from Liftoff.

The smaller code size comes from:
* Parameters are passed through registers, not the stack.
* Lower number of parameters: the call target, number of parameters, and
context are not passed as parameters.
* No int to smi conversion in generated code.

R=clemensb@chromium.org

Bug: v8:10281
Change-Id: I4734b94c8a2aff08a5938504e3e36d0d2424f8ca
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2110010
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66797}
parent d1253ae9
...@@ -858,6 +858,7 @@ namespace internal { ...@@ -858,6 +858,7 @@ namespace internal {
TFC(WasmI64AtomicWait64, WasmI64AtomicWait64) \ TFC(WasmI64AtomicWait64, WasmI64AtomicWait64) \
TFC(WasmMemoryGrow, WasmMemoryGrow) \ TFC(WasmMemoryGrow, WasmMemoryGrow) \
TFC(WasmTableInit, WasmTableInit) \ TFC(WasmTableInit, WasmTableInit) \
TFC(WasmTableCopy, WasmTableCopy) \
TFC(WasmTableGet, WasmTableGet) \ TFC(WasmTableGet, WasmTableGet) \
TFC(WasmTableSet, WasmTableSet) \ TFC(WasmTableSet, WasmTableSet) \
TFC(WasmStackGuard, NoContext) \ TFC(WasmStackGuard, NoContext) \
......
...@@ -248,6 +248,39 @@ TF_BUILTIN(WasmTableInit, WasmBuiltinsAssembler) { ...@@ -248,6 +248,39 @@ TF_BUILTIN(WasmTableInit, WasmBuiltinsAssembler) {
segment_index, dst, src, size); segment_index, dst, src, size);
} }
TF_BUILTIN(WasmTableCopy, WasmBuiltinsAssembler) {
// We cap {dst}, {src}, and {size} by {wasm::kV8MaxWasmTableSize + 1} to make
// sure that the values fit into a Smi.
STATIC_ASSERT(static_cast<size_t>(Smi::kMaxValue) >=
wasm::kV8MaxWasmTableSize + 1);
constexpr uint32_t kCap =
static_cast<uint32_t>(wasm::kV8MaxWasmTableSize + 1);
TNode<Uint32T> dst_raw =
UncheckedCast<Uint32T>(Parameter(Descriptor::kDestination));
TNode<Smi> dst = SmiFromUint32WithSaturation(dst_raw, kCap);
TNode<Uint32T> src_raw =
UncheckedCast<Uint32T>(Parameter(Descriptor::kSource));
TNode<Smi> src = SmiFromUint32WithSaturation(src_raw, kCap);
TNode<Uint32T> size_raw =
UncheckedCast<Uint32T>(Parameter(Descriptor::kSize));
TNode<Smi> size = SmiFromUint32WithSaturation(size_raw, kCap);
TNode<Smi> dst_table =
UncheckedCast<Smi>(Parameter(Descriptor::kDestinationTable));
TNode<Smi> src_table =
UncheckedCast<Smi>(Parameter(Descriptor::kSourceTable));
TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
TNode<Context> context = LoadContextFromInstance(instance);
TailCallRuntime(Runtime::kWasmTableCopy, context, instance, dst_table,
src_table, dst, src, size);
}
TF_BUILTIN(WasmTableGet, WasmBuiltinsAssembler) { TF_BUILTIN(WasmTableGet, WasmBuiltinsAssembler) {
TNode<Int32T> entry_index = TNode<Int32T> entry_index =
UncheckedCast<Int32T>(Parameter(Descriptor::kEntryIndex)); UncheckedCast<Int32T>(Parameter(Descriptor::kEntryIndex));
......
...@@ -386,6 +386,12 @@ void WasmTableInitDescriptor::InitializePlatformSpecific( ...@@ -386,6 +386,12 @@ void WasmTableInitDescriptor::InitializePlatformSpecific(
kParameterCount - kStackArgumentsCount); kParameterCount - kStackArgumentsCount);
} }
void WasmTableCopyDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data,
kParameterCount - kStackArgumentsCount);
}
void WasmTableGetDescriptor::InitializePlatformSpecific( void WasmTableGetDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount); DefaultInitializePlatformSpecific(data, kParameterCount);
......
...@@ -97,6 +97,7 @@ namespace internal { ...@@ -97,6 +97,7 @@ namespace internal {
V(WasmI64AtomicWait64) \ V(WasmI64AtomicWait64) \
V(WasmMemoryGrow) \ V(WasmMemoryGrow) \
V(WasmTableInit) \ V(WasmTableInit) \
V(WasmTableCopy) \
V(WasmTableGet) \ V(WasmTableGet) \
V(WasmTableSet) \ V(WasmTableSet) \
V(WasmThrow) \ V(WasmThrow) \
...@@ -1319,6 +1320,29 @@ class WasmTableInitDescriptor final : public CallInterfaceDescriptor { ...@@ -1319,6 +1320,29 @@ class WasmTableInitDescriptor final : public CallInterfaceDescriptor {
DECLARE_DESCRIPTOR(WasmTableInitDescriptor, CallInterfaceDescriptor) DECLARE_DESCRIPTOR(WasmTableInitDescriptor, CallInterfaceDescriptor)
}; };
class WasmTableCopyDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS_NO_CONTEXT(kDestination, kSource, kSize, kDestinationTable,
kSourceTable)
DEFINE_PARAMETER_TYPES(MachineType::Int32(), // kDestination
MachineType::Int32(), // kSource
MachineType::Int32(), // kSize
MachineType::AnyTagged(), // kDestinationTable
MachineType::AnyTagged(), // kSourceTable
)
#if V8_TARGET_ARCH_IA32
static constexpr bool kPassLastArgOnStack = true;
#else
static constexpr bool kPassLastArgOnStack = false;
#endif
// Pass the last parameter through the stack.
static constexpr int kStackArgumentsCount = kPassLastArgOnStack ? 1 : 0;
DECLARE_DESCRIPTOR(WasmTableCopyDescriptor, CallInterfaceDescriptor)
};
class WasmTableGetDescriptor final : public CallInterfaceDescriptor { class WasmTableGetDescriptor final : public CallInterfaceDescriptor {
public: public:
DEFINE_PARAMETERS_NO_CONTEXT(kTableIndex, kEntryIndex) DEFINE_PARAMETERS_NO_CONTEXT(kTableIndex, kEntryIndex)
......
...@@ -4996,16 +4996,17 @@ Node* WasmGraphBuilder::TableCopy(uint32_t table_dst_index, ...@@ -4996,16 +4996,17 @@ Node* WasmGraphBuilder::TableCopy(uint32_t table_dst_index,
uint32_t table_src_index, Node* dst, uint32_t table_src_index, Node* dst,
Node* src, Node* size, Node* src, Node* size,
wasm::WasmCodePosition position) { wasm::WasmCodePosition position) {
Node* args[] = { auto call_descriptor = GetBuiltinCallDescriptor<WasmTableCopyDescriptor>(
graph()->NewNode(mcgraph()->common()->NumberConstant(table_dst_index)), this, StubCallMode::kCallWasmRuntimeStub);
graph()->NewNode(mcgraph()->common()->NumberConstant(table_src_index)),
BuildConvertUint32ToSmiWithSaturation(dst, FLAG_wasm_max_table_size),
BuildConvertUint32ToSmiWithSaturation(src, FLAG_wasm_max_table_size),
BuildConvertUint32ToSmiWithSaturation(size, FLAG_wasm_max_table_size)};
Node* result =
BuildCallToRuntime(Runtime::kWasmTableCopy, args, arraysize(args));
return result; intptr_t target = wasm::WasmCode::kWasmTableCopy;
Node* call_target =
mcgraph()->RelocatableIntPtrConstant(target, RelocInfo::WASM_STUB_CALL);
return gasm_->Call(
call_descriptor, call_target, dst, src, size,
graph()->NewNode(mcgraph()->common()->NumberConstant(table_dst_index)),
graph()->NewNode(mcgraph()->common()->NumberConstant(table_src_index)));
} }
Node* WasmGraphBuilder::TableGrow(uint32_t table_index, Node* value, Node* WasmGraphBuilder::TableGrow(uint32_t table_index, Node* value,
......
...@@ -516,16 +516,15 @@ RUNTIME_FUNCTION(Runtime_WasmTableInit) { ...@@ -516,16 +516,15 @@ RUNTIME_FUNCTION(Runtime_WasmTableInit) {
RUNTIME_FUNCTION(Runtime_WasmTableCopy) { RUNTIME_FUNCTION(Runtime_WasmTableCopy) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(5, args.length()); DCHECK_EQ(6, args.length());
DCHECK(isolate->context().is_null()); CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate)); CONVERT_UINT32_ARG_CHECKED(table_dst_index, 1);
auto instance = CONVERT_UINT32_ARG_CHECKED(table_src_index, 2);
Handle<WasmInstanceObject>(GetWasmInstanceOnStackTop(isolate), isolate); CONVERT_UINT32_ARG_CHECKED(dst, 3);
CONVERT_UINT32_ARG_CHECKED(table_dst_index, 0); CONVERT_UINT32_ARG_CHECKED(src, 4);
CONVERT_UINT32_ARG_CHECKED(table_src_index, 1); CONVERT_UINT32_ARG_CHECKED(count, 5);
CONVERT_UINT32_ARG_CHECKED(dst, 2);
CONVERT_UINT32_ARG_CHECKED(src, 3); DCHECK(!isolate->context().is_null());
CONVERT_UINT32_ARG_CHECKED(count, 4);
bool oob = !WasmInstanceObject::CopyTableEntries( bool oob = !WasmInstanceObject::CopyTableEntries(
isolate, instance, table_dst_index, table_src_index, dst, src, count); isolate, instance, table_dst_index, table_src_index, dst, src, count);
......
...@@ -570,7 +570,7 @@ namespace internal { ...@@ -570,7 +570,7 @@ namespace internal {
F(WasmFunctionTableGet, 3, 1) \ F(WasmFunctionTableGet, 3, 1) \
F(WasmFunctionTableSet, 4, 1) \ F(WasmFunctionTableSet, 4, 1) \
F(WasmTableInit, 6, 1) \ F(WasmTableInit, 6, 1) \
F(WasmTableCopy, 5, 1) \ F(WasmTableCopy, 6, 1) \
F(WasmTableGrow, 3, 1) \ F(WasmTableGrow, 3, 1) \
F(WasmTableFill, 4, 1) \ F(WasmTableFill, 4, 1) \
F(WasmIsValidFuncRefValue, 1, 1) \ F(WasmIsValidFuncRefValue, 1, 1) \
......
...@@ -56,6 +56,7 @@ struct WasmModule; ...@@ -56,6 +56,7 @@ struct WasmModule;
V(WasmI64AtomicWait64) \ V(WasmI64AtomicWait64) \
V(WasmMemoryGrow) \ V(WasmMemoryGrow) \
V(WasmTableInit) \ V(WasmTableInit) \
V(WasmTableCopy) \
V(WasmTableGet) \ V(WasmTableGet) \
V(WasmTableSet) \ V(WasmTableSet) \
V(WasmStackGuard) \ V(WasmStackGuard) \
......
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