Commit 6d3d8f7b authored by Ben L. Titzer's avatar Ben L. Titzer Committed by Commit Bot

[wasm] Add runtime call plumbing for Table operations.

This CL adds two new runtime calls for table operations:
  - Runtime_WasmTableInit
  - Runtime_WasmTableCopy

These runtime calls (will) implement the semantics for the corresponding
bytecodes from the bulk memory proposal. The actual implementation
of these runtime calls will be done in further CLs.

The third table operation, table.drop, will be implemented with inline
code, similar to memory.drop. This is also be done in a further CL.

R=mstarzinger@chromium.org
CC=​binji@chromium.org
BUG=v8:7747

Change-Id: I498aa054329baf9f72ae55d245b12c3ccd4157b7
Reviewed-on: https://chromium-review.googlesource.com/c/1408994
Commit-Queue: Ben Titzer <titzer@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58786}
parent a6f44629
......@@ -3119,9 +3119,10 @@ Node* WasmGraphBuilder::BuildCallToRuntimeWithContext(
DCHECK_EQ(1, fun->result_size);
Node* centry_stub =
LOAD_INSTANCE_FIELD(CEntryStub, MachineType::TaggedPointer());
// At the moment we only allow 4 parameters. If more parameters are needed,
// TODO(titzer): allow arbitrary number of runtime arguments
// At the moment we only allow 5 parameters. If more parameters are needed,
// increase this constant accordingly.
static const int kMaxParams = 4;
static const int kMaxParams = 5;
DCHECK_GE(kMaxParams, parameter_count);
Node* inputs[kMaxParams + 6];
int count = 0;
......@@ -4356,6 +4357,44 @@ Node* WasmGraphBuilder::MemoryFill(Node* dst, Node* value, Node* size,
return BuildCCall(&sig, function, dst, value, size);
}
Node* WasmGraphBuilder::TableInit(uint32_t table_index,
uint32_t elem_segment_index, Node* dst,
Node* src, Node* size,
wasm::WasmCodePosition position) {
// TODO(titzer): bounds check table indexes against maximum table size.
Node* args[] = {
// --
graph()->NewNode(mcgraph()->common()->NumberConstant(table_index)),
graph()->NewNode(mcgraph()->common()->NumberConstant(elem_segment_index)),
BuildChangeUint31ToSmi(dst), // --
BuildChangeUint31ToSmi(src), // --
BuildChangeUint31ToSmi(size) // --
};
Node* result =
BuildCallToRuntime(Runtime::kWasmTableInit, args, arraysize(args));
return result;
}
Node* WasmGraphBuilder::TableDrop(uint32_t elem_segment_index,
wasm::WasmCodePosition position) {
UNREACHABLE();
}
Node* WasmGraphBuilder::TableCopy(Node* dst, Node* src, Node* size,
wasm::WasmCodePosition position) {
// TODO(titzer): bounds check table indexes against maximum table size.
Node* args[] = {
BuildChangeUint31ToSmi(dst), // --
BuildChangeUint31ToSmi(src), // --
BuildChangeUint31ToSmi(size) // --
};
Node* result =
BuildCallToRuntime(Runtime::kWasmTableCopy, args, arraysize(args));
return result;
}
class WasmDecorator final : public GraphDecorator {
public:
explicit WasmDecorator(NodeOriginTable* origins, wasm::Decoder* decoder)
......
......@@ -360,13 +360,19 @@ class WasmGraphBuilder {
wasm::WasmCodePosition position);
Node* MemoryInit(uint32_t data_segment_index, Node* dst, Node* src,
Node* size, wasm::WasmCodePosition position);
Node* MemoryDrop(uint32_t data_segment_index,
wasm::WasmCodePosition position);
Node* MemoryCopy(Node* dst, Node* src, Node* size,
wasm::WasmCodePosition position);
Node* MemoryDrop(uint32_t data_segment_index,
wasm::WasmCodePosition position);
Node* MemoryFill(Node* dst, Node* fill, Node* size,
wasm::WasmCodePosition position);
Node* TableInit(uint32_t table_index, uint32_t elem_segment_index, Node* dst,
Node* src, Node* size, wasm::WasmCodePosition position);
Node* TableDrop(uint32_t elem_segment_index, wasm::WasmCodePosition position);
Node* TableCopy(Node* dst, Node* src, Node* size,
wasm::WasmCodePosition position);
bool has_simd() const { return has_simd_; }
const wasm::WasmModule* module() { return env_ ? env_->module : nullptr; }
......
......@@ -319,5 +319,47 @@ RUNTIME_FUNCTION(Runtime_WasmI64AtomicWait) {
timeout_ms);
}
RUNTIME_FUNCTION(Runtime_WasmTableInit) {
HandleScope scope(isolate);
DCHECK_EQ(5, args.length());
auto instance = GetWasmInstanceOnStackTop(isolate);
CONVERT_UINT32_ARG_CHECKED(table_index, 0);
CONVERT_UINT32_ARG_CHECKED(elem_segment_index, 1);
CONVERT_UINT32_ARG_CHECKED(dst, 2);
CONVERT_UINT32_ARG_CHECKED(src, 3);
CONVERT_UINT32_ARG_CHECKED(size, 4);
PrintF(
"TableInit(table_index=%u, elem_segment_index=%u, dst=%u, src=%u, "
"size=%u)\n",
table_index, elem_segment_index, dst, src, size);
USE(instance);
USE(table_index);
USE(elem_segment_index);
USE(dst);
USE(src);
USE(size);
UNREACHABLE();
}
RUNTIME_FUNCTION(Runtime_WasmTableCopy) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
auto instance = GetWasmInstanceOnStackTop(isolate);
CONVERT_UINT32_ARG_CHECKED(dst, 0);
CONVERT_UINT32_ARG_CHECKED(src, 1);
CONVERT_UINT32_ARG_CHECKED(size, 2);
PrintF("TableCopy(dst=%u, src=%u, size=%u)\n", dst, src, size);
USE(instance);
USE(dst);
USE(src);
USE(size);
UNREACHABLE();
}
} // namespace internal
} // namespace v8
......@@ -539,6 +539,8 @@ namespace internal {
F(WasmStackGuard, 0, 1) \
F(WasmThrowCreate, 2, 1) \
F(WasmThrowTypeError, 0, 1) \
F(WasmTableInit, 5, 1) \
F(WasmTableCopy, 3, 1) \
F(WasmCompileLazy, 2, 1)
#define FOR_EACH_INTRINSIC_RETURN_PAIR_IMPL(F, I) \
......
......@@ -553,15 +553,17 @@ class WasmGraphBuildingInterface {
}
void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm,
Vector<Value> args) {
BUILD(Unreachable, decoder->position());
BUILD(TableInit, imm.table.index, imm.elem_segment_index, args[0].node,
args[1].node, args[2].node, decoder->position());
}
void TableDrop(FullDecoder* decoder,
const TableDropImmediate<validate>& imm) {
BUILD(Unreachable, decoder->position());
BUILD(TableDrop, imm.index, decoder->position());
}
void TableCopy(FullDecoder* decoder, const TableIndexImmediate<validate>& imm,
Vector<Value> args) {
BUILD(Unreachable, decoder->position());
BUILD(TableCopy, args[0].node, args[1].node, args[2].node,
decoder->position());
}
private:
......
......@@ -320,3 +320,49 @@ function getMemoryFill(mem) {
assertTraps(
kTrapMemOutOfBounds, () => memoryFill(kPageSize + 1, v, kPageSize));
})();
(function TestTableInit0() {
let builder = new WasmModuleBuilder();
let sig_v_iii = builder.addType(kSig_v_iii);
builder.setTableBounds(5, 5);
builder.addElementSegment(0, false, []);
builder.addElementSegment(0, false, []);
builder.addFunction("init0", sig_v_iii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kExprGetLocal, 2,
kNumericPrefix, kExprTableInit, kTableZero, kSegmentZero])
.exportAs("init0");
let instance = builder.instantiate();
let init = instance.exports.init0;
// TODO(titzer): we only check that a function containing TableInit can be compiled.
// init(1, 2, 3);
})();
(function TestTableDrop0() {
// TODO(titzer): initial testcase for table drop
})();
(function TestTableCopy0() {
let builder = new WasmModuleBuilder();
let sig_v_iii = builder.addType(kSig_v_iii);
builder.setTableBounds(5, 5);
builder.addFunction("copy", sig_v_iii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kExprGetLocal, 2,
kNumericPrefix, kExprTableCopy, kTableZero])
.exportAs("copy");
let instance = builder.instantiate();
let copy = instance.exports.copy;
// TODO(titzer): we only check that a function containing TableCopy can be compiled.
// copy(1, 2, 3);
})();
......@@ -106,6 +106,7 @@ let kExternalException = 4;
let kTableZero = 0;
let kMemoryZero = 0;
let kSegmentZero = 0;
let kExceptionAttribute = 0;
......
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