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

Implement Atomics API

This is behind the flag "--harmony-atomics", and it only works on
SharedArrayBuffers. This implementation only includes the runtime functions.
The TurboFan implementation will be next.

The draft spec for Atomics can be found here:
https://docs.google.com/document/d/1NDGA_gZJ7M7w1Bh8S0AoDyEqwDdRh4uSoTPSNn77PFk

BUG=
LOG=n

Review URL: https://codereview.chromium.org/1162503002

Cr-Commit-Position: refs/heads/master@{#28796}
parent 614d6a3b
......@@ -269,6 +269,7 @@ action("js2c_experimental") {
"src/messages.h",
"src/proxy.js",
"src/generator.js",
"src/harmony-atomics.js",
"src/harmony-array.js",
"src/harmony-array-includes.js",
"src/harmony-typedarray.js",
......@@ -998,6 +999,7 @@ source_set("v8_base") {
"src/runtime-profiler.cc",
"src/runtime-profiler.h",
"src/runtime/runtime-array.cc",
"src/runtime/runtime-atomics.cc",
"src/runtime/runtime-classes.cc",
"src/runtime/runtime-collections.cc",
"src/runtime/runtime-compiler.cc",
......
......@@ -230,6 +230,7 @@ class Genesis BASE_EMBEDDED {
bool InstallExperimentalNatives();
bool InstallExtraNatives();
void InstallBuiltinFunctionIds();
void InstallExperimentalBuiltinFunctionIds();
void InstallJSFunctionResultCaches();
void InitializeNormalizedMapCaches();
......@@ -1766,6 +1767,7 @@ EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_destructuring)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_object)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_spread_arrays)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_sharedarraybuffer)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_atomics)
void Genesis::InstallNativeFunctions_harmony_proxies() {
......@@ -1777,6 +1779,7 @@ void Genesis::InstallNativeFunctions_harmony_proxies() {
}
}
#undef INSTALL_NATIVE
#define EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(id) \
......@@ -1797,6 +1800,7 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_spreadcalls)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_destructuring)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_object)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_spread_arrays)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_atomics)
void Genesis::InitializeGlobal_harmony_regexps() {
Handle<JSObject> builtins(native_context()->builtins());
......@@ -2441,6 +2445,8 @@ bool Genesis::InstallExperimentalNatives() {
static const char* harmony_spread_arrays_natives[] = {nullptr};
static const char* harmony_sharedarraybuffer_natives[] = {
"native harmony-sharedarraybuffer.js", NULL};
static const char* harmony_atomics_natives[] = {"native harmony-atomics.js",
nullptr};
for (int i = ExperimentalNatives::GetDebuggerCount();
i < ExperimentalNatives::GetBuiltinsCount(); i++) {
......@@ -2463,6 +2469,7 @@ bool Genesis::InstallExperimentalNatives() {
CallUtilsFunction(isolate(), "PostExperimentals");
InstallExperimentalNativeFunctions();
InstallExperimentalBuiltinFunctionIds();
return true;
}
......@@ -2488,6 +2495,11 @@ static void InstallBuiltinFunctionId(Handle<JSObject> holder,
}
#define INSTALL_BUILTIN_ID(holder_expr, fun_name, name) \
{ #holder_expr, #fun_name, k##name } \
,
void Genesis::InstallBuiltinFunctionIds() {
HandleScope scope(isolate());
struct BuiltinFunctionIds {
......@@ -2496,12 +2508,8 @@ void Genesis::InstallBuiltinFunctionIds() {
BuiltinFunctionId id;
};
#define INSTALL_BUILTIN_ID(holder_expr, fun_name, name) \
{ #holder_expr, #fun_name, k##name } \
,
const BuiltinFunctionIds builtins[] = {
FUNCTIONS_WITH_ID_LIST(INSTALL_BUILTIN_ID)};
#undef INSTALL_BUILTIN_ID
for (const BuiltinFunctionIds& builtin : builtins) {
Handle<JSObject> holder =
......@@ -2511,6 +2519,29 @@ void Genesis::InstallBuiltinFunctionIds() {
}
void Genesis::InstallExperimentalBuiltinFunctionIds() {
if (FLAG_harmony_atomics) {
struct BuiltinFunctionIds {
const char* holder_expr;
const char* fun_name;
BuiltinFunctionId id;
};
const BuiltinFunctionIds atomic_builtins[] = {
ATOMIC_FUNCTIONS_WITH_ID_LIST(INSTALL_BUILTIN_ID)};
for (const BuiltinFunctionIds& builtin : atomic_builtins) {
Handle<JSObject> holder =
ResolveBuiltinIdHolder(native_context(), builtin.holder_expr);
InstallBuiltinFunctionId(holder, builtin.fun_name, builtin.id);
}
}
}
#undef INSTALL_BUILTIN_ID
// Do not forget to update macros.py with named constant
// of cache id.
#define JSFUNCTION_RESULT_CACHE_LIST(F) \
......
......@@ -193,7 +193,8 @@ DEFINE_IMPLICATION(es_staging, harmony)
V(harmony_unicode_regexps, "harmony unicode regexps") \
V(harmony_reflect, "harmony Reflect API") \
V(harmony_destructuring, "harmony destructuring") \
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer")
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \
V(harmony_atomics, "harmony atomics")
// Features that are complete (but still behind --harmony/es-staging flag).
#define HARMONY_STAGED(V) \
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function(global, utils) {
"use strict";
%CheckIsBootstrapping();
// -------------------------------------------------------------------
// Imports
var GlobalObject = global.Object;
// -------------------------------------------------------------------
function CheckSharedTypedArray(sta) {
if (!%_IsSharedTypedArray(sta)) {
throw MakeTypeError(kNotSharedTypedArray, sta);
}
}
function CheckSharedIntegerTypedArray(ia) {
if (!%_IsSharedIntegerTypedArray(ia)) {
throw MakeTypeError(kNotIntegerSharedTypedArray, ia);
}
}
//-------------------------------------------------------------------
function AtomicsCompareExchangeJS(sta, index, oldValue, newValue) {
CheckSharedTypedArray(sta);
index = $toInteger(index);
if (index < 0 || index >= sta.length) {
return UNDEFINED;
}
return %_AtomicsCompareExchange(sta, index, oldValue, newValue);
}
function AtomicsLoadJS(sta, index) {
CheckSharedTypedArray(sta);
index = $toInteger(index);
if (index < 0 || index >= sta.length) {
return UNDEFINED;
}
return %_AtomicsLoad(sta, index);
}
function AtomicsStoreJS(sta, index, value) {
CheckSharedTypedArray(sta);
index = $toInteger(index);
if (index < 0 || index >= sta.length) {
return UNDEFINED;
}
return %_AtomicsStore(sta, index, value);
}
function AtomicsAddJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = $toInteger(index);
if (index < 0 || index >= ia.length) {
return UNDEFINED;
}
return %_AtomicsAdd(ia, index, value);
}
function AtomicsSubJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = $toInteger(index);
if (index < 0 || index >= ia.length) {
return UNDEFINED;
}
return %_AtomicsSub(ia, index, value);
}
function AtomicsAndJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = $toInteger(index);
if (index < 0 || index >= ia.length) {
return UNDEFINED;
}
return %_AtomicsAnd(ia, index, value);
}
function AtomicsOrJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = $toInteger(index);
if (index < 0 || index >= ia.length) {
return UNDEFINED;
}
return %_AtomicsOr(ia, index, value);
}
function AtomicsXorJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = $toInteger(index);
if (index < 0 || index >= ia.length) {
return UNDEFINED;
}
return %_AtomicsXor(ia, index, value);
}
function AtomicsExchangeJS(ia, index, value) {
CheckSharedIntegerTypedArray(ia);
index = $toInteger(index);
if (index < 0 || index >= ia.length) {
return UNDEFINED;
}
return %_AtomicsExchange(ia, index, value);
}
function AtomicsIsLockFreeJS(size) {
return %_AtomicsIsLockFree(size);
}
// -------------------------------------------------------------------
function AtomicsConstructor() {}
var Atomics = new AtomicsConstructor();
%InternalSetPrototype(Atomics, GlobalObject.prototype);
%AddNamedProperty(global, "Atomics", Atomics, DONT_ENUM);
%FunctionSetInstanceClassName(AtomicsConstructor, 'Atomics');
%AddNamedProperty(Atomics, symbolToStringTag, "Atomics", READ_ONLY | DONT_ENUM);
utils.InstallFunctions(Atomics, DONT_ENUM, [
"compareExchange", AtomicsCompareExchangeJS,
"load", AtomicsLoadJS,
"store", AtomicsStoreJS,
"add", AtomicsAddJS,
"sub", AtomicsSubJS,
"and", AtomicsAndJS,
"or", AtomicsOrJS,
"xor", AtomicsXorJS,
"exchange", AtomicsExchangeJS,
"isLockFree", AtomicsIsLockFreeJS,
]);
})
......@@ -161,6 +161,8 @@ class CallSite {
T(NotGeneric, "% is not generic") \
T(NotIterable, "% is not iterable") \
T(NotTypedArray, "this is not a typed array.") \
T(NotSharedTypedArray, "% is not a shared typed array.") \
T(NotIntegerSharedTypedArray, "% is not an integer shared typed array.") \
T(ObjectGetterExpectingFunction, \
"Object.prototype.__defineGetter__: Expecting function") \
T(ObjectGetterCallable, "Getter must be a function: %") \
......
......@@ -6866,11 +6866,16 @@ class Script: public Struct {
V(Math, clz32, MathClz32) \
V(Math, fround, MathFround)
#define ATOMIC_FUNCTIONS_WITH_ID_LIST(V) \
V(Atomics, load, AtomicsLoad) \
V(Atomics, store, AtomicsStore)
enum BuiltinFunctionId {
kArrayCode,
#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
k##name,
FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
ATOMIC_FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
#undef DECLARE_FUNCTION_ID
// Fake id for a special case of Math.pow. Note, it continues the
// list of math functions.
......
This diff is collapsed.
......@@ -476,6 +476,29 @@ RUNTIME_FUNCTION(Runtime_IsTypedArray) {
}
RUNTIME_FUNCTION(Runtime_IsSharedTypedArray) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
return isolate->heap()->ToBoolean(
args[0]->IsJSTypedArray() &&
JSTypedArray::cast(args[0])->GetBuffer()->is_shared());
}
RUNTIME_FUNCTION(Runtime_IsSharedIntegerTypedArray) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
if (!args[0]->IsJSTypedArray()) {
return isolate->heap()->false_value();
}
Handle<JSTypedArray> obj(JSTypedArray::cast(args[0]));
return isolate->heap()->ToBoolean(obj->GetBuffer()->is_shared() &&
obj->type() != kExternalFloat32Array &&
obj->type() != kExternalFloat64Array);
}
RUNTIME_FUNCTION(Runtime_DataViewInitialize) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
......
......@@ -55,6 +55,17 @@ namespace internal {
RUNTIME_ASSERT(args[index]->IsNumber()); \
double name = args.number_at(index);
// Cast the given argument to a size_t and store its value in a variable with
// the given name. If the argument is not a size_t call IllegalOperation and
// return.
#define CONVERT_SIZE_ARG_CHECKED(name, index) \
RUNTIME_ASSERT(args[index]->IsNumber()); \
Handle<Object> name##_object = args.at<Object>(index); \
size_t name = 0; \
RUNTIME_ASSERT(TryNumberToSize(isolate, *name##_object, &name));
// Call the specified converter on the object *comand store the result in
// a variable of the specified type with the given name. If the
// object is not a Number call IllegalOperation and return.
......
......@@ -53,6 +53,19 @@ namespace internal {
F(FastOneByteArrayJoin, 2, 1)
#define FOR_EACH_INTRINSIC_ATOMICS(F) \
F(AtomicsCompareExchange, 4, 1) \
F(AtomicsLoad, 2, 1) \
F(AtomicsStore, 3, 1) \
F(AtomicsAdd, 3, 1) \
F(AtomicsSub, 3, 1) \
F(AtomicsAnd, 3, 1) \
F(AtomicsOr, 3, 1) \
F(AtomicsXor, 3, 1) \
F(AtomicsExchange, 3, 1) \
F(AtomicsIsLockFree, 1, 1)
#define FOR_EACH_INTRINSIC_CLASSES(F) \
F(ThrowNonMethodError, 0, 1) \
F(ThrowUnsupportedSuperError, 0, 1) \
......@@ -655,6 +668,8 @@ namespace internal {
F(TypedArraySetFastCases, 3, 1) \
F(TypedArrayMaxSizeInHeap, 0, 1) \
F(IsTypedArray, 1, 1) \
F(IsSharedTypedArray, 1, 1) \
F(IsSharedIntegerTypedArray, 1, 1) \
F(DataViewInitialize, 4, 1) \
F(DataViewGetUint8, 3, 1) \
F(DataViewGetInt8, 3, 1) \
......@@ -687,6 +702,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_RETURN_OBJECT(F) \
FOR_EACH_INTRINSIC_ARRAY(F) \
FOR_EACH_INTRINSIC_ATOMICS(F) \
FOR_EACH_INTRINSIC_CLASSES(F) \
FOR_EACH_INTRINSIC_COLLECTIONS(F) \
FOR_EACH_INTRINSIC_COMPILER(F) \
......@@ -874,6 +890,8 @@ class Runtime : public AllStatic {
static MaybeHandle<JSArray> GetInternalProperties(Isolate* isolate,
Handle<Object>);
static bool AtomicIsLockFree(uint32_t size);
};
......@@ -890,6 +908,29 @@ class DeclareGlobalsNativeFlag : public BitField<bool, 1, 1> {};
STATIC_ASSERT(LANGUAGE_END == 3);
class DeclareGlobalsLanguageMode : public BitField<LanguageMode, 2, 2> {};
//---------------------------------------------------------------------------
// Inline functions
// Assume that 32-bit architectures don't have 64-bit atomic ops.
// TODO(binji): can we do better here?
#if V8_TARGET_ARCH_64_BIT && V8_HOST_ARCH_64_BIT
#define ATOMICS_REQUIRE_LOCK_64_BIT 0
inline bool Runtime::AtomicIsLockFree(uint32_t size) {
return size == 1 || size == 2 || size == 4 || size == 8;
}
#else
#define ATOMICS_REQUIRE_LOCK_64_BIT 1
inline bool Runtime::AtomicIsLockFree(uint32_t size) {
return size == 1 || size == 2 || size == 4;
}
#endif
} // namespace internal
} // namespace v8
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-atomics --harmony-sharedarraybuffer
function Module(stdlib, foreign, heap) {
"use asm";
var MEM8 = new stdlib.Int8Array(heap);
var MEM16 = new stdlib.Int16Array(heap);
var MEM32 = new stdlib.Int32Array(heap);
var MEMU8 = new stdlib.Uint8Array(heap);
var MEMU16 = new stdlib.Uint16Array(heap);
var MEMU32 = new stdlib.Uint32Array(heap);
var add = stdlib.Atomics.add;
var fround = stdlib.Math.fround;
function addi8(i, x) {
i = i | 0;
x = x | 0;
return add(MEM8, i, x)|0;
}
function addi16(i, x) {
i = i | 0;
x = x | 0;
return add(MEM16, i, x)|0;
}
function addi32(i, x) {
i = i | 0;
x = x | 0;
return add(MEM32, i, x)|0;
}
function addu8(i, x) {
i = i | 0;
x = x >>> 0;
return add(MEMU8, i, x)>>>0;
}
function addu16(i, x) {
i = i | 0;
x = x >>> 0;
return add(MEMU16, i, x)>>>0;
}
function addu32(i, x) {
i = i | 0;
x = x >>> 0;
return add(MEMU32, i, x)>>>0;
}
return {
addi8: addi8,
addi16: addi16,
addi32: addi32,
addu8: addu8,
addu16: addu16,
addu32: addu32,
};
}
var sab = new SharedArrayBuffer(16);
var m = Module(this, {}, sab);
function clearArray() {
var ui8 = new Uint8Array(sab);
for (var i = 0; i < sab.byteLength; ++i) {
ui8[i] = 0;
}
}
function testElementType(taConstr, f) {
clearArray();
var ta = new taConstr(sab);
var name = Object.prototype.toString.call(ta);
assertEquals(0, f(0, 10), name);
assertEquals(10, ta[0]);
assertEquals(10, f(0, 10), name);
assertEquals(20, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
}
testElementType(Int8Array, m.addi8);
testElementType(Int16Array, m.addi16);
testElementType(Int32Array, m.addi32);
testElementType(Uint8Array, m.addu8);
testElementType(Uint16Array, m.addu16);
testElementType(Uint32Array, m.addu32);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-atomics --harmony-sharedarraybuffer
function Module(stdlib, foreign, heap) {
"use asm";
var MEM8 = new stdlib.Int8Array(heap);
var MEM16 = new stdlib.Int16Array(heap);
var MEM32 = new stdlib.Int32Array(heap);
var MEMU8 = new stdlib.Uint8Array(heap);
var MEMU16 = new stdlib.Uint16Array(heap);
var MEMU32 = new stdlib.Uint32Array(heap);
var and = stdlib.Atomics.and;
var fround = stdlib.Math.fround;
function andi8(i, x) {
i = i | 0;
x = x | 0;
return and(MEM8, i, x)|0;
}
function andi16(i, x) {
i = i | 0;
x = x | 0;
return and(MEM16, i, x)|0;
}
function andi32(i, x) {
i = i | 0;
x = x | 0;
return and(MEM32, i, x)|0;
}
function andu8(i, x) {
i = i | 0;
x = x >>> 0;
return and(MEMU8, i, x)>>>0;
}
function andu16(i, x) {
i = i | 0;
x = x >>> 0;
return and(MEMU16, i, x)>>>0;
}
function andu32(i, x) {
i = i | 0;
x = x >>> 0;
return and(MEMU32, i, x)>>>0;
}
return {
andi8: andi8,
andi16: andi16,
andi32: andi32,
andu8: andu8,
andu16: andu16,
andu32: andu32,
};
}
var sab = new SharedArrayBuffer(16);
var m = Module(this, {}, sab);
function clearArray() {
var ui8 = new Uint8Array(sab);
for (var i = 0; i < sab.byteLength; ++i) {
ui8[i] = 0;
}
}
function testElementType(taConstr, f) {
clearArray();
var ta = new taConstr(sab);
var name = Object.prototype.toString.call(ta);
ta[0] = 0x7f;
assertEquals(0x7f, f(0, 0xf), name);
assertEquals(0xf, ta[0]);
assertEquals(0xf, f(0, 0x19), name);
assertEquals(0x9, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
}
testElementType(Int8Array, m.andi8);
testElementType(Int16Array, m.andi16);
testElementType(Int32Array, m.andi32);
testElementType(Uint8Array, m.andu8);
testElementType(Uint16Array, m.andu16);
testElementType(Uint32Array, m.andu32);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-atomics --harmony-sharedarraybuffer
function Module(stdlib, foreign, heap) {
"use asm";
var MEM8 = new stdlib.Int8Array(heap);
var MEM16 = new stdlib.Int16Array(heap);
var MEM32 = new stdlib.Int32Array(heap);
var MEMU8 = new stdlib.Uint8Array(heap);
var MEMU16 = new stdlib.Uint16Array(heap);
var MEMU32 = new stdlib.Uint32Array(heap);
var MEMF32 = new stdlib.Float32Array(heap);
var MEMF64 = new stdlib.Float64Array(heap);
var compareExchange = stdlib.Atomics.compareExchange;
var fround = stdlib.Math.fround;
function compareExchangei8(i, o, n) {
i = i | 0;
o = o | 0;
n = n | 0;
return compareExchange(MEM8, i, o, n)|0;
}
function compareExchangei16(i, o, n) {
i = i | 0;
o = o | 0;
n = n | 0;
return compareExchange(MEM16, i, o, n)|0;
}
function compareExchangei32(i, o, n) {
i = i | 0;
o = o | 0;
n = n | 0;
return compareExchange(MEM32, i, o, n)|0;
}
function compareExchangeu8(i, o, n) {
i = i | 0;
o = o >>> 0;
n = n >>> 0;
return compareExchange(MEMU8, i, o, n)>>>0;
}
function compareExchangeu16(i, o, n) {
i = i | 0;
o = o >>> 0;
n = n >>> 0;
return compareExchange(MEMU16, i, o, n)>>>0;
}
function compareExchangeu32(i, o, n) {
i = i | 0;
o = o >>> 0;
n = n >>> 0;
return compareExchange(MEMU32, i, o, n)>>>0;
}
function compareExchangef32(i, o, n) {
i = i | 0;
o = fround(o);
n = fround(n);
return fround(compareExchange(MEMF32, i, o, n));
}
function compareExchangef64(i, o, n) {
i = i | 0;
o = +o;
n = +n;
return +compareExchange(MEMF64, i, o, n);
}
return {
compareExchangei8: compareExchangei8,
compareExchangei16: compareExchangei16,
compareExchangei32: compareExchangei32,
compareExchangeu8: compareExchangeu8,
compareExchangeu16: compareExchangeu16,
compareExchangeu32: compareExchangeu32,
compareExchangef32: compareExchangef32,
compareExchangef64: compareExchangef64
};
}
var sab = new SharedArrayBuffer(16);
var m = Module(this, {}, sab);
function clearArray() {
var ui8 = new Uint8Array(sab);
for (var i = 0; i < sab.byteLength; ++i) {
ui8[i] = 0;
}
}
function testElementType(taConstr, f, oobValue) {
clearArray();
var ta = new taConstr(sab);
var name = Object.prototype.toString.call(ta);
assertEquals(0, ta[0]);
assertEquals(0, f(0, 0, 50), name);
assertEquals(50, ta[0]);
// Value is not equal to 0, so compareExchange won't store 100
assertEquals(50, f(0, 0, 100), name);
assertEquals(50, ta[0]);
// out of bounds
assertEquals(oobValue, f(-1, 0, 0), name);
assertEquals(oobValue, f(ta.length, 0, 0), name);
}
testElementType(Int8Array, m.compareExchangei8, 0);
testElementType(Int16Array, m.compareExchangei16, 0);
testElementType(Int32Array, m.compareExchangei32, 0);
testElementType(Uint8Array, m.compareExchangeu8, 0);
testElementType(Uint16Array, m.compareExchangeu16, 0);
testElementType(Uint32Array, m.compareExchangeu32, 0);
testElementType(Float32Array, m.compareExchangef32, NaN);
testElementType(Float64Array, m.compareExchangef64, NaN);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-atomics --harmony-sharedarraybuffer
function Module(stdlib, foreign, heap) {
"use asm";
var MEM8 = new stdlib.Int8Array(heap);
var MEM16 = new stdlib.Int16Array(heap);
var MEM32 = new stdlib.Int32Array(heap);
var MEMU8 = new stdlib.Uint8Array(heap);
var MEMU16 = new stdlib.Uint16Array(heap);
var MEMU32 = new stdlib.Uint32Array(heap);
var exchange = stdlib.Atomics.exchange;
var fround = stdlib.Math.fround;
function exchangei8(i, x) {
i = i | 0;
x = x | 0;
return exchange(MEM8, i, x)|0;
}
function exchangei16(i, x) {
i = i | 0;
x = x | 0;
return exchange(MEM16, i, x)|0;
}
function exchangei32(i, x) {
i = i | 0;
x = x | 0;
return exchange(MEM32, i, x)|0;
}
function exchangeu8(i, x) {
i = i | 0;
x = x >>> 0;
return exchange(MEMU8, i, x)>>>0;
}
function exchangeu16(i, x) {
i = i | 0;
x = x >>> 0;
return exchange(MEMU16, i, x)>>>0;
}
function exchangeu32(i, x) {
i = i | 0;
x = x >>> 0;
return exchange(MEMU32, i, x)>>>0;
}
return {
exchangei8: exchangei8,
exchangei16: exchangei16,
exchangei32: exchangei32,
exchangeu8: exchangeu8,
exchangeu16: exchangeu16,
exchangeu32: exchangeu32,
};
}
var sab = new SharedArrayBuffer(16);
var m = Module(this, {}, sab);
function clearArray() {
var ui8 = new Uint8Array(sab);
for (var i = 0; i < sab.byteLength; ++i) {
ui8[i] = 0;
}
}
function testElementType(taConstr, f) {
clearArray();
var ta = new taConstr(sab);
var name = Object.prototype.toString.call(ta);
ta[0] = 0x7f;
assertEquals(0x7f, f(0, 0xf), name);
assertEquals(0xf, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
}
testElementType(Int8Array, m.exchangei8);
testElementType(Int16Array, m.exchangei16);
testElementType(Int32Array, m.exchangei32);
testElementType(Uint8Array, m.exchangeu8);
testElementType(Uint16Array, m.exchangeu16);
testElementType(Uint32Array, m.exchangeu32);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-atomics --harmony-sharedarraybuffer
function Module(stdlib, foreign, heap) {
"use asm";
var MEM8 = new stdlib.Int8Array(heap);
var MEM16 = new stdlib.Int16Array(heap);
var MEM32 = new stdlib.Int32Array(heap);
var MEMU8 = new stdlib.Uint8Array(heap);
var MEMU16 = new stdlib.Uint16Array(heap);
var MEMU32 = new stdlib.Uint32Array(heap);
var MEMF32 = new stdlib.Float32Array(heap);
var MEMF64 = new stdlib.Float64Array(heap);
var load = stdlib.Atomics.load;
var fround = stdlib.Math.fround;
function loadi8(i) {
i = i | 0;
return load(MEM8, i)|0;
}
function loadi16(i) {
i = i | 0;
return load(MEM16, i)|0;
}
function loadi32(i) {
i = i | 0;
return load(MEM32, i)|0;
}
function loadu8(i) {
i = i | 0;
return load(MEMU8, i)>>>0;
}
function loadu16(i) {
i = i | 0;
return load(MEMU16, i)>>>0;
}
function loadu32(i) {
i = i | 0;
return load(MEMU32, i)>>>0;
}
function loadf32(i) {
i = i | 0;
return fround(load(MEMF32, i));
}
function loadf64(i) {
i = i | 0;
return +load(MEMF64, i);
}
return {
loadi8: loadi8,
loadi16: loadi16,
loadi32: loadi32,
loadu8: loadu8,
loadu16: loadu16,
loadu32: loadu32,
loadf32: loadf32,
loadf64: loadf64
};
}
var sab = new SharedArrayBuffer(16);
var m = Module(this, {}, sab);
function clearArray() {
var ui8 = new Uint8Array(sab);
for (var i = 0; i < sab.byteLength; ++i) {
ui8[i] = 0;
}
}
function testElementType(taConstr, f, oobValue) {
clearArray();
var ta = new taConstr(sab);
var name = Object.prototype.toString.call(ta);
ta[0] = 10;
assertEquals(10, f(0), name);
assertEquals(0, f(1), name);
// out of bounds
assertEquals(oobValue, f(-1), name);
assertEquals(oobValue, f(ta.length), name);
}
testElementType(Int8Array, m.loadi8, 0);
testElementType(Int16Array, m.loadi16, 0);
testElementType(Int32Array, m.loadi32, 0);
testElementType(Uint8Array, m.loadu8, 0);
testElementType(Uint16Array, m.loadu16, 0);
testElementType(Uint32Array, m.loadu32, 0);
testElementType(Float32Array, m.loadf32, NaN);
testElementType(Float64Array, m.loadf64, NaN);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-atomics --harmony-sharedarraybuffer
function Module(stdlib, foreign, heap) {
"use asm";
var MEM8 = new stdlib.Int8Array(heap);
var MEM16 = new stdlib.Int16Array(heap);
var MEM32 = new stdlib.Int32Array(heap);
var MEMU8 = new stdlib.Uint8Array(heap);
var MEMU16 = new stdlib.Uint16Array(heap);
var MEMU32 = new stdlib.Uint32Array(heap);
var or = stdlib.Atomics.or;
var fround = stdlib.Math.fround;
function ori8(i, x) {
i = i | 0;
x = x | 0;
return or(MEM8, i, x)|0;
}
function ori16(i, x) {
i = i | 0;
x = x | 0;
return or(MEM16, i, x)|0;
}
function ori32(i, x) {
i = i | 0;
x = x | 0;
return or(MEM32, i, x)|0;
}
function oru8(i, x) {
i = i | 0;
x = x >>> 0;
return or(MEMU8, i, x)>>>0;
}
function oru16(i, x) {
i = i | 0;
x = x >>> 0;
return or(MEMU16, i, x)>>>0;
}
function oru32(i, x) {
i = i | 0;
x = x >>> 0;
return or(MEMU32, i, x)>>>0;
}
return {
ori8: ori8,
ori16: ori16,
ori32: ori32,
oru8: oru8,
oru16: oru16,
oru32: oru32,
};
}
var sab = new SharedArrayBuffer(16);
var m = Module(this, {}, sab);
function clearArray() {
var ui8 = new Uint8Array(sab);
for (var i = 0; i < sab.byteLength; ++i) {
ui8[i] = 0;
}
}
function testElementType(taConstr, f) {
clearArray();
var ta = new taConstr(sab);
var name = Object.prototype.toString.call(ta);
assertEquals(0, f(0, 0xf), name);
assertEquals(0xf, ta[0]);
assertEquals(0xf, f(0, 0x11), name);
assertEquals(0x1f, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
}
testElementType(Int8Array, m.ori8);
testElementType(Int16Array, m.ori16);
testElementType(Int32Array, m.ori32);
testElementType(Uint8Array, m.oru8);
testElementType(Uint16Array, m.oru16);
testElementType(Uint32Array, m.oru32);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-atomics --harmony-sharedarraybuffer
function Module(stdlib, foreign, heap) {
"use asm";
var MEM8 = new stdlib.Int8Array(heap);
var MEM16 = new stdlib.Int16Array(heap);
var MEM32 = new stdlib.Int32Array(heap);
var MEMU8 = new stdlib.Uint8Array(heap);
var MEMU16 = new stdlib.Uint16Array(heap);
var MEMU32 = new stdlib.Uint32Array(heap);
var MEMF32 = new stdlib.Float32Array(heap);
var MEMF64 = new stdlib.Float64Array(heap);
var store = stdlib.Atomics.store;
var fround = stdlib.Math.fround;
function storei8(i, x) {
i = i | 0;
x = x | 0;
return store(MEM8, i, x)|0;
}
function storei16(i, x) {
i = i | 0;
x = x | 0;
return store(MEM16, i, x)|0;
}
function storei32(i, x) {
i = i | 0;
x = x | 0;
return store(MEM32, i, x)|0;
}
function storeu8(i, x) {
i = i | 0;
x = x >>> 0;
return store(MEMU8, i, x)>>>0;
}
function storeu16(i, x) {
i = i | 0;
x = x >>> 0;
return store(MEMU16, i, x)>>>0;
}
function storeu32(i, x) {
i = i | 0;
x = x >>> 0;
return store(MEMU32, i, x)>>>0;
}
function storef32(i, x) {
i = i | 0;
x = fround(x);
return fround(store(MEMF32, i, x));
}
function storef64(i, x) {
i = i | 0;
x = +x;
return +store(MEMF64, i, x);
}
return {
storei8: storei8,
storei16: storei16,
storei32: storei32,
storeu8: storeu8,
storeu16: storeu16,
storeu32: storeu32,
storef32: storef32,
storef64: storef64
};
}
var sab = new SharedArrayBuffer(16);
var m = Module(this, {}, sab);
function clearArray() {
var ui8 = new Uint8Array(sab);
for (var i = 0; i < sab.byteLength; ++i) {
ui8[i] = 0;
}
}
function testElementType(taConstr, f, oobValue) {
clearArray();
var ta = new taConstr(sab);
var name = Object.prototype.toString.call(ta);
assertEquals(10, f(0, 10), name);
assertEquals(10, ta[0]);
// out of bounds
assertEquals(oobValue, f(-1, 0), name);
assertEquals(oobValue, f(ta.length, 0), name);
}
testElementType(Int8Array, m.storei8, 0);
testElementType(Int16Array, m.storei16, 0);
testElementType(Int32Array, m.storei32, 0);
testElementType(Uint8Array, m.storeu8, 0);
testElementType(Uint16Array, m.storeu16, 0);
testElementType(Uint32Array, m.storeu32, 0);
testElementType(Float32Array, m.storef32, NaN);
testElementType(Float64Array, m.storef64, NaN);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-atomics --harmony-sharedarraybuffer
function Module(stdlib, foreign, heap) {
"use asm";
var MEM8 = new stdlib.Int8Array(heap);
var MEM16 = new stdlib.Int16Array(heap);
var MEM32 = new stdlib.Int32Array(heap);
var MEMU8 = new stdlib.Uint8Array(heap);
var MEMU16 = new stdlib.Uint16Array(heap);
var MEMU32 = new stdlib.Uint32Array(heap);
var sub = stdlib.Atomics.sub;
var fround = stdlib.Math.fround;
function subi8(i, x) {
i = i | 0;
x = x | 0;
return sub(MEM8, i, x)|0;
}
function subi16(i, x) {
i = i | 0;
x = x | 0;
return sub(MEM16, i, x)|0;
}
function subi32(i, x) {
i = i | 0;
x = x | 0;
return sub(MEM32, i, x)|0;
}
function subu8(i, x) {
i = i | 0;
x = x >>> 0;
return sub(MEMU8, i, x)>>>0;
}
function subu16(i, x) {
i = i | 0;
x = x >>> 0;
return sub(MEMU16, i, x)>>>0;
}
function subu32(i, x) {
i = i | 0;
x = x >>> 0;
return sub(MEMU32, i, x)>>>0;
}
return {
subi8: subi8,
subi16: subi16,
subi32: subi32,
subu8: subu8,
subu16: subu16,
subu32: subu32,
};
}
var sab = new SharedArrayBuffer(16);
var m = Module(this, {}, sab);
function clearArray() {
var ui8 = new Uint8Array(sab);
for (var i = 0; i < sab.byteLength; ++i) {
ui8[i] = 0;
}
}
function testElementType(taConstr, f) {
clearArray();
var ta = new taConstr(sab);
var name = Object.prototype.toString.call(ta);
ta[0] = 30;
assertEquals(30, f(0, 10), name);
assertEquals(20, ta[0]);
assertEquals(20, f(0, 10), name);
assertEquals(10, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
}
testElementType(Int8Array, m.subi8);
testElementType(Int16Array, m.subi16);
testElementType(Int32Array, m.subi32);
testElementType(Uint8Array, m.subu8);
testElementType(Uint16Array, m.subu16);
testElementType(Uint32Array, m.subu32);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-atomics --harmony-sharedarraybuffer
function Module(stdlib, foreign, heap) {
"use asm";
var MEM8 = new stdlib.Int8Array(heap);
var MEM16 = new stdlib.Int16Array(heap);
var MEM32 = new stdlib.Int32Array(heap);
var MEMU8 = new stdlib.Uint8Array(heap);
var MEMU16 = new stdlib.Uint16Array(heap);
var MEMU32 = new stdlib.Uint32Array(heap);
var xor = stdlib.Atomics.xor;
var fround = stdlib.Math.fround;
function xori8(i, x) {
i = i | 0;
x = x | 0;
return xor(MEM8, i, x)|0;
}
function xori16(i, x) {
i = i | 0;
x = x | 0;
return xor(MEM16, i, x)|0;
}
function xori32(i, x) {
i = i | 0;
x = x | 0;
return xor(MEM32, i, x)|0;
}
function xoru8(i, x) {
i = i | 0;
x = x >>> 0;
return xor(MEMU8, i, x)>>>0;
}
function xoru16(i, x) {
i = i | 0;
x = x >>> 0;
return xor(MEMU16, i, x)>>>0;
}
function xoru32(i, x) {
i = i | 0;
x = x >>> 0;
return xor(MEMU32, i, x)>>>0;
}
return {
xori8: xori8,
xori16: xori16,
xori32: xori32,
xoru8: xoru8,
xoru16: xoru16,
xoru32: xoru32,
};
}
var sab = new SharedArrayBuffer(16);
var m = Module(this, {}, sab);
function clearArray() {
var ui8 = new Uint8Array(sab);
for (var i = 0; i < sab.byteLength; ++i) {
ui8[i] = 0;
}
}
function testElementType(taConstr, f) {
clearArray();
var ta = new taConstr(sab);
var name = Object.prototype.toString.call(ta);
assertEquals(0, f(0, 0xf), name);
assertEquals(0xf, ta[0]);
assertEquals(0xf, f(0, 0x11), name);
assertEquals(0x1e, ta[0]);
// out of bounds
assertEquals(0, f(-1, 0), name);
assertEquals(0, f(ta.length, 0), name);
}
testElementType(Int8Array, m.xori8);
testElementType(Int16Array, m.xori16);
testElementType(Int32Array, m.xori32);
testElementType(Uint8Array, m.xoru8);
testElementType(Uint16Array, m.xoru16);
testElementType(Uint32Array, m.xoru32);
This diff is collapsed.
......@@ -833,6 +833,7 @@
'../../src/runtime-profiler.cc',
'../../src/runtime-profiler.h',
'../../src/runtime/runtime-array.cc',
'../../src/runtime/runtime-atomics.cc',
'../../src/runtime/runtime-classes.cc',
'../../src/runtime/runtime-collections.cc',
'../../src/runtime/runtime-compiler.cc',
......@@ -1743,6 +1744,7 @@
'../../src/messages.h',
'../../src/proxy.js',
'../../src/generator.js',
'../../src/harmony-atomics.js',
'../../src/harmony-array.js',
'../../src/harmony-array-includes.js',
'../../src/harmony-tostring.js',
......
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