Bug 854209 - add asm.js mochitests (r=sstangl)

This commit is contained in:
Luke Wagner 2013-05-03 14:45:07 -07:00
parent bc05dd698f
commit 64cf6530d4
8 changed files with 173 additions and 33 deletions

View File

@ -925,6 +925,22 @@ js::IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
args.rval().set(BooleanValue(false)); args.rval().set(BooleanValue(false));
return true; return true;
} }
JSBool
js::IsAsmJSModule(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().set(BooleanValue(false));
return true;
}
JSBool
js::IsAsmJSFunction(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().set(BooleanValue(false));
return true;
}
#endif #endif
static JSFunctionSpecWithHelp TestingFunctions[] = { static JSFunctionSpecWithHelp TestingFunctions[] = {
@ -1071,6 +1087,16 @@ static JSFunctionSpecWithHelp TestingFunctions[] = {
" Returns whether asm.js compilation is currently available or whether it is disabled\n" " Returns whether asm.js compilation is currently available or whether it is disabled\n"
" (e.g., by the debugger)."), " (e.g., by the debugger)."),
JS_FN_HELP("isAsmJSModule", IsAsmJSModule, 1, 0,
"isAsmJSModule(fn)",
" Returns whether the given value is a function containing \"use asm\" that has been\n"
" validated according to the asm.js spec."),
JS_FN_HELP("isAsmJSFunction", IsAsmJSFunction, 1, 0,
"isAsmJSModule(fn)",
" Returns whether the given value is a nested function in an asm.js module that has been\n"
" both compile- and link-time validated."),
JS_FN_HELP("inParallelSection", testingFunc_inParallelSection, 0, 0, JS_FN_HELP("inParallelSection", testingFunc_inParallelSection, 0, 0,
"inParallelSection()", "inParallelSection()",
" True if this code is executing within a parallel section."), " True if this code is executing within a parallel section."),

View File

@ -5614,6 +5614,37 @@ js::IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
return true; return true;
} }
static bool
IsMaybeWrappedNativeFunction(const Value &v, Native native)
{
if (!v.isObject())
return false;
JSObject *obj = CheckedUnwrap(&v.toObject());
if (!obj)
return false;
return obj->isFunction() && obj->toFunction()->maybeNative() == native;
}
JSBool
js::IsAsmJSModule(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
bool rval = args.hasDefined(0) && IsMaybeWrappedNativeFunction(args[0], LinkAsmJS);
args.rval().set(BooleanValue(rval));
return true;
}
JSBool
js::IsAsmJSFunction(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
bool rval = args.hasDefined(0) && IsMaybeWrappedNativeFunction(args[0], CallAsmJS);
args.rval().set(BooleanValue(rval));
return true;
}
AsmJSModule::~AsmJSModule() AsmJSModule::~AsmJSModule()
{ {
for (size_t i = 0; i < numFunctionCounts(); i++) for (size_t i = 0; i < numFunctionCounts(); i++)

View File

@ -24,11 +24,6 @@ class AsmJSModule;
namespace frontend { struct TokenStream; struct ParseNode; } namespace frontend { struct TokenStream; struct ParseNode; }
namespace ion { class MIRGenerator; class LIRGraph; } namespace ion { class MIRGenerator; class LIRGraph; }
// Return whether asm.js optimization is inhibitted by the platform or
// dynamically disabled. (Exposed as JSNative for shell testing.)
extern JSBool
IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp);
// Called after parsing a function 'fn' which contains the "use asm" directive. // Called after parsing a function 'fn' which contains the "use asm" directive.
// This function performs type-checking and code-generation. If type-checking // This function performs type-checking and code-generation. If type-checking
// succeeds, the generated native function is assigned to |moduleFun|. // succeeds, the generated native function is assigned to |moduleFun|.
@ -51,6 +46,11 @@ CompileAsmJS(JSContext *cx, frontend::TokenStream &ts, frontend::ParseNode *fn,
extern JSBool extern JSBool
LinkAsmJS(JSContext *cx, unsigned argc, JS::Value *vp); LinkAsmJS(JSContext *cx, unsigned argc, JS::Value *vp);
// The js::Native for the functions nested in an asm.js module. Calling this
// native will trampoline into generated code.
extern JSBool
CallAsmJS(JSContext *cx, unsigned argc, JS::Value *vp);
// Force any currently-executing asm.js code to call // Force any currently-executing asm.js code to call
// js_HandleExecutionInterrupt. // js_HandleExecutionInterrupt.
void void
@ -157,6 +157,23 @@ IsAsmJSModuleNative(js::Native native)
} }
#endif #endif
// Exposed for shell testing:
// Return whether asm.js optimization is inhibitted by the platform or
// dynamically disabled:
extern JSBool
IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp);
// Return whether the given value is a function containing "use asm" that has
// been validated according to the asm.js spec.
extern JSBool
IsAsmJSModule(JSContext *cx, unsigned argc, Value *vp);
// Return whether the given value is a nested function in an asm.js module that
// has been both compile- and link-time validated.
extern JSBool
IsAsmJSFunction(JSContext *cx, unsigned argc, Value *vp);
} // namespace js } // namespace js
#endif // jsion_asmjs_h__ #endif // jsion_asmjs_h__

View File

@ -281,8 +281,8 @@ AsmJSActivation::~AsmJSActivation()
static const unsigned ASM_MODULE_SLOT = 0; static const unsigned ASM_MODULE_SLOT = 0;
static const unsigned ASM_EXPORT_INDEX_SLOT = 1; static const unsigned ASM_EXPORT_INDEX_SLOT = 1;
static JSBool extern JSBool
CallAsmJS(JSContext *cx, unsigned argc, Value *vp) js::CallAsmJS(JSContext *cx, unsigned argc, Value *vp)
{ {
CallArgs callArgs = CallArgsFromVp(argc, vp); CallArgs callArgs = CallArgsFromVp(argc, vp);
RootedFunction callee(cx, callArgs.callee().toFunction()); RootedFunction callee(cx, callArgs.callee().toFunction());

View File

@ -14,32 +14,9 @@ const BUF_64KB = new ArrayBuffer(64 * 1024);
function asmCompile() function asmCompile()
{ {
if (!isAsmJSCompilationAvailable()) var f = Function.apply(null, arguments);
return Function.apply(null, arguments); assertEq(!isAsmJSCompilationAvailable() || isAsmJSModule(f), true);
return f;
// asm.js emits a warning on successful compilation
// Turn on warnings-as-errors
var oldOpts = options("werror");
assertEq(oldOpts.indexOf("werror"), -1);
// Verify that the code is succesfully compiled
var caught = false;
try {
Function.apply(null, arguments);
} catch (e) {
if ((''+e).indexOf(ASM_OK_STRING) == -1)
throw new Error("Didn't catch the expected success error; instead caught: " + e);
caught = true;
}
if (!caught)
throw new Error("Didn't catch the success error");
// Turn warnings-as-errors back off
options("werror");
// Compile for real
return Function.apply(null, arguments);
} }
function assertAsmTypeFail() function assertAsmTypeFail()

View File

@ -95,6 +95,8 @@ MOCHITEST_FILES = chrome_wrappers_helper.html \
test_bug865260.html \ test_bug865260.html \
file_crosscompartment_weakmap.html \ file_crosscompartment_weakmap.html \
test_crosscompartment_weakmap.html \ test_crosscompartment_weakmap.html \
test_asmjs.html \
file_asmjs.js \
$(NULL) $(NULL)
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,26 @@
function f(stdlib, foreign, buffer) {
"use asm";
var i32 = new stdlib.Int32Array(buffer);
function main(n) {
n = n|0;
var i = 0, sum = 0;
for (; (i|0) < (n|0); i=(i+1)|0)
sum = (sum + (i32[(i<<2)>>2]|0))|0;
return sum|0;
}
return main;
}
var i32 = new Int32Array(4096/4);
for (var i = 0; i < 100; i++)
i32[i] = i;
var fMain = f(this, null, i32.buffer);
if (fMain(4) !== 6)
throw "f.main(4)";
if (fMain(100) !== 4950)
throw "f.main(100)";
if (fMain(3000000) !== 4950)
throw "f.main(3000000)";
postMessage("ok");

View File

@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=854209
-->
<head>
<meta charset="utf-8">
<title>asm.js browser tests</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=854209">asm.js browser tests</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var jsFuns = SpecialPowers.Cu.getJSTestingFunctions();
ok(jsFuns.isAsmJSCompilationAvailable());
function f1() { "use asm"; function g() {} return g }
ok(jsFuns.isAsmJSModule(f1), "f1 is an asm.js module");
ok(jsFuns.isAsmJSFunction(f1()), "f1.g is an asm.js function");
function f2(stdlib, foreign, buffer) {
"use asm";
var i32 = new stdlib.Int32Array(buffer);
function main(n) {
n = n|0;
var i = 0, sum = 0;
for (; (i|0) < (n|0); i=(i+1)|0)
sum = (sum + (i32[(i<<2)>>2]|0))|0;
return sum|0;
}
return main;
}
ok(jsFuns.isAsmJSModule(f2), "f2 is an asm.js module");
var i32 = new Int32Array(4096/4);
for (var i = 0; i < 100; i++)
i32[i] = i;
var f2Main = f2(this, null, i32.buffer);
ok(f2Main, "f2.main is an asm.js function");
ok(f2Main(4) == 6, "f2.main(4)");
ok(f2Main(100) == 4950, "f2.main(100)");
ok(f2Main(3000000) == 4950, "f2.main(3000000)");
var w = new Worker('http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_asmjs.js');
w.onmessage = function(e) {
ok(e.data === "ok", "Worker asm.js tests");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>