diff --git a/src/wasm/wasm-objects.cc b/src/wasm/wasm-objects.cc index 7d5da2737d..00342d8df7 100644 --- a/src/wasm/wasm-objects.cc +++ b/src/wasm/wasm-objects.cc @@ -1415,10 +1415,18 @@ Address WasmInstanceObject::GetCallTarget(uint32_t func_index) { namespace { void CopyTableEntriesImpl(Handle instance, uint32_t dst, uint32_t src, uint32_t count) { - for (uint32_t i = 0; i < count; i++) { - auto from_entry = IndirectFunctionTableEntry(instance, dst + i); - auto to_entry = IndirectFunctionTableEntry(instance, src + i); - from_entry.CopyFrom(to_entry); + if (src < dst) { + for (uint32_t i = count; i > 0; i--) { + auto to_entry = IndirectFunctionTableEntry(instance, dst + i - 1); + auto from_entry = IndirectFunctionTableEntry(instance, src + i - 1); + to_entry.CopyFrom(from_entry); + } + } else { + for (uint32_t i = 0; i < count; i++) { + auto to_entry = IndirectFunctionTableEntry(instance, dst + i); + auto from_entry = IndirectFunctionTableEntry(instance, src + i); + to_entry.CopyFrom(from_entry); + } } } } // namespace @@ -1429,9 +1437,11 @@ bool WasmInstanceObject::CopyTableEntries(Isolate* isolate, uint32_t table_index, uint32_t dst, uint32_t src, uint32_t count) { CHECK_EQ(0, table_index); // TODO(titzer): multiple tables in TableCopy + if (count == 0) return true; // no-op auto max = instance->indirect_function_table_size(); if (dst > max || count > (max - dst)) return false; // out-of-bounds if (src > max || count > (max - src)) return false; // out-of-bounds + if (dst == src) return true; // no-op if (!instance->has_table_object()) { // No table object, only need to update this instance. @@ -1454,8 +1464,14 @@ bool WasmInstanceObject::CopyTableEntries(Isolate* isolate, // Copy the function entries. Handle functions(table->functions(), isolate); - for (uint32_t i = 0; i < count; i++) { - functions->set(dst + i, functions->get(src + i)); + if (src < dst) { + for (uint32_t i = count; i > 0; i--) { + functions->set(dst + i - 1, functions->get(src + i - 1)); + } + } else { + for (uint32_t i = 0; i < count; i++) { + functions->set(dst + i, functions->get(src + i)); + } } return true; } diff --git a/test/mjsunit/wasm/table-copy.js b/test/mjsunit/wasm/table-copy.js index d4fda45ab4..89572fa41e 100644 --- a/test/mjsunit/wasm/table-copy.js +++ b/test/mjsunit/wasm/table-copy.js @@ -30,6 +30,9 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); copy(0, i, kTableSize - i); copy(i, 0, kTableSize - i); } + let big = 1000000; + copy(big, 0, 0); // nop + copy(0, big, 0); // nop })(); function addFunction(builder, k) { @@ -94,6 +97,8 @@ function assertTable(obj, ...elems) { assertTable(table, f1, f2, f2, f3, f4); copy(3, 0, 2); assertTable(table, f1, f2, f2, f1, f2); + copy(1, 0, 2); + assertTable(table, f1, f1, f2, f1, f2); })(); function assertCall(call, ...elems) {