Commit aa3422b6 authored by binji's avatar binji Committed by Commit bot

[SAB] Fix crash in Atomics.wake w/ infinite count.

Also if the count is not specified, it should wake all waiters.

BUG=v8:4777

Review-Url: https://codereview.chromium.org/2659083004
Cr-Commit-Position: refs/heads/master@{#42871}
parent 6a82fe90
...@@ -188,10 +188,9 @@ Object* FutexEmulation::Wait(Isolate* isolate, ...@@ -188,10 +188,9 @@ Object* FutexEmulation::Wait(Isolate* isolate,
return result; return result;
} }
Object* FutexEmulation::Wake(Isolate* isolate, Object* FutexEmulation::Wake(Isolate* isolate,
Handle<JSArrayBuffer> array_buffer, size_t addr, Handle<JSArrayBuffer> array_buffer, size_t addr,
int num_waiters_to_wake) { uint32_t num_waiters_to_wake) {
DCHECK(addr < NumberToSize(array_buffer->byte_length())); DCHECK(addr < NumberToSize(array_buffer->byte_length()));
int waiters_woken = 0; int waiters_woken = 0;
...@@ -203,7 +202,9 @@ Object* FutexEmulation::Wake(Isolate* isolate, ...@@ -203,7 +202,9 @@ Object* FutexEmulation::Wake(Isolate* isolate,
if (backing_store == node->backing_store_ && addr == node->wait_addr_) { if (backing_store == node->backing_store_ && addr == node->wait_addr_) {
node->waiting_ = false; node->waiting_ = false;
node->cond_.NotifyOne(); node->cond_.NotifyOne();
--num_waiters_to_wake; if (num_waiters_to_wake != kWakeAll) {
--num_waiters_to_wake;
}
waiters_woken++; waiters_woken++;
} }
......
...@@ -82,6 +82,9 @@ class FutexWaitList { ...@@ -82,6 +82,9 @@ class FutexWaitList {
class FutexEmulation : public AllStatic { class FutexEmulation : public AllStatic {
public: public:
// Pass to Wake() to wake all waiters.
static const uint32_t kWakeAll = UINT32_MAX;
// Check that array_buffer[addr] == value, and return "not-equal" if not. If // Check that array_buffer[addr] == value, and return "not-equal" if not. If
// they are equal, block execution on |isolate|'s thread until woken via // they are equal, block execution on |isolate|'s thread until woken via
// |Wake|, or when the time given in |rel_timeout_ms| elapses. Note that // |Wake|, or when the time given in |rel_timeout_ms| elapses. Note that
...@@ -92,10 +95,11 @@ class FutexEmulation : public AllStatic { ...@@ -92,10 +95,11 @@ class FutexEmulation : public AllStatic {
size_t addr, int32_t value, double rel_timeout_ms); size_t addr, int32_t value, double rel_timeout_ms);
// Wake |num_waiters_to_wake| threads that are waiting on the given |addr|. // Wake |num_waiters_to_wake| threads that are waiting on the given |addr|.
// The rest of the waiters will continue to wait. The return value is the // |num_waiters_to_wake| can be kWakeAll, in which case all waiters are
// number of woken waiters. // woken. The rest of the waiters will continue to wait. The return value is
// the number of woken waiters.
static Object* Wake(Isolate* isolate, Handle<JSArrayBuffer> array_buffer, static Object* Wake(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
size_t addr, int num_waiters_to_wake); size_t addr, uint32_t num_waiters_to_wake);
// Return the number of threads waiting on |addr|. Should only be used for // Return the number of threads waiting on |addr|. Should only be used for
// testing. // testing.
......
...@@ -13,10 +13,12 @@ ...@@ -13,10 +13,12 @@
var GlobalObject = global.Object; var GlobalObject = global.Object;
var MaxSimple; var MaxSimple;
var MinSimple;
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
utils.Import(function(from) { utils.Import(function(from) {
MaxSimple = from.MaxSimple; MaxSimple = from.MaxSimple;
MinSimple = from.MinSimple;
}); });
// ------------------------------------------------------------------- // -------------------------------------------------------------------
...@@ -123,7 +125,12 @@ function AtomicsWaitJS(ia, index, value, timeout) { ...@@ -123,7 +125,12 @@ function AtomicsWaitJS(ia, index, value, timeout) {
function AtomicsWakeJS(ia, index, count) { function AtomicsWakeJS(ia, index, count) {
CheckSharedInteger32TypedArray(ia); CheckSharedInteger32TypedArray(ia);
index = ValidateIndex(index, %_TypedArrayGetLength(ia)); index = ValidateIndex(index, %_TypedArrayGetLength(ia));
count = MaxSimple(0, TO_INTEGER(count)); if (IS_UNDEFINED(count)) {
count = kMaxUint32;
} else {
// Clamp to [0, kMaxUint32].
count = MinSimple(MaxSimple(0, TO_INTEGER(count)), kMaxUint32);
}
return %AtomicsWake(ia, index, count); return %AtomicsWake(ia, index, count);
} }
......
...@@ -45,7 +45,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsWake) { ...@@ -45,7 +45,7 @@ RUNTIME_FUNCTION(Runtime_AtomicsWake) {
DCHECK_EQ(3, args.length()); DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0); CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
CONVERT_SIZE_ARG_CHECKED(index, 1); CONVERT_SIZE_ARG_CHECKED(index, 1);
CONVERT_INT32_ARG_CHECKED(count, 2); CONVERT_UINT32_ARG_CHECKED(count, 2);
CHECK(sta->GetBuffer()->is_shared()); CHECK(sta->GetBuffer()->is_shared());
CHECK_LT(index, NumberToSize(sta->length())); CHECK_LT(index, NumberToSize(sta->length()));
CHECK_EQ(sta->type(), kExternalInt32Array); CHECK_EQ(sta->type(), kExternalInt32Array);
......
...@@ -104,6 +104,11 @@ ...@@ -104,6 +104,11 @@
%SetAllowAtomicsWait(true); %SetAllowAtomicsWait(true);
})(); })();
(function TestWakePositiveInfinity() {
var i32a = new Int32Array(new SharedArrayBuffer(16));
Atomics.wake(i32a, 0, Number.POSITIVE_INFINITY);
})();
//// WORKER ONLY TESTS //// WORKER ONLY TESTS
if (this.Worker) { if (this.Worker) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment