Reland "[atomics] Wire up 64 bit atomic Wait in JS"

Relands 64bit atomic wait with ubsan fix, previously reviewed at:
https://chromium-review.googlesource.com/c/v8/v8/+/1728260

This reverts commit 2a383f4cf1.

Bug: v8:8100, v8:9576
Change-Id: Ibeec86c8a796bfbef9884cdb836892e902030bf3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1733389
Commit-Queue: Joshua Litt <joshualitt@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63059}
This commit is contained in:
Joshua Litt 2019-08-02 08:13:15 -07:00 committed by Commit Bot
parent 8ab0eed20c
commit 91e53e2695
5 changed files with 83 additions and 24 deletions

View File

@ -37,12 +37,16 @@ BUILTIN(AtomicsIsLockFree) {
// ES #sec-validatesharedintegertypedarray
V8_WARN_UNUSED_RESULT MaybeHandle<JSTypedArray> ValidateSharedIntegerTypedArray(
Isolate* isolate, Handle<Object> object, bool only_int32 = false) {
Isolate* isolate, Handle<Object> object,
bool only_int32_and_big_int64 = false) {
if (object->IsJSTypedArray()) {
Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object);
if (typed_array->GetBuffer()->is_shared()) {
if (only_int32) {
if (typed_array->type() == kExternalInt32Array) return typed_array;
if (only_int32_and_big_int64) {
if (typed_array->type() == kExternalInt32Array ||
typed_array->type() == kExternalBigInt64Array) {
return typed_array;
}
} else {
if (typed_array->type() != kExternalFloat32Array &&
typed_array->type() != kExternalFloat64Array &&
@ -54,8 +58,9 @@ V8_WARN_UNUSED_RESULT MaybeHandle<JSTypedArray> ValidateSharedIntegerTypedArray(
THROW_NEW_ERROR(
isolate,
NewTypeError(only_int32 ? MessageTemplate::kNotInt32SharedTypedArray
: MessageTemplate::kNotIntegerSharedTypedArray,
NewTypeError(only_int32_and_big_int64
? MessageTemplate::kNotInt32OrBigInt64SharedTypedArray
: MessageTemplate::kNotIntegerSharedTypedArray,
object),
JSTypedArray);
}
@ -83,6 +88,15 @@ V8_WARN_UNUSED_RESULT Maybe<size_t> ValidateAtomicAccess(
}
namespace {
inline size_t GetAddress64(size_t index, size_t byte_offset) {
return (index << 3) + byte_offset;
}
inline size_t GetAddress32(size_t index, size_t byte_offset) {
return (index << 2) + byte_offset;
}
MaybeHandle<Object> AtomicsWake(Isolate* isolate, Handle<Object> array,
Handle<Object> index, Handle<Object> count) {
Handle<JSTypedArray> sta;
@ -109,9 +123,19 @@ MaybeHandle<Object> AtomicsWake(Isolate* isolate, Handle<Object> array,
}
Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
size_t addr = (i << 2) + sta->byte_offset();
return Handle<Object>(FutexEmulation::Wake(array_buffer, addr, c), isolate);
if (sta->type() == kExternalBigInt64Array) {
return Handle<Object>(
FutexEmulation::Wake(array_buffer, GetAddress64(i, sta->byte_offset()),
c),
isolate);
} else {
DCHECK(sta->type() == kExternalInt32Array);
return Handle<Object>(
FutexEmulation::Wake(array_buffer, GetAddress32(i, sta->byte_offset()),
c),
isolate);
}
}
} // namespace
@ -157,9 +181,16 @@ BUILTIN(AtomicsWait) {
if (maybe_index.IsNothing()) return ReadOnlyRoots(isolate).exception();
size_t i = maybe_index.FromJust();
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
Object::ToInt32(isolate, value));
int32_t value_int32 = NumberToInt32(*value);
// According to the spec, we have to check value's type before
// looking at the timeout.
if (sta->type() == kExternalBigInt64Array) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
BigInt::FromObject(isolate, value));
} else {
DCHECK(sta->type() == kExternalInt32Array);
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
Object::ToInt32(isolate, value));
}
double timeout_number;
if (timeout->IsUndefined(isolate)) {
@ -180,10 +211,17 @@ BUILTIN(AtomicsWait) {
}
Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
size_t addr = (i << 2) + sta->byte_offset();
return FutexEmulation::WaitJs(isolate, array_buffer, addr, value_int32,
timeout_number);
if (sta->type() == kExternalBigInt64Array) {
return FutexEmulation::WaitJs64(
isolate, array_buffer, GetAddress64(i, sta->byte_offset()),
Handle<BigInt>::cast(value)->AsInt64(), timeout_number);
} else {
DCHECK(sta->type() == kExternalInt32Array);
return FutexEmulation::WaitJs32(isolate, array_buffer,
GetAddress32(i, sta->byte_offset()),
NumberToInt32(*value), timeout_number);
}
}
} // namespace internal

View File

@ -146,7 +146,8 @@ namespace internal {
T(NotSuperConstructorAnonymousClass, \
"Super constructor % of anonymous class is not a constructor") \
T(NotIntegerSharedTypedArray, "% is not an integer shared typed array.") \
T(NotInt32SharedTypedArray, "% is not an int32 shared typed array.") \
T(NotInt32OrBigInt64SharedTypedArray, \
"% is not an int32 or BigInt64 shared typed array.") \
T(ObjectGetterExpectingFunction, \
"Object.prototype.__defineGetter__: Expecting function") \
T(ObjectGetterCallable, "Getter must be a function: %") \

View File

@ -11,6 +11,7 @@
#include "src/execution/isolate.h"
#include "src/handles/handles-inl.h"
#include "src/numbers/conversions.h"
#include "src/objects/bigint.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/objects-inl.h"
@ -80,10 +81,9 @@ void AtomicsWaitWakeHandle::Wake() {
enum WaitReturnValue : int { kOk = 0, kNotEqual = 1, kTimedOut = 2 };
Object FutexEmulation::WaitJs(Isolate* isolate,
Handle<JSArrayBuffer> array_buffer, size_t addr,
int32_t value, double rel_timeout_ms) {
Object res = Wait32(isolate, array_buffer, addr, value, rel_timeout_ms);
namespace {
Object WaitJsTranslateReturn(Isolate* isolate, Object res) {
if (res.IsSmi()) {
int val = Smi::ToInt(res);
switch (val) {
@ -100,6 +100,22 @@ Object FutexEmulation::WaitJs(Isolate* isolate,
return res;
}
} // namespace
Object FutexEmulation::WaitJs32(Isolate* isolate,
Handle<JSArrayBuffer> array_buffer, size_t addr,
int32_t value, double rel_timeout_ms) {
Object res = Wait32(isolate, array_buffer, addr, value, rel_timeout_ms);
return WaitJsTranslateReturn(isolate, res);
}
Object FutexEmulation::WaitJs64(Isolate* isolate,
Handle<JSArrayBuffer> array_buffer, size_t addr,
int64_t value, double rel_timeout_ms) {
Object res = Wait64(isolate, array_buffer, addr, value, rel_timeout_ms);
return WaitJsTranslateReturn(isolate, res);
}
Object FutexEmulation::Wait32(Isolate* isolate,
Handle<JSArrayBuffer> array_buffer, size_t addr,
int32_t value, double rel_timeout_ms) {

View File

@ -117,8 +117,12 @@ class FutexEmulation : public AllStatic {
// |rel_timeout_ms| can be Infinity.
// If woken, return "ok", otherwise return "timed-out". The initial check and
// the decision to wait happen atomically.
static Object WaitJs(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
size_t addr, int32_t value, double rel_timeout_ms);
static Object WaitJs32(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
size_t addr, int32_t value, double rel_timeout_ms);
// An version of WaitJs32 for int64_t values.
static Object WaitJs64(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
size_t addr, int64_t value, double rel_timeout_ms);
// Same as WaitJs above except it returns 0 (ok), 1 (not equal) and 2 (timed
// out) as expected by Wasm.

View File

@ -450,10 +450,6 @@
'built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds': [FAIL],
'built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-out-of-bounds': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=8100
'built-ins/Atomics/notify/bigint/*': [SKIP],
'built-ins/Atomics/wait/bigint/*': [SKIP],
# https://bugs.chromium.org/p/v8/issues/detail?id=6049
'built-ins/Object/internals/DefineOwnProperty/consistent-value-function-caller': [FAIL_SLOPPY],
'built-ins/Object/internals/DefineOwnProperty/consistent-value-function-arguments': [FAIL_SLOPPY],
@ -571,7 +567,11 @@
######################## NEEDS INVESTIGATION ###########################
# https://bugs.chromium.org/p/v8/issues/detail?id=7833
#
# Test262 needs to expose CanBlock
'built-ins/Atomics/wait/bigint/cannot-suspend-throws': [SKIP],
'built-ins/Atomics/wait/cannot-suspend-throws': [SKIP],
# Flaky
'built-ins/Atomics/wait/undefined-index-defaults-to-zero': [SKIP],
##################### DELIBERATE INCOMPATIBILITIES #####################