Bug 1205390 - make Odin accept TypedArray constructors for shared memory. r=luke

This commit is contained in:
Lars T Hansen 2015-10-23 13:19:08 +02:00
parent 20e8824b95
commit 1f96a66c3d
5 changed files with 181 additions and 16 deletions

View File

@ -230,7 +230,7 @@ ValidateArrayView(JSContext* cx, AsmJSModule::Global& global, HandleValue global
bool tac = IsTypedArrayConstructor(v, global.viewType());
bool stac = IsSharedTypedArrayConstructor(v, global.viewType());
if (!((tac || stac) && stac == isShared))
if (!(tac || (stac && isShared)))
return LinkFail(cx, "bad typed array constructor");
return true;

View File

@ -314,6 +314,10 @@ class AsmJSModule
MOZ_ASSERT(pod.which_ == ArrayView || pod.which_ == SharedArrayView || pod.which_ == ArrayViewCtor);
return pod.u.viewType_;
}
void makeViewShared() {
MOZ_ASSERT(pod.which_ == ArrayView);
pod.which_ = SharedArrayView;
}
PropertyName* mathName() const {
MOZ_ASSERT(pod.which_ == MathBuiltinFunction);
return name_;
@ -1106,6 +1110,15 @@ class AsmJSModule
return pod.isSharedView_ == shared;
return !pod.isSharedView_ || shared;
}
void setViewsAreShared() {
if (pod.hasArrayView_)
pod.isSharedView_ = true;
for (size_t i=0 ; i < globals_.length() ; i++) {
Global& g = globals_[i];
if (g.which() == Global::ArrayView)
g.makeViewShared();
}
}
/*************************************************************************/

View File

@ -773,6 +773,10 @@ class MOZ_STACK_CLASS ModuleValidator
MOZ_ASSERT(isAnyArrayView());
return u.viewInfo.isSharedView_;
}
void setViewIsSharedView() {
MOZ_ASSERT(isAnyArrayView());
u.viewInfo.isSharedView_ = true;
}
bool isMathFunction() const {
return which_ == MathBuiltinFunction;
}
@ -918,6 +922,7 @@ class MOZ_STACK_CLASS ModuleValidator
bool canValidateChangeHeap_;
bool hasChangeHeap_;
bool supportsSimd_;
bool atomicsPresent_;
ScopedJSDeletePtr<ModuleCompileResults> compileResults_;
DebugOnly<bool> finishedFunctionBodies_;
@ -943,6 +948,7 @@ class MOZ_STACK_CLASS ModuleValidator
canValidateChangeHeap_(false),
hasChangeHeap_(false),
supportsSimd_(cx->jitSupportsSimd()),
atomicsPresent_(false),
compileResults_(nullptr),
finishedFunctionBodies_(false)
{
@ -1155,6 +1161,7 @@ class MOZ_STACK_CLASS ModuleValidator
Global* global = moduleLifo_.new_<Global>(Global::AtomicsBuiltinFunction);
if (!global)
return false;
atomicsPresent_ = true;
global->u.atomicsBuiltinFunc_ = func;
return globals_.putNew(varName, global);
}
@ -1509,6 +1516,14 @@ class MOZ_STACK_CLASS ModuleValidator
}
void startFunctionBodies() {
if (atomicsPresent_) {
for (GlobalMap::Range r = globals_.all() ; !r.empty() ; r.popFront()) {
Global* g = r.front().value();
if (g->isAnyArrayView())
g->setViewIsSharedView();
}
module_->setViewsAreShared();
}
module_->startFunctionBodies();
}
bool finishFunctionBodies(ScopedJSDeletePtr<ModuleCompileResults>* compileResults) {

View File

@ -0,0 +1,116 @@
// Transitional test cases, useful while Odin accepts both
// "Int32Array" and "SharedInt32Array" to construct a view onto shared
// memory but the former only when an atomic operation is referenced,
// as per spec. Eventually it will stop accepting "SharedInt32Array",
// because that name is going away.
//
// These should not run with --no-asmjs.
//////////////////////////////////////////////////////////////////////
//
// Int8Array can be used on SharedArrayBuffer, if atomics are present
function m1(stdlib, ffi, heap) {
"use asm";
var i8 = new stdlib.Int8Array(heap);
var add = stdlib.Atomics.add;
function f() {
add(i8, 0, 1);
return 37;
}
return { f:f }
}
assertEq(isAsmJSModule(m1), true);
var { f } = m1(this, {}, new SharedArrayBuffer(65536));
assertEq(f(), 37);
//////////////////////////////////////////////////////////////////////
//
// SharedInt8Array can still be used on SharedArrayBuffer.
// (SharedInt8Array will eventually disappear, and this
// test case with it.)
function m2(stdlib, ffi, heap) {
"use asm";
var i8 = new stdlib.SharedInt8Array(heap);
var add = stdlib.Atomics.add;
function g() {
add(i8, 0, 1);
return 42;
}
return { g:g }
}
assertEq(isAsmJSModule(m2), true);
var { g } = m2(this, {}, new SharedArrayBuffer(65536));
assertEq(g(), 42);
//////////////////////////////////////////////////////////////////////
//
// SharedInt8Array still cannot be used on ArrayBuffer, even without
// atomics present.
// (SharedInt8Array will eventually disappear, and this
// test case with it.)
function m3(stdlib, ffi, heap) {
"use asm";
var i8 = new stdlib.SharedInt8Array(heap);
function h() {
return i8[0]|0;
}
return { h:h }
}
// Running the shell with -w you should see an error here.
assertEq(isAsmJSModule(m3), true);
try {
var wasThrown = false;
m3(this, {}, new ArrayBuffer(65536));
}
catch (e) {
wasThrown = true;
}
assertEq(wasThrown, true);
//////////////////////////////////////////////////////////////////////
//
// Int8Array cannot be used on SharedArrayBuffer if atomics are not imported.
// One argument for the restriction is that there are some optimizations
// that are legal if the memory is known not to be shared that are illegal
// when it is shared.
function m4(stdlib, ffi, heap) {
"use asm";
var i8 = new stdlib.Int8Array(heap);
function i() {
return i8[0]|0;
}
return { i:i }
}
assertEq(isAsmJSModule(m4), true);
// An error is not actually thrown because the link failure drops us
// back to JS execution and then the Int8Array constructor will copy data
// from the SharedArrayBuffer.
//
// Running the shell with -w you should see an error here.
var { i } = m4(this, {}, new SharedArrayBuffer(65536));
assertEq(isAsmJSFunction(i), false);

View File

@ -1,5 +1,5 @@
// |jit-test| test-also-noasmjs
if (!this.SharedArrayBuffer || !this.SharedInt32Array || !this.Atomics)
if (!this.SharedArrayBuffer || !this.Atomics)
quit();
// The code duplication below is very far from elegant but provides
@ -8,6 +8,27 @@ if (!this.SharedArrayBuffer || !this.SharedInt32Array || !this.Atomics)
load(libdir + "asm.js");
load(libdir + "asserts.js");
// This hack allows the test cases to run with --no-asmjs: the field values
// are basically ignored in asm.js mode, and the correct (Firefox-specific)
// field values are used in non-asm.js mode. If run in a non-Firefox
// browser that does not have the parallel type hierarchy this should also
// work.
//
// This hack will be removed when the parallel type hierarchy is removed
// from Firefox, bug 1176214.
const atomicStdlib = {
Atomics: Atomics,
Int8Array: this.SharedInt8Array ? SharedInt8Array : Int8Array,
Uint8Array: this.SharedUint8Array ? SharedUint8Array : Uint8Array,
Int16Array: this.SharedInt16Array ? SharedInt16Array : Int16Array,
Uint16Array: this.SharedUint16Array ? SharedUint16Array : Uint16Array,
Int32Array: this.SharedInt32Array ? SharedInt32Array : Int32Array,
Uint32Array: this.SharedUint32Array ? SharedUint32Array : Uint32Array,
Float32Array: this.SharedFloat32Array ? SharedFloat32Array : Float32Array,
Float64Array: this.SharedFloat64Array ? SharedFloat64Array : Float64Array
};
var loadModule_int32_code =
USE_ASM + `
var atomic_fence = stdlib.Atomics.fence;
@ -21,7 +42,7 @@ var loadModule_int32_code =
var atomic_or = stdlib.Atomics.or;
var atomic_xor = stdlib.Atomics.xor;
var i32a = new stdlib.SharedInt32Array(heap);
var i32a = new stdlib.Int32Array(heap);
function do_fence() {
atomic_fence();
@ -233,7 +254,7 @@ var loadModule_int32 = asmCompile('stdlib', 'foreign', 'heap', loadModule_int32_
function test_int32(heap) {
var i32a = new SharedInt32Array(heap);
var i32m = asmLink(loadModule_int32, this, {}, heap);
var i32m = asmLink(loadModule_int32, atomicStdlib, {}, heap);
var size = SharedInt32Array.BYTES_PER_ELEMENT;
@ -338,7 +359,7 @@ var loadModule_uint32_code =
var atomic_or = stdlib.Atomics.or;
var atomic_xor = stdlib.Atomics.xor;
var i32a = new stdlib.SharedUint32Array(heap);
var i32a = new stdlib.Uint32Array(heap);
// Load element 0
function do_load() {
@ -516,7 +537,7 @@ var loadModule_uint32 = asmCompile('stdlib', 'foreign', 'heap', loadModule_uint3
function test_uint32(heap) {
var i32a = new SharedUint32Array(heap);
var i32m = loadModule_uint32(this, {}, heap);
var i32m = loadModule_uint32(atomicStdlib, {}, heap);
var size = SharedUint32Array.BYTES_PER_ELEMENT;
@ -619,7 +640,7 @@ var loadModule_int16_code =
var atomic_or = stdlib.Atomics.or;
var atomic_xor = stdlib.Atomics.xor;
var i16a = new stdlib.SharedInt16Array(heap);
var i16a = new stdlib.Int16Array(heap);
function do_fence() {
atomic_fence();
@ -802,7 +823,7 @@ var loadModule_int16 = asmCompile('stdlib', 'foreign', 'heap', loadModule_int16_
function test_int16(heap) {
var i16a = new SharedInt16Array(heap);
var i16m = loadModule_int16(this, {}, heap);
var i16m = loadModule_int16(atomicStdlib, {}, heap);
var size = SharedInt16Array.BYTES_PER_ELEMENT;
@ -914,7 +935,7 @@ var loadModule_uint16_code =
var atomic_or = stdlib.Atomics.or;
var atomic_xor = stdlib.Atomics.xor;
var i16a = new stdlib.SharedUint16Array(heap);
var i16a = new stdlib.Uint16Array(heap);
// Load element 0
function do_load() {
@ -1092,7 +1113,7 @@ var loadModule_uint16 = asmCompile('stdlib', 'foreign', 'heap', loadModule_uint1
function test_uint16(heap) {
var i16a = new SharedUint16Array(heap);
var i16m = loadModule_uint16(this, {}, heap);
var i16m = loadModule_uint16(atomicStdlib, {}, heap);
var size = SharedUint16Array.BYTES_PER_ELEMENT;
@ -1202,7 +1223,7 @@ var loadModule_int8_code =
var atomic_or = stdlib.Atomics.or;
var atomic_xor = stdlib.Atomics.xor;
var i8a = new stdlib.SharedInt8Array(heap);
var i8a = new stdlib.Int8Array(heap);
// Load element 0
function do_load() {
@ -1380,7 +1401,7 @@ var loadModule_int8 = asmCompile('stdlib', 'foreign', 'heap', loadModule_int8_co
function test_int8(heap) {
var i8a = new SharedInt8Array(heap);
var i8m = loadModule_int8(this, {}, heap);
var i8m = loadModule_int8(atomicStdlib, {}, heap);
for ( var i=0 ; i < i8a.length ; i++ )
i8a[i] = 0;
@ -1483,7 +1504,7 @@ var loadModule_uint8_code =
var atomic_or = stdlib.Atomics.or;
var atomic_xor = stdlib.Atomics.xor;
var i8a = new stdlib.SharedUint8Array(heap);
var i8a = new stdlib.Uint8Array(heap);
// Load element 0
function do_load() {
@ -1661,7 +1682,7 @@ var loadModule_uint8 = asmCompile('stdlib', 'foreign', 'heap', loadModule_uint8_
function test_uint8(heap) {
var i8a = new SharedUint8Array(heap);
var i8m = loadModule_uint8(this, {}, heap);
var i8m = loadModule_uint8(atomicStdlib, {}, heap);
for ( var i=0 ; i < i8a.length ; i++ )
i8a[i] = 0;
@ -1816,7 +1837,7 @@ var loadModule_misc_code =
var loadModule_misc = asmCompile('stdlib', 'foreign', 'heap', loadModule_misc_code);
function test_misc(heap) {
var misc = loadModule_misc(this, {}, heap);
var misc = loadModule_misc(atomicStdlib, {}, heap);
assertEq(misc.ilf1(), 1);
assertEq(misc.ilf2(), 1);
@ -1848,7 +1869,7 @@ setARMHwCapFlags('vfp');
asmCompile('stdlib', 'ffi', 'heap',
USE_ASM + `
var atomic_exchange = stdlib.Atomics.exchange;
var i8a = new stdlib.SharedInt8Array(heap);
var i8a = new stdlib.Int8Array(heap);
function do_xchg() {
var v = 0;