Bug 933001 - Part 2/5 - Make SharedArrayBuffer usable as an AsmJS heap. r=luke

This commit is contained in:
Sean Stangl 2014-02-20 14:47:03 -08:00
parent f9325c702d
commit ae8cbd7af4
4 changed files with 58 additions and 29 deletions

View File

@ -223,6 +223,38 @@ ValidateConstant(JSContext *cx, AsmJSModule::Global &global, HandleValue globalV
return true;
}
static bool
LinkModuleToHeap(JSContext *cx, AsmJSModule &module, Handle<ArrayBufferObject*> heap)
{
if (!IsValidAsmJSHeapLength(heap->byteLength())) {
ScopedJSFreePtr<char> msg(
JS_smprintf("ArrayBuffer byteLength 0x%x is not a valid heap length. The next "
"valid length is 0x%x",
heap->byteLength(),
RoundUpToNextValidAsmJSHeapLength(heap->byteLength())));
return LinkFail(cx, msg.get());
}
// This check is sufficient without considering the size of the loaded datum because heap
// loads and stores start on an aligned boundary and the heap byteLength has larger alignment.
JS_ASSERT((module.minHeapLength() - 1) <= INT32_MAX);
if (heap->byteLength() < module.minHeapLength()) {
ScopedJSFreePtr<char> msg(
JS_smprintf("ArrayBuffer byteLength of 0x%x is less than 0x%x (which is the"
"largest constant heap access offset rounded up to the next valid "
"heap size).",
heap->byteLength(),
module.minHeapLength()));
return LinkFail(cx, msg.get());
}
if (!ArrayBufferObject::prepareForAsmJS(cx, heap))
return LinkFail(cx, "Unable to prepare ArrayBuffer for asm.js use");
module.initHeap(heap, cx);
return true;
}
static bool
DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module)
{
@ -245,34 +277,9 @@ DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module)
if (!IsTypedArrayBuffer(bufferVal))
return LinkFail(cx, "bad ArrayBuffer argument");
heap = &bufferVal.toObject().as<ArrayBufferObject>();
if (!IsValidAsmJSHeapLength(heap->byteLength())) {
ScopedJSFreePtr<char> msg(
JS_smprintf("ArrayBuffer byteLength 0x%x is not a valid heap length. The next "
"valid length is 0x%x",
heap->byteLength(),
RoundUpToNextValidAsmJSHeapLength(heap->byteLength())));
return LinkFail(cx, msg.get());
}
// This check is sufficient without considering the size of the loaded datum because heap
// loads and stores start on an aligned boundary and the heap byteLength has larger alignment.
JS_ASSERT((module.minHeapLength() - 1) <= INT32_MAX);
if (heap->byteLength() < module.minHeapLength()) {
ScopedJSFreePtr<char> msg(
JS_smprintf("ArrayBuffer byteLength of 0x%x is less than 0x%x (which is the"
"largest constant heap access offset rounded up to the next valid "
"heap size).",
heap->byteLength(),
module.minHeapLength()));
return LinkFail(cx, msg.get());
}
if (!ArrayBufferObject::prepareForAsmJS(cx, heap))
return LinkFail(cx, "Unable to prepare ArrayBuffer for asm.js use");
module.initHeap(heap, cx);
heap = &AsTypedArrayBuffer(bufferVal);
if (!LinkModuleToHeap(cx, module, heap))
return false;
}
AutoObjectVector ffis(cx);

View File

@ -533,6 +533,10 @@ ArrayBufferObject::prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buf
if (buffer->isAsmJSArrayBuffer())
return true;
// SharedArrayBuffers are already created with AsmJS support in mind.
if (buffer->isSharedArrayBuffer())
return true;
// Get the entire reserved region (with all pages inaccessible).
void *p;
# ifdef XP_WIN
@ -598,6 +602,9 @@ ArrayBufferObject::prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buf
if (buffer->isAsmJSArrayBuffer())
return true;
if (buffer->isSharedArrayBuffer())
return true;
if (!ensureNonInline(cx, buffer))
return false;
@ -616,6 +623,7 @@ ArrayBufferObject::releaseAsmJSArrayBuffer(FreeOp *fop, JSObject *obj)
bool
ArrayBufferObject::neuterAsmJSArrayBuffer(JSContext *cx, ArrayBufferObject &buffer)
{
JS_ASSERT(!buffer.isSharedArrayBuffer());
#ifdef JS_ION
AsmJSActivation *act = cx->mainThread().asmJSActivationStackFromOwnerThread();
for (; act; act = act->prev()) {

View File

@ -2768,7 +2768,18 @@ js::IsTypedArrayConstructor(HandleValue v, uint32_t type)
bool
js::IsTypedArrayBuffer(HandleValue v)
{
return v.isObject() && v.toObject().is<ArrayBufferObject>();
return v.isObject() &&
(v.toObject().is<ArrayBufferObject>() ||
v.toObject().is<SharedArrayBufferObject>());
}
ArrayBufferObject &
js::AsTypedArrayBuffer(HandleValue v)
{
JS_ASSERT(IsTypedArrayBuffer(v));
if (v.toObject().is<ArrayBufferObject>())
return v.toObject().as<ArrayBufferObject>();
return v.toObject().as<SharedArrayBufferObject>();
}
/* JS Friend API */

View File

@ -150,6 +150,9 @@ IsTypedArrayConstructor(HandleValue v, uint32_t type);
bool
IsTypedArrayBuffer(HandleValue v);
ArrayBufferObject &
AsTypedArrayBuffer(HandleValue v);
static inline unsigned
TypedArrayShift(ArrayBufferView::ViewType viewType)
{