Commit 51474635 authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm][memory64] Implement 64-bit init expressions

For memory64, the init expressions for data segments provide a 64-bit
value. This CL adds a new {EvalUint64InitExpr} function alongside
{EvalUint32InitExpr}. It supports i64.const and global.get operations.

R=manoskouk@chromium.org

Bug: v8:10949
Change-Id: I58acbb28acb8771a0947f9d5df1c14e6ca0f79cf
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2632589Reviewed-by: 's avatarManos Koukoutos <manoskouk@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72131}
parent c65456bf
......@@ -39,11 +39,11 @@ uint32_t EvalUint32InitExpr(Handle<WasmInstanceObject> instance,
case WasmInitExpr::kI32Const:
return expr.immediate().i32_const;
case WasmInitExpr::kGlobalGet: {
uint32_t offset =
instance->module()->globals[expr.immediate().index].offset;
const auto& global = instance->module()->globals[expr.immediate().index];
DCHECK_EQ(kWasmI32, global.type);
auto raw_addr = reinterpret_cast<Address>(
instance->untagged_globals_buffer().backing_store()) +
offset;
global.offset;
return ReadLittleEndianValue<uint32_t>(raw_addr);
}
default:
......@@ -51,6 +51,24 @@ uint32_t EvalUint32InitExpr(Handle<WasmInstanceObject> instance,
}
}
uint64_t EvalUint64InitExpr(Handle<WasmInstanceObject> instance,
const WasmInitExpr& expr) {
switch (expr.kind()) {
case WasmInitExpr::kI64Const:
return expr.immediate().i64_const;
case WasmInitExpr::kGlobalGet: {
const auto& global = instance->module()->globals[expr.immediate().index];
DCHECK_EQ(kWasmI64, global.type);
auto raw_addr = reinterpret_cast<Address>(
instance->untagged_globals_buffer().backing_store()) +
global.offset;
return ReadLittleEndianValue<uint64_t>(raw_addr);
}
default:
UNREACHABLE();
}
}
namespace {
byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
......@@ -826,15 +844,23 @@ void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) {
// Passive segments are not copied during instantiation.
if (!segment.active) continue;
uint32_t dest_offset = EvalUint32InitExpr(instance, segment.dest_addr);
bool ok = base::ClampToBounds(
dest_offset, &size, static_cast<uint32_t>(instance->memory_size()));
if (!ok) {
size_t dest_offset;
if (module_->is_memory64) {
uint64_t dest_offset_64 = EvalUint64InitExpr(instance, segment.dest_addr);
// Clamp to {std::numeric_limits<size_t>::max()}, which is always an
// invalid offset.
DCHECK_GT(std::numeric_limits<size_t>::max(), instance->memory_size());
dest_offset = static_cast<size_t>(std::min(
dest_offset_64, uint64_t{std::numeric_limits<size_t>::max()}));
} else {
dest_offset = EvalUint32InitExpr(instance, segment.dest_addr);
}
if (!base::IsInBounds<size_t>(dest_offset, size, instance->memory_size())) {
thrower_->RuntimeError("data segment is out of bounds");
return;
}
// No need to copy empty segments.
if (size == 0) continue;
std::memcpy(instance->memory_start() + dest_offset,
wire_bytes.begin() + segment.source.offset(), size);
}
......
......@@ -7,6 +7,7 @@
#include "test/cctest/wasm/wasm-run-utils.h"
#include "test/common/wasm/test-signatures.h"
#include "test/common/wasm/wasm-macro-gen.h"
#include "test/common/wasm/wasm-module-runner.h"
namespace v8 {
namespace internal {
......@@ -54,6 +55,36 @@ WASM_EXEC_TEST(Load) {
// TODO(clemensb): Test atomic instructions.
WASM_EXEC_TEST(InitExpression) {
EXPERIMENTAL_FLAG_SCOPE(memory64);
Isolate* isolate = CcTest::InitIsolateOnce();
HandleScope scope(isolate);
ErrorThrower thrower(isolate, "TestMemory64InitExpression");
const byte data[] = {
WASM_MODULE_HEADER, //
SECTION(Memory, //
ENTRY_COUNT(1), //
kMemory64WithMaximum, // type
1, // initial size
2), // maximum size
SECTION(Data, //
ENTRY_COUNT(1), //
0, // linear memory index
WASM_I64V_3(0xFFFF), kExprEnd, // destination offset
U32V_1(1), // source size
'c') // data bytes
};
testing::CompileAndInstantiateForTesting(
isolate, &thrower, ModuleWireBytes(data, data + arraysize(data)));
if (thrower.error()) {
thrower.Reify()->Print();
FATAL("compile or instantiate error");
}
}
} // namespace wasm
} // namespace internal
} // namespace v8
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