static bool SendFunctionsToPerf(JSContext *cx, AsmJSModule &module) { if (!PerfFuncEnabled()) return true; AsmJSPerfSpewer perfSpewer; unsigned long base = (unsigned long) module.functionCode(); const AsmJSModule::PostLinkFailureInfo &info = module.postLinkFailureInfo(); const char *filename = const_cast<char *>(info.scriptSource->filename()); for (unsigned i = 0; i < module.numPerfFunctions(); i++) { const AsmJSModule::ProfiledFunction &func = module.perfProfiledFunction(i); unsigned long start = base + (unsigned long) func.startCodeOffset; unsigned long end = base + (unsigned long) func.endCodeOffset; JS_ASSERT(end >= start); unsigned long size = (end - start); JSAutoByteString bytes; const char *method_name = AtomToPrintableString(cx, func.name, &bytes); if (!method_name) return false; unsigned lineno = func.lineno; unsigned columnIndex = func.columnIndex; perfSpewer.writeFunctionMap(start, size, filename, lineno, columnIndex, method_name); } return true; }
static bool SendBlocksToPerf(JSContext *cx, AsmJSModule &module) { if (!PerfBlockEnabled()) return true; AsmJSPerfSpewer spewer; unsigned long funcBaseAddress = (unsigned long) module.functionCode(); const AsmJSModule::PostLinkFailureInfo &info = module.postLinkFailureInfo(); const char *filename = const_cast<char *>(info.scriptSource->filename()); for (unsigned i = 0; i < module.numPerfBlocksFunctions(); i++) { const AsmJSModule::ProfiledBlocksFunction &func = module.perfProfiledBlocksFunction(i); unsigned long size = (unsigned long)func.endCodeOffset - (unsigned long)func.startCodeOffset; JSAutoByteString bytes; const char *method_name = AtomToPrintableString(cx, func.name, &bytes); if (!method_name) return false; spewer.writeBlocksMap(funcBaseAddress, func.startCodeOffset, size, filename, method_name, func.blocks); } return true; }
static bool HandleDynamicLinkFailure(JSContext *cx, CallArgs args, AsmJSModule &module, HandlePropertyName name) { if (cx->isExceptionPending()) return false; const AsmJSModule::PostLinkFailureInfo &info = module.postLinkFailureInfo(); uint32_t length = info.bufEnd - info.bufStart; Rooted<JSStableString*> src(cx, info.scriptSource->substring(cx, info.bufStart, info.bufEnd)); if (!src) return false; RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, cx->global(), name, JSFunction::FinalizeKind, TenuredObject)); if (!fun) return false; AutoNameVector formals(cx); formals.reserve(3); if (module.globalArgumentName()) formals.infallibleAppend(module.globalArgumentName()); if (module.importArgumentName()) formals.infallibleAppend(module.importArgumentName()); if (module.bufferArgumentName()) formals.infallibleAppend(module.bufferArgumentName()); CompileOptions options(cx); options.setPrincipals(cx->compartment()->principals) .setOriginPrincipals(info.scriptSource->originPrincipals()) .setCompileAndGo(false) .setNoScriptRval(false); if (!frontend::CompileFunctionBody(cx, &fun, options, formals, src->chars().get(), length)) return false; // Call the function we just recompiled. unsigned argc = args.length(); InvokeArgs args2(cx); if (!args2.init(argc)) return false; args2.setCallee(ObjectValue(*fun)); args2.setThis(args.thisv()); for (unsigned i = 0; i < argc; i++) args2[i].set(args[i]); if (!Invoke(cx, args2)) return false; args.rval().set(args2.rval()); return true; }
static bool HandleDynamicLinkFailure(JSContext *cx, CallArgs args, AsmJSModule &module, HandlePropertyName name) { if (cx->isExceptionPending()) return false; const AsmJSModule::PostLinkFailureInfo &info = module.postLinkFailureInfo(); uint32_t length = info.bufEnd_ - info.bufStart_; Rooted<JSFlatString*> src(cx, info.scriptSource_->substring(cx, info.bufStart_, info.bufEnd_)); const jschar *chars = src->chars(); RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, cx->global(), name)); if (!fun) return false; AutoNameVector formals(cx); formals.reserve(3); if (module.globalArgumentName()) formals.infallibleAppend(module.globalArgumentName()); if (module.importArgumentName()) formals.infallibleAppend(module.importArgumentName()); if (module.bufferArgumentName()) formals.infallibleAppend(module.bufferArgumentName()); if (!frontend::CompileFunctionBody(cx, &fun, info.options_, formals, chars, length, /* isAsmJSRecompile = */ true)) return false; // Call the function we just recompiled. unsigned argc = args.length(); JS_ASSERT(argc <= 3); InvokeArgsGuard args2; if (!cx->stack.pushInvokeArgs(cx, args.length(), &args2)) return false; args2.setCallee(ObjectValue(*fun)); args2.setThis(args.thisv()); if (argc > 0) args2[0] = args[0]; if (argc > 1) args2[1] = args[1]; if (argc > 2) args2[2] = args[2]; if (!Invoke(cx, args2)) return false; args.rval().set(args2.rval()); return true; }