Add Isolate parameter to disallow Atomics.wait

Atomics.wait is a function which may block, which is not allowed on the
main thread. Since V8 doesn't know whether a particular isolate is the
"main thread", this CL adds an option to Isolate::CreateParams to choose
whether this function is allowed.

Review-Url: https://codereview.chromium.org/2642293002
Cr-Commit-Position: refs/heads/master@{#42611}
This commit is contained in:
binji 2017-01-23 14:06:12 -08:00 committed by Commit bot
parent 67244dcef1
commit 6eba6b4b89
9 changed files with 45 additions and 7 deletions

View File

@ -6345,7 +6345,8 @@ class V8_EXPORT Isolate {
create_histogram_callback(nullptr),
add_histogram_sample_callback(nullptr),
array_buffer_allocator(nullptr),
external_references(nullptr) {}
external_references(nullptr),
allow_atomics_wait(true) {}
/**
* The optional entry_hook allows the host application to provide the
@ -6401,6 +6402,12 @@ class V8_EXPORT Isolate {
* entire lifetime of the isolate.
*/
intptr_t* external_references;
/**
* Whether calling Atomics.wait (a function that may block) is allowed in
* this isolate.
*/
bool allow_atomics_wait;
};

View File

@ -8121,6 +8121,7 @@ Isolate* Isolate::New(const Isolate::CreateParams& params) {
}
isolate->set_api_external_references(params.external_references);
isolate->set_allow_atomics_wait(params.allow_atomics_wait);
SetResourceConstraints(isolate, params.constraints);
// TODO(jochen): Once we got rid of Isolate::Current(), we can remove this.
Isolate::Scope isolate_scope(v8_isolate);

View File

@ -1194,6 +1194,9 @@ class Isolate {
base::Mutex* simulator_i_cache_mutex() { return &simulator_i_cache_mutex_; }
#endif
void set_allow_atomics_wait(bool set) { allow_atomics_wait_ = set; }
bool allow_atomics_wait() { return allow_atomics_wait_; }
protected:
explicit Isolate(bool enable_serializer);
bool IsArrayOrObjectPrototype(Object* object);
@ -1472,6 +1475,8 @@ class Isolate {
base::Mutex simulator_i_cache_mutex_;
#endif
bool allow_atomics_wait_;
friend class ExecutionAccess;
friend class HandleScopeImplementer;
friend class HeapTester;

View File

@ -269,6 +269,7 @@ class ErrorUtils : public AllStatic {
"ArrayBuffer subclass returned this from species constructor") \
T(ArrayFunctionsOnFrozen, "Cannot modify frozen array elements") \
T(ArrayFunctionsOnSealed, "Cannot add/remove sealed array elements") \
T(AtomicsWaitNotAllowed, "Atomics.wait cannot be called in this context") \
T(CalledNonCallable, "% is not a function") \
T(CalledOnNonObject, "% called on non-object") \
T(CalledOnNullOrUndefined, "% called on null or undefined") \

View File

@ -29,6 +29,11 @@ RUNTIME_FUNCTION(Runtime_AtomicsWait) {
CHECK_EQ(sta->type(), kExternalInt32Array);
CHECK(timeout == V8_INFINITY || !std::isnan(timeout));
if (!isolate->allow_atomics_wait()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kAtomicsWaitNotAllowed));
}
Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
size_t addr = (index << 2) + NumberToSize(sta->byte_offset());
@ -65,5 +70,14 @@ RUNTIME_FUNCTION(Runtime_AtomicsNumWaitersForTesting) {
return FutexEmulation::NumWaitersForTesting(isolate, array_buffer, addr);
}
RUNTIME_FUNCTION(Runtime_SetAllowAtomicsWait) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_BOOLEAN_ARG_CHECKED(set, 0);
isolate->set_allow_atomics_wait(set);
return isolate->heap()->undefined_value();
}
} // namespace internal
} // namespace v8

View File

@ -73,7 +73,8 @@ namespace internal {
F(AtomicsIsLockFree, 1, 1) \
F(AtomicsWait, 4, 1) \
F(AtomicsWake, 3, 1) \
F(AtomicsNumWaitersForTesting, 2, 1)
F(AtomicsNumWaitersForTesting, 2, 1) \
F(SetAllowAtomicsWait, 1, 1)
#define FOR_EACH_INTRINSIC_CLASSES(F) \
F(ThrowUnsupportedSuperError, 0, 1) \

View File

@ -88,7 +88,7 @@ bytecodes: [
B(TestEqualStrict), R(12), U8(20),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), U16(129),
B(Wide), B(LdaSmi), U16(130),
B(Star), R(12),
B(LdaConstant), U8(9),
B(Star), R(13),
@ -233,7 +233,7 @@ bytecodes: [
B(TestEqualStrict), R(13), U8(20),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), U16(129),
B(Wide), B(LdaSmi), U16(130),
B(Star), R(13),
B(LdaConstant), U8(9),
B(Star), R(14),
@ -391,7 +391,7 @@ bytecodes: [
B(TestEqualStrict), R(12), U8(22),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), U16(129),
B(Wide), B(LdaSmi), U16(130),
B(Star), R(12),
B(LdaConstant), U8(9),
B(Star), R(13),
@ -539,7 +539,7 @@ bytecodes: [
B(TestEqualStrict), R(11), U8(24),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), U16(129),
B(Wide), B(LdaSmi), U16(130),
B(Star), R(11),
B(LdaConstant), U8(11),
B(Star), R(12),

View File

@ -497,7 +497,7 @@ bytecodes: [
B(TestEqualStrict), R(11), U8(20),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), U16(129),
B(Wide), B(LdaSmi), U16(130),
B(Star), R(11),
B(LdaConstant), U8(14),
B(Star), R(12),

View File

@ -95,6 +95,15 @@
assertEquals("timed-out", Atomics.wait(i32a, 0, 0, -Infinity));
})();
(function TestWaitNotAllowed() {
%SetAllowAtomicsWait(false);
var i32a = new Int32Array(new SharedArrayBuffer(16));
assertThrows(function() {
Atomics.wait(i32a, 0, 0, -1);
});
%SetAllowAtomicsWait(true);
})();
//// WORKER ONLY TESTS
if (this.Worker) {