Skip to content

Commit

Permalink
[wasm] Implement memory.{copy,fill} explicitly
Browse files Browse the repository at this point in the history
V8's MemMove and libc's memset do not specify how the memory is filled,
but wasm requires the direction to be backward only when the regions are
overlapping and the source address is less than the destination address.

Bug: v8:8950
Change-Id: If392967b51b33ad65fe145660f44b857559e34b1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1507316
Commit-Queue: Ben Smith <binji@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60106}
  • Loading branch information
binji authored and Commit Bot committed Mar 7, 2019
1 parent a510cea commit 1f5ece9
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 additions & 2 deletions src/wasm/wasm-external-refs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,36 @@ void float64_pow_wrapper(Address data) {
}

void memory_copy_wrapper(Address dst, Address src, uint32_t size) {
MemMove(reinterpret_cast<void*>(dst), reinterpret_cast<void*>(src), size);
// Use explicit forward and backward copy to match the required semantics for
// the memory.copy instruction. It is assumed that the caller of this
// function has already performed bounds checks, so {src + size} and
// {dst + size} should not overflow.
DCHECK(src + size >= src && dst + size >= dst);
uint8_t* dst8 = reinterpret_cast<uint8_t*>(dst);
uint8_t* src8 = reinterpret_cast<uint8_t*>(src);
if (src < dst && src + size > dst && dst + size > src) {
dst8 += size - 1;
src8 += size - 1;
for (; size > 0; size--) {
*dst8-- = *src8--;
}
} else {
for (; size > 0; size--) {
*dst8++ = *src8++;
}
}
}

void memory_fill_wrapper(Address dst, uint32_t value, uint32_t size) {
memset(reinterpret_cast<void*>(dst), value, size);
// Use an explicit forward copy to match the required semantics for the
// memory.fill instruction. It is assumed that the caller of this function
// has already performed bounds checks, so {dst + size} should not overflow.
DCHECK(dst + size >= dst);
uint8_t* dst8 = reinterpret_cast<uint8_t*>(dst);
uint8_t value8 = static_cast<uint8_t>(value);
for (; size > 0; size--) {
*dst8++ = value8;
}
}

static WasmTrapCallbackForTesting wasm_trap_callback_for_testing = nullptr;
Expand Down

0 comments on commit 1f5ece9

Please sign in to comment.