Bug 900669 - OdinMonkey: factor LinkAsmJS in preparation for later changes (r=bbouvier)
authorLuke Wagner <luke@mozilla.com>
Tue, 06 Aug 2013 15:54:30 -0500
changeset 154603 7abe5be6f8d2e0a2a8382331ca7040bc80a99e04
parent 154602 8b241c4e3eec80c5740a3b943d4205bec341136e
child 154604 25c8d8674c1fe0efa5220674930931ca36025842
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs900669
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 900669 - OdinMonkey: factor LinkAsmJS in preparation for later changes (r=bbouvier)
js/src/ion/AsmJSLink.cpp
--- a/js/src/ion/AsmJSLink.cpp
+++ b/js/src/ion/AsmJSLink.cpp
@@ -547,80 +547,102 @@ SendBlocksToPerf(JSContext *cx, AsmJSMod
 
         spewer.writeBlocksMap(funcBaseAddress, func.startCodeOffset, size, filename, method_name, func.blocks);
     }
 
     return true;
 }
 #endif
 
-// Implements the semantics of an asm.js module function that has been successfully validated.
-// A successfully validated asm.js module does not have bytecode emitted, but rather a list of
-// dynamic constraints that must be satisfied by the arguments passed by the caller. If these
-// constraints are satisfied, then LinkAsmJS can return CallAsmJS native functions that trampoline
-// into compiled code. If any of the constraints fails, LinkAsmJS reparses the entire asm.js module
-// from source so that it can be run as plain bytecode.
 static bool
-LinkAsmJS(JSContext *cx, unsigned argc, JS::Value *vp)
+SendModuleToAttachedProfiler(JSContext *cx, AsmJSModule &module)
 {
-    CallArgs args = CallArgsFromVp(argc, vp);
-    RootedFunction fun(cx, &args.callee().as<JSFunction>());
-    RootedObject moduleObj(cx,  &fun->getExtendedSlot(MODULE_FUN_SLOT).toObject());
-    AsmJSModule &module = AsmJSModuleObjectToModule(moduleObj);
-
-    // If linking fails, recompile the function (including emitting bytecode)
-    // as if it's normal JS code.
-    if (!DynamicallyLinkModule(cx, args, module)) {
-        RootedPropertyName name(cx, fun->name());
-        return HandleDynamicLinkFailure(cx, args, module, name);
-    }
-
 #if defined(MOZ_VTUNE)
     if (IsVTuneProfilingActive() && !SendFunctionsToVTune(cx, module))
         return false;
 #endif
 
 #if defined(JS_ION_PERF)
     if (!SendBlocksToPerf(cx, module))
         return false;
     if (!SendFunctionsToPerf(cx, module))
         return false;
 #endif
 
+    return true;
+}
+
+
+static JSObject *
+CreateExportObject(JSContext *cx, HandleObject moduleObj)
+{
+    AsmJSModule &module = AsmJSModuleObjectToModule(moduleObj);
+
     if (module.numExportedFunctions() == 1) {
         const AsmJSModule::ExportedFunction &func = module.exportedFunction(0);
-        if (!func.maybeFieldName()) {
-            RootedFunction fun(cx, NewExportedFunction(cx, func, moduleObj, 0));
-            if (!fun)
-                return false;
-
-            args.rval().set(ObjectValue(*fun));
-            return true;
-        }
+        if (!func.maybeFieldName())
+            return NewExportedFunction(cx, func, moduleObj, 0);
     }
 
     gc::AllocKind allocKind = gc::GetGCObjectKind(module.numExportedFunctions());
     RootedObject obj(cx, NewBuiltinClassInstance(cx, &JSObject::class_, allocKind));
     if (!obj)
-        return false;
+        return NULL;
 
     for (unsigned i = 0; i < module.numExportedFunctions(); i++) {
         const AsmJSModule::ExportedFunction &func = module.exportedFunction(i);
 
         RootedFunction fun(cx, NewExportedFunction(cx, func, moduleObj, i));
         if (!fun)
-            return false;
+            return NULL;
 
         JS_ASSERT(func.maybeFieldName() != NULL);
         RootedId id(cx, NameToId(func.maybeFieldName()));
         RootedValue val(cx, ObjectValue(*fun));
         if (!DefineNativeProperty(cx, obj, id, val, NULL, NULL, JSPROP_ENUMERATE, 0, 0))
-            return false;
+            return NULL;
     }
 
+    return obj;
+}
+
+// Implements the semantics of an asm.js module function that has been successfully validated.
+static bool
+LinkAsmJS(JSContext *cx, unsigned argc, JS::Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    // The LinkAsmJS builtin (created by NewAsmJSModuleFunction) is an extended
+    // function and stores its module in an extended slot.
+    RootedFunction fun(cx, &args.callee().as<JSFunction>());
+    RootedObject moduleObj(cx,  &fun->getExtendedSlot(MODULE_FUN_SLOT).toObject());
+    AsmJSModule &module = AsmJSModuleObjectToModule(moduleObj);
+
+    // Link the module by performing the link-time validation checks in the
+    // asm.js spec and then patching the generated module to associate it with
+    // the given heap (ArrayBuffer) and a new global data segment (the closure
+    // state shared by the inner asm.js functions).
+    if (!DynamicallyLinkModule(cx, args, module)) {
+        // Linking failed, so reparse the entire asm.js module from scratch to
+        // get normal interpreted bytecode which we can simply Invoke. Very slow.
+        RootedPropertyName name(cx, fun->name());
+        return HandleDynamicLinkFailure(cx, args, module, name);
+    }
+
+    // Notify profilers so that asm.js generated code shows up with JS function
+    // names and lines in native (i.e., not SPS) profilers.
+    if (!SendModuleToAttachedProfiler(cx, module))
+        return false;
+
+    // Link-time validation succeeded, so wrap all the exported functions with
+    // CallAsmJS builtins that trampoline into the generated code.
+    JSObject *obj = CreateExportObject(cx, moduleObj);
+    if (!obj)
+        return false;
+
     args.rval().set(ObjectValue(*obj));
     return true;
 }
 
 JSFunction *
 js::NewAsmJSModuleFunction(JSContext *cx, JSFunction *origFun, HandleObject moduleObj)
 {
     RootedPropertyName name(cx, origFun->name());