Fix Wasm atomic waits on big endian platforms
Wasm values are stored in memory in little endian order even on BE machines and as a result they need to be manually reversed after a load. Other such atomic ops get patched during Wasm compilation or during code-gen, this is one of the few places where a runtime call is made to C++ which requires this fix. As the the runtime stub is used on both TurboFan and Liftoff this patch will fix both cases. Up until now the cctest was passing incorrectly as it's mixing the Wasm memory buffer with TypedArrays. TypedArrays don't have the LE enforcement and use the native byte order. With this patch the test is now failing as expected and is being skipped for now. Bug: v8:12505 Change-Id: I49fac208f1fab7396b7d9911e803bc047b3b8263 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3350744 Reviewed-by: Andreas Haas <ahaas@chromium.org> Reviewed-by: Shu-yu Guo <syg@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Commit-Queue: Milad Farazmand <mfarazma@redhat.com> Cr-Commit-Position: refs/heads/main@{#78433}
This commit is contained in:
parent
099cb420b9
commit
183a2abc21
@ -297,7 +297,7 @@ Object FutexEmulation::WaitWasm32(Isolate* isolate,
|
||||
size_t addr, int32_t value,
|
||||
int64_t rel_timeout_ns) {
|
||||
return Wait<int32_t>(isolate, WaitMode::kSync, array_buffer, addr, value,
|
||||
rel_timeout_ns >= 0, rel_timeout_ns);
|
||||
rel_timeout_ns >= 0, rel_timeout_ns, CallType::kIsWasm);
|
||||
}
|
||||
|
||||
Object FutexEmulation::WaitWasm64(Isolate* isolate,
|
||||
@ -305,7 +305,7 @@ Object FutexEmulation::WaitWasm64(Isolate* isolate,
|
||||
size_t addr, int64_t value,
|
||||
int64_t rel_timeout_ns) {
|
||||
return Wait<int64_t>(isolate, WaitMode::kSync, array_buffer, addr, value,
|
||||
rel_timeout_ns >= 0, rel_timeout_ns);
|
||||
rel_timeout_ns >= 0, rel_timeout_ns, CallType::kIsWasm);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -346,21 +346,22 @@ double WaitTimeoutInMs(double timeout_ns) {
|
||||
template <typename T>
|
||||
Object FutexEmulation::Wait(Isolate* isolate, WaitMode mode,
|
||||
Handle<JSArrayBuffer> array_buffer, size_t addr,
|
||||
T value, bool use_timeout, int64_t rel_timeout_ns) {
|
||||
T value, bool use_timeout, int64_t rel_timeout_ns,
|
||||
CallType call_type) {
|
||||
if (mode == WaitMode::kSync) {
|
||||
return WaitSync(isolate, array_buffer, addr, value, use_timeout,
|
||||
rel_timeout_ns);
|
||||
rel_timeout_ns, call_type);
|
||||
}
|
||||
DCHECK_EQ(mode, WaitMode::kAsync);
|
||||
return WaitAsync(isolate, array_buffer, addr, value, use_timeout,
|
||||
rel_timeout_ns);
|
||||
rel_timeout_ns, call_type);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Object FutexEmulation::WaitSync(Isolate* isolate,
|
||||
Handle<JSArrayBuffer> array_buffer, size_t addr,
|
||||
T value, bool use_timeout,
|
||||
int64_t rel_timeout_ns) {
|
||||
int64_t rel_timeout_ns, CallType call_type) {
|
||||
VMState<ATOMICS_WAIT> state(isolate);
|
||||
base::TimeDelta rel_timeout =
|
||||
base::TimeDelta::FromNanoseconds(rel_timeout_ns);
|
||||
@ -398,7 +399,15 @@ Object FutexEmulation::WaitSync(Isolate* isolate,
|
||||
FutexWaitListNode::ResetWaitingOnScopeExit reset_waiting(node);
|
||||
|
||||
std::atomic<T>* p = reinterpret_cast<std::atomic<T>*>(wait_location);
|
||||
if (p->load() != value) {
|
||||
T loaded_value = p->load();
|
||||
#if defined(V8_TARGET_BIG_ENDIAN)
|
||||
// If loading a Wasm value, it needs to be reversed on Big Endian platforms.
|
||||
if (call_type == CallType::kIsWasm) {
|
||||
DCHECK(sizeof(T) == kInt32Size || sizeof(T) == kInt64Size);
|
||||
loaded_value = ByteReverse(loaded_value);
|
||||
}
|
||||
#endif
|
||||
if (loaded_value != value) {
|
||||
result = handle(Smi::FromInt(WaitReturnValue::kNotEqual), isolate);
|
||||
callback_result = AtomicsWaitEvent::kNotEqual;
|
||||
break;
|
||||
@ -523,7 +532,7 @@ template <typename T>
|
||||
Object FutexEmulation::WaitAsync(Isolate* isolate,
|
||||
Handle<JSArrayBuffer> array_buffer,
|
||||
size_t addr, T value, bool use_timeout,
|
||||
int64_t rel_timeout_ns) {
|
||||
int64_t rel_timeout_ns, CallType call_type) {
|
||||
base::TimeDelta rel_timeout =
|
||||
base::TimeDelta::FromNanoseconds(rel_timeout_ns);
|
||||
|
||||
@ -543,7 +552,15 @@ Object FutexEmulation::WaitAsync(Isolate* isolate,
|
||||
// 17. Let w be ! AtomicLoad(typedArray, i).
|
||||
std::atomic<T>* p = reinterpret_cast<std::atomic<T>*>(
|
||||
static_cast<int8_t*>(backing_store->buffer_start()) + addr);
|
||||
if (p->load() != value) {
|
||||
T loaded_value = p->load();
|
||||
#if defined(V8_TARGET_BIG_ENDIAN)
|
||||
// If loading a Wasm value, it needs to be reversed on Big Endian platforms.
|
||||
if (call_type == CallType::kIsWasm) {
|
||||
DCHECK(sizeof(T) == kInt32Size || sizeof(T) == kInt64Size);
|
||||
loaded_value = ByteReverse(loaded_value);
|
||||
}
|
||||
#endif
|
||||
if (loaded_value != value) {
|
||||
result_kind = ResultKind::kNotEqual;
|
||||
} else if (use_timeout && rel_timeout_ns == 0) {
|
||||
result_kind = ResultKind::kTimedOut;
|
||||
|
@ -141,6 +141,7 @@ class FutexWaitListNode {
|
||||
class FutexEmulation : public AllStatic {
|
||||
public:
|
||||
enum WaitMode { kSync = 0, kAsync };
|
||||
enum class CallType { kIsNotWasm = 0, kIsWasm };
|
||||
|
||||
// Pass to Wake() to wake all waiters.
|
||||
static const uint32_t kWakeAll = UINT32_MAX;
|
||||
@ -214,17 +215,18 @@ class FutexEmulation : public AllStatic {
|
||||
template <typename T>
|
||||
static Object Wait(Isolate* isolate, WaitMode mode,
|
||||
Handle<JSArrayBuffer> array_buffer, size_t addr, T value,
|
||||
bool use_timeout, int64_t rel_timeout_ns);
|
||||
bool use_timeout, int64_t rel_timeout_ns,
|
||||
CallType call_type = CallType::kIsNotWasm);
|
||||
|
||||
template <typename T>
|
||||
static Object WaitSync(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
|
||||
size_t addr, T value, bool use_timeout,
|
||||
int64_t rel_timeout_ns);
|
||||
int64_t rel_timeout_ns, CallType call_type);
|
||||
|
||||
template <typename T>
|
||||
static Object WaitAsync(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
|
||||
size_t addr, T value, bool use_timeout,
|
||||
int64_t rel_timeout_ns);
|
||||
int64_t rel_timeout_ns, CallType call_type);
|
||||
|
||||
// Resolve the Promises of the async waiters which belong to |isolate|.
|
||||
static void ResolveAsyncWaiterPromises(Isolate* isolate);
|
||||
|
@ -282,6 +282,9 @@
|
||||
|
||||
##############################################################################
|
||||
['byteorder == big', {
|
||||
# BUG(v8:12505). Tests which share Wasm memory buffer with Js Typed arrays.
|
||||
'test-api/WasmI32AtomicWaitCallback': [SKIP],
|
||||
'test-api/WasmI64AtomicWaitCallback': [SKIP],
|
||||
# Peephole optimization not supported on big-endian machines.
|
||||
'test-regexp/Peephole*': [SKIP],
|
||||
}], # 'byteorder == big'
|
||||
|
Loading…
Reference in New Issue
Block a user