Revert "[wasm] Implement table.init for interpreter"
This reverts commit 63608968b6
.
Reason for revert:
https://ci.chromium.org/p/v8/builders/ci/V8%20Win32%20-%20debug/19535
Original change's description:
> [wasm] Implement table.init for interpreter
>
> This also fixes CheckCallViaJS when a trap occurs. In that case, the
> trap callback is called instead of an exception being thrown, so if it
> isn't handled, a bogus result will be returned instead.
>
> Bug: v8:8965
> Change-Id: I560e89f353756df23c062fb8c9484d9971c19253
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1539078
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Commit-Queue: Ben Smith <binji@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#60473}
TBR=binji@chromium.org,mstarzinger@chromium.org
Change-Id: Iee528ac2f16988b25579af3555e6f17974cb0b05
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:8965
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1539498
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60474}
This commit is contained in:
parent
63608968b6
commit
470aaf6699
@ -1705,18 +1705,6 @@ class ThreadImpl {
|
||||
len += imm.length;
|
||||
return ok;
|
||||
}
|
||||
case kExprTableInit: {
|
||||
TableInitImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc));
|
||||
auto size = Pop().to<uint32_t>();
|
||||
auto src = Pop().to<uint32_t>();
|
||||
auto dst = Pop().to<uint32_t>();
|
||||
bool ok = WasmInstanceObject::InitTableEntries(
|
||||
instance_object_->GetIsolate(), instance_object_, imm.table.index,
|
||||
imm.elem_segment_index, dst, src, size);
|
||||
if (!ok) DoTrap(kTrapTableOutOfBounds, pc);
|
||||
len += imm.length;
|
||||
return ok;
|
||||
}
|
||||
case kExprTableCopy: {
|
||||
TableCopyImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc));
|
||||
auto size = Pop().to<uint32_t>();
|
||||
|
@ -27,9 +27,6 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace wasm {
|
||||
|
||||
// static
|
||||
const uint32_t WasmElemSegment::kNullIndex;
|
||||
|
||||
WireBytesRef WasmModule::LookupFunctionName(const ModuleWireBytes& wire_bytes,
|
||||
uint32_t function_index) const {
|
||||
if (!function_names) {
|
||||
|
@ -392,133 +392,6 @@ void CheckTableCall(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
}
|
||||
} // namespace
|
||||
|
||||
WASM_EXEC_TEST(TableInitElems) {
|
||||
EXPERIMENTAL_FLAG_SCOPE(bulk_memory);
|
||||
Isolate* isolate = CcTest::InitIsolateOnce();
|
||||
HandleScope scope(isolate);
|
||||
TestSignatures sigs;
|
||||
WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier);
|
||||
const uint32_t kTableSize = 5;
|
||||
std::vector<uint32_t> function_indexes;
|
||||
const uint32_t sig_index = r.builder().AddSignature(sigs.i_v());
|
||||
|
||||
for (uint32_t i = 0; i < kTableSize; ++i) {
|
||||
WasmFunctionCompiler& fn = r.NewFunction(sigs.i_v(), "f");
|
||||
BUILD(fn, WASM_I32V_1(i));
|
||||
fn.SetSigIndex(sig_index);
|
||||
function_indexes.push_back(fn.function_index());
|
||||
}
|
||||
|
||||
// Passive element segment has [f0, f1, f2, f3, f4, null].
|
||||
function_indexes.push_back(WasmElemSegment::kNullIndex);
|
||||
|
||||
r.builder().AddIndirectFunctionTable(nullptr, kTableSize);
|
||||
r.builder().AddPassiveElementSegment(function_indexes);
|
||||
|
||||
WasmFunctionCompiler& call = r.NewFunction(sigs.i_i(), "call");
|
||||
BUILD(call, WASM_CALL_INDIRECT0(sig_index, WASM_GET_LOCAL(0)));
|
||||
const uint32_t call_index = call.function_index();
|
||||
|
||||
BUILD(r,
|
||||
WASM_TABLE_INIT(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
|
||||
WASM_GET_LOCAL(2)),
|
||||
kExprI32Const, 0);
|
||||
|
||||
auto table = handle(
|
||||
WasmTableObject::cast(r.builder().instance_object()->tables().get(0)),
|
||||
isolate);
|
||||
const double null = 0xDEADBEEF;
|
||||
|
||||
CheckTableCall(isolate, table, r, call_index, null, null, null, null, null);
|
||||
|
||||
// 0 count is ok in bounds, and at end of regions.
|
||||
r.CheckCallViaJS(0, 0, 0, 0);
|
||||
r.CheckCallViaJS(0, kTableSize, 0, 0);
|
||||
r.CheckCallViaJS(0, 0, kTableSize, 0);
|
||||
|
||||
// Test actual writes.
|
||||
r.CheckCallViaJS(0, 0, 0, 1);
|
||||
CheckTableCall(isolate, table, r, call_index, 0, null, null, null, null);
|
||||
r.CheckCallViaJS(0, 0, 0, 2);
|
||||
CheckTableCall(isolate, table, r, call_index, 0, 1, null, null, null);
|
||||
r.CheckCallViaJS(0, 0, 0, 3);
|
||||
CheckTableCall(isolate, table, r, call_index, 0, 1, 2, null, null);
|
||||
r.CheckCallViaJS(0, 3, 0, 2);
|
||||
CheckTableCall(isolate, table, r, call_index, 0, 1, 2, 0, 1);
|
||||
r.CheckCallViaJS(0, 3, 1, 2);
|
||||
CheckTableCall(isolate, table, r, call_index, 0, 1, 2, 1, 2);
|
||||
r.CheckCallViaJS(0, 3, 2, 2);
|
||||
CheckTableCall(isolate, table, r, call_index, 0, 1, 2, 2, 3);
|
||||
r.CheckCallViaJS(0, 3, 3, 2);
|
||||
CheckTableCall(isolate, table, r, call_index, 0, 1, 2, 3, 4);
|
||||
}
|
||||
|
||||
WASM_EXEC_TEST(TableInitOob) {
|
||||
EXPERIMENTAL_FLAG_SCOPE(bulk_memory);
|
||||
Isolate* isolate = CcTest::InitIsolateOnce();
|
||||
HandleScope scope(isolate);
|
||||
TestSignatures sigs;
|
||||
WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_tier);
|
||||
const uint32_t kTableSize = 5;
|
||||
std::vector<uint32_t> function_indexes;
|
||||
const uint32_t sig_index = r.builder().AddSignature(sigs.i_v());
|
||||
|
||||
for (uint32_t i = 0; i < kTableSize; ++i) {
|
||||
WasmFunctionCompiler& fn = r.NewFunction(sigs.i_v(), "f");
|
||||
BUILD(fn, WASM_I32V_1(i));
|
||||
fn.SetSigIndex(sig_index);
|
||||
function_indexes.push_back(fn.function_index());
|
||||
}
|
||||
|
||||
r.builder().AddIndirectFunctionTable(nullptr, kTableSize);
|
||||
r.builder().AddPassiveElementSegment(function_indexes);
|
||||
|
||||
WasmFunctionCompiler& call = r.NewFunction(sigs.i_i(), "call");
|
||||
BUILD(call, WASM_CALL_INDIRECT0(sig_index, WASM_GET_LOCAL(0)));
|
||||
const uint32_t call_index = call.function_index();
|
||||
|
||||
BUILD(r,
|
||||
WASM_TABLE_INIT(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
|
||||
WASM_GET_LOCAL(2)),
|
||||
kExprI32Const, 0);
|
||||
|
||||
auto table = handle(
|
||||
WasmTableObject::cast(r.builder().instance_object()->tables().get(0)),
|
||||
isolate);
|
||||
const double null = 0xDEADBEEF;
|
||||
|
||||
CheckTableCall(isolate, table, r, call_index, null, null, null, null, null);
|
||||
|
||||
// Write all values up to the out-of-bounds write.
|
||||
r.CheckCallViaJS(0xDEADBEEF, 3, 0, 3);
|
||||
CheckTableCall(isolate, table, r, call_index, null, null, null, 0, 1);
|
||||
|
||||
// Write all values up to the out-of-bounds read.
|
||||
r.CheckCallViaJS(0xDEADBEEF, 0, 3, 3);
|
||||
CheckTableCall(isolate, table, r, call_index, 3, 4, null, 0, 1);
|
||||
|
||||
// 0-count is oob.
|
||||
r.CheckCallViaJS(0xDEADBEEF, kTableSize + 1, 0, 0);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 0, kTableSize + 1, 0);
|
||||
|
||||
r.CheckCallViaJS(0xDEADBEEF, 0, 0, 6);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 0, 1, 5);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 0, 2, 4);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 0, 3, 3);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 0, 4, 2);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 0, 5, 1);
|
||||
|
||||
r.CheckCallViaJS(0xDEADBEEF, 0, 0, 6);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 1, 0, 5);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 2, 0, 4);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 3, 0, 3);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 4, 0, 2);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 5, 0, 1);
|
||||
|
||||
r.CheckCallViaJS(0xDEADBEEF, 10, 0, 1);
|
||||
r.CheckCallViaJS(0xDEADBEEF, 0, 10, 1);
|
||||
}
|
||||
|
||||
WASM_EXEC_TEST(TableCopyElems) {
|
||||
EXPERIMENTAL_FLAG_SCOPE(bulk_memory);
|
||||
Isolate* isolate = CcTest::InitIsolateOnce();
|
||||
|
@ -266,15 +266,6 @@ uint32_t TestingModuleBuilder::AddPassiveDataSegment(Vector<const byte> bytes) {
|
||||
return index;
|
||||
}
|
||||
|
||||
uint32_t TestingModuleBuilder::AddPassiveElementSegment(
|
||||
const std::vector<uint32_t>& entries) {
|
||||
uint32_t index = static_cast<uint32_t>(test_module_->elem_segments.size());
|
||||
test_module_->elem_segments.emplace_back();
|
||||
auto& elem_segment = test_module_->elem_segments.back();
|
||||
elem_segment.entries = entries;
|
||||
return index;
|
||||
}
|
||||
|
||||
CompilationEnv TestingModuleBuilder::CreateCompilationEnv() {
|
||||
return {
|
||||
test_module_ptr_,
|
||||
|
@ -191,7 +191,6 @@ class TestingModuleBuilder {
|
||||
uint32_t AddException(FunctionSig* sig);
|
||||
|
||||
uint32_t AddPassiveDataSegment(Vector<const byte> bytes);
|
||||
uint32_t AddPassiveElementSegment(const std::vector<uint32_t>& entries);
|
||||
|
||||
WasmFunction* GetFunctionAt(int index) {
|
||||
return &test_module_->functions[index];
|
||||
@ -451,21 +450,18 @@ class WasmRunner : public WasmRunnerBase {
|
||||
: WasmRunner(execution_tier, nullptr, "main", kNoRuntimeExceptionSupport,
|
||||
lower_simd) {}
|
||||
|
||||
void SetUpTrapCallback() {
|
||||
WasmRunnerBase::trap_happened = false;
|
||||
auto trap_callback = []() -> void {
|
||||
WasmRunnerBase::trap_happened = true;
|
||||
set_trap_callback_for_testing(nullptr);
|
||||
};
|
||||
set_trap_callback_for_testing(trap_callback);
|
||||
}
|
||||
|
||||
ReturnType Call(ParamTypes... p) {
|
||||
DCHECK(compiled_);
|
||||
if (interpret()) return CallInterpreter(p...);
|
||||
|
||||
ReturnType return_value = static_cast<ReturnType>(0xDEADBEEFDEADBEEF);
|
||||
SetUpTrapCallback();
|
||||
WasmRunnerBase::trap_happened = false;
|
||||
|
||||
auto trap_callback = []() -> void {
|
||||
WasmRunnerBase::trap_happened = true;
|
||||
set_trap_callback_for_testing(nullptr);
|
||||
};
|
||||
set_trap_callback_for_testing(trap_callback);
|
||||
|
||||
wrapper_.SetInnerCode(builder_.GetFunctionCode(main_fn_index_));
|
||||
wrapper_.SetInstance(builder_.instance_object());
|
||||
@ -512,7 +508,6 @@ class WasmRunner : public WasmRunnerBase {
|
||||
void CheckCallApplyViaJS(double expected, uint32_t function_index,
|
||||
Handle<Object>* buffer, int count) {
|
||||
Isolate* isolate = builder_.isolate();
|
||||
SetUpTrapCallback();
|
||||
if (jsfuncs_.size() <= function_index) {
|
||||
jsfuncs_.resize(function_index + 1);
|
||||
}
|
||||
@ -525,7 +520,7 @@ class WasmRunner : public WasmRunnerBase {
|
||||
Execution::TryCall(isolate, jsfunc, global, count, buffer,
|
||||
Execution::MessageHandling::kReport, nullptr);
|
||||
|
||||
if (retval.is_null() || WasmRunnerBase::trap_happened) {
|
||||
if (retval.is_null()) {
|
||||
CHECK_EQ(expected, static_cast<double>(0xDEADBEEF));
|
||||
} else {
|
||||
Handle<Object> result = retval.ToHandleChecked();
|
||||
|
141
test/mjsunit/wasm/table-init.js
Normal file
141
test/mjsunit/wasm/table-init.js
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --experimental-wasm-bulk-memory
|
||||
|
||||
load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
function addFunction(builder, k) {
|
||||
let m = builder.addFunction("", kSig_i_v)
|
||||
.addBody([...wasmI32Const(k)]);
|
||||
return m;
|
||||
}
|
||||
|
||||
function addFunctions(builder, count) {
|
||||
let o = {};
|
||||
for (var i = 0; i < count; i++) {
|
||||
let name = `f${i}`;
|
||||
o[name] = addFunction(builder, i);
|
||||
o[name].exportAs(name);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
function assertTable(obj, ...elems) {
|
||||
for (var i = 0; i < elems.length; i++) {
|
||||
assertEquals(elems[i], obj.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
(function TestTableInitInBounds() {
|
||||
print(arguments.callee.name);
|
||||
let builder = new WasmModuleBuilder();
|
||||
let sig_v_iii = builder.addType(kSig_v_iii);
|
||||
let kTableSize = 5;
|
||||
|
||||
builder.setTableBounds(kTableSize, kTableSize);
|
||||
{
|
||||
let o = addFunctions(builder, kTableSize);
|
||||
builder.addPassiveElementSegment(
|
||||
[o.f0.index, o.f1.index, o.f2.index, o.f3.index, o.f4.index, null]);
|
||||
}
|
||||
|
||||
builder.addFunction("init0", sig_v_iii)
|
||||
.addBody([
|
||||
kExprGetLocal, 0,
|
||||
kExprGetLocal, 1,
|
||||
kExprGetLocal, 2,
|
||||
kNumericPrefix, kExprTableInit, kSegmentZero, kTableZero])
|
||||
.exportAs("init0");
|
||||
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
|
||||
let instance = builder.instantiate();
|
||||
let x = instance.exports;
|
||||
|
||||
assertTable(x.table, null, null, null, null, null);
|
||||
|
||||
// 0 count is ok in bounds, and at end of regions.
|
||||
x.init0(0, 0, 0);
|
||||
x.init0(kTableSize, 0, 0);
|
||||
x.init0(0, kTableSize, 0);
|
||||
|
||||
// test actual writes.
|
||||
x.init0(0, 0, 1);
|
||||
assertTable(x.table, x.f0, null, null, null, null);
|
||||
x.init0(0, 0, 2);
|
||||
assertTable(x.table, x.f0, x.f1, null, null, null);
|
||||
x.init0(0, 0, 3);
|
||||
assertTable(x.table, x.f0, x.f1, x.f2, null, null);
|
||||
x.init0(3, 0, 2);
|
||||
assertTable(x.table, x.f0, x.f1, x.f2, x.f0, x.f1);
|
||||
x.init0(3, 1, 2);
|
||||
assertTable(x.table, x.f0, x.f1, x.f2, x.f1, x.f2);
|
||||
x.init0(3, 2, 2);
|
||||
assertTable(x.table, x.f0, x.f1, x.f2, x.f2, x.f3);
|
||||
x.init0(3, 3, 2);
|
||||
assertTable(x.table, x.f0, x.f1, x.f2, x.f3, x.f4);
|
||||
|
||||
// test writing null
|
||||
x.init0(0, 5, 1);
|
||||
assertTable(x.table, null, x.f1, x.f2, x.f3, x.f4);
|
||||
})();
|
||||
|
||||
(function TestTableInitOob() {
|
||||
print(arguments.callee.name);
|
||||
let builder = new WasmModuleBuilder();
|
||||
let sig_v_iii = builder.addType(kSig_v_iii);
|
||||
let kTableSize = 5;
|
||||
|
||||
builder.setTableBounds(kTableSize, kTableSize);
|
||||
{
|
||||
let o = addFunctions(builder, kTableSize);
|
||||
builder.addPassiveElementSegment(
|
||||
[o.f0.index, o.f1.index, o.f2.index, o.f3.index, o.f4.index]);
|
||||
}
|
||||
|
||||
builder.addFunction("init0", sig_v_iii)
|
||||
.addBody([
|
||||
kExprGetLocal, 0,
|
||||
kExprGetLocal, 1,
|
||||
kExprGetLocal, 2,
|
||||
kNumericPrefix, kExprTableInit, kSegmentZero, kTableZero])
|
||||
.exportAs("init0");
|
||||
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
|
||||
let instance = builder.instantiate();
|
||||
let x = instance.exports;
|
||||
|
||||
assertTable(x.table, null, null, null, null, null);
|
||||
|
||||
// Write all values up to the out-of-bounds write.
|
||||
assertThrows(() => x.init0(3, 0, 3));
|
||||
assertTable(x.table, null, null, null, x.f0, x.f1);
|
||||
|
||||
// Write all values up to the out-of-bounds read.
|
||||
assertThrows(() => x.init0(0, 3, 3));
|
||||
assertTable(x.table, x.f3, x.f4, null, x.f0, x.f1);
|
||||
|
||||
// 0-count is oob.
|
||||
assertThrows(() => x.init0(kTableSize+1, 0, 0));
|
||||
assertThrows(() => x.init0(0, kTableSize+1, 0));
|
||||
|
||||
assertThrows(() => x.init0(0, 0, 6));
|
||||
assertThrows(() => x.init0(0, 1, 5));
|
||||
assertThrows(() => x.init0(0, 2, 4));
|
||||
assertThrows(() => x.init0(0, 3, 3));
|
||||
assertThrows(() => x.init0(0, 4, 2));
|
||||
assertThrows(() => x.init0(0, 5, 1));
|
||||
|
||||
assertThrows(() => x.init0(0, 0, 6));
|
||||
assertThrows(() => x.init0(1, 0, 5));
|
||||
assertThrows(() => x.init0(2, 0, 4));
|
||||
assertThrows(() => x.init0(3, 0, 3));
|
||||
assertThrows(() => x.init0(4, 0, 2));
|
||||
assertThrows(() => x.init0(5, 0, 1));
|
||||
|
||||
assertThrows(() => x.init0(10, 0, 1));
|
||||
assertThrows(() => x.init0(0, 10, 1));
|
||||
})();
|
Loading…
Reference in New Issue
Block a user