static bool HandleDynamicLinkFailure(JSContext *cx, CallArgs args, AsmJSModule &module, HandlePropertyName name) { if (cx->isExceptionPending()) return false; uint32_t begin = module.srcBodyStart(); // starts right after 'use asm' uint32_t end = module.srcEndBeforeCurly(); Rooted<JSFlatString*> src(cx, module.scriptSource()->substringDontDeflate(cx, begin, end)); if (!src) return false; RootedFunction fun(cx, NewScriptedFunction(cx, 0, JSFunction::INTERPRETED, name, JSFunction::FinalizeKind, TenuredObject)); if (!fun) return false; AutoNameVector formals(cx); if (!formals.reserve(3)) return false; 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.setMutedErrors(module.scriptSource()->mutedErrors()) .setFile(module.scriptSource()->filename()) .setCompileAndGo(false) .setNoScriptRval(false); // The exported function inherits an implicit strict context if the module // also inherited it somehow. if (module.strict()) options.strictOption = true; AutoStableStringChars stableChars(cx); if (!stableChars.initTwoByte(cx, src)) return false; const char16_t *chars = stableChars.twoByteRange().start().get(); SourceBufferHolder::Ownership ownership = stableChars.maybeGiveOwnershipToCaller() ? SourceBufferHolder::GiveOwnership : SourceBufferHolder::NoOwnership; SourceBufferHolder srcBuf(chars, end - begin, ownership); if (!frontend::CompileFunctionBody(cx, &fun, options, formals, srcBuf, /* enclosingScope = */ NullPtr())) return false; // Call the function we just recompiled. args.setCallee(ObjectValue(*fun)); return Invoke(cx, args, args.isConstructing() ? CONSTRUCT : NO_CONSTRUCT); }
static bool HandleDynamicLinkFailure(JSContext *cx, CallArgs args, AsmJSModule &module, HandlePropertyName name) { if (cx->isExceptionPending()) return false; uint32_t begin = module.charsBegin(); uint32_t end = module.charsEnd(); Rooted<JSStableString*> src(cx, module.scriptSource()->substring(cx, begin, end)); if (!src) return false; RootedFunction fun(cx, NewFunction(cx, NullPtr(), nullptr, 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(module.scriptSource()->originPrincipals()) .setCompileAndGo(false) .setNoScriptRval(false); if (!frontend::CompileFunctionBody(cx, &fun, options, formals, src->chars().get(), end - begin)) 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 SendBlocksToPerf(JSContext *cx, AsmJSModule &module) { if (!PerfBlockEnabled()) return true; unsigned long funcBaseAddress = (unsigned long) module.codeBase(); const char *filename = module.scriptSource()->filename(); for (unsigned i = 0; i < module.numPerfBlocksFunctions(); i++) { const AsmJSModule::ProfiledBlocksFunction &func = module.perfProfiledBlocksFunction(i); size_t size = func.endCodeOffset - func.startCodeOffset; JSAutoByteString bytes; const char *name = AtomToPrintableString(cx, func.name, &bytes); if (!name) return false; writePerfSpewerAsmJSBlocksMap(funcBaseAddress, func.startCodeOffset, func.endInlineCodeOffset, size, filename, name, func.blocks); } return true; }
static bool SendFunctionsToPerf(JSContext *cx, AsmJSModule &module) { if (!PerfFuncEnabled()) return true; uintptr_t base = (uintptr_t) module.codeBase(); const char *filename = module.scriptSource()->filename(); for (unsigned i = 0; i < module.numPerfFunctions(); i++) { const AsmJSModule::ProfiledFunction &func = module.perfProfiledFunction(i); uintptr_t start = base + (unsigned long) func.startCodeOffset; uintptr_t end = base + (unsigned long) func.endCodeOffset; JS_ASSERT(end >= start); size_t size = end - start; JSAutoByteString bytes; const char *name = AtomToPrintableString(cx, func.name, &bytes); if (!name) return false; writePerfSpewerAsmJSFunctionMap(start, size, filename, func.lineno, func.columnIndex, name); } return true; }
static bool HandleDynamicLinkFailure(JSContext *cx, CallArgs args, AsmJSModule &module, HandlePropertyName name) { if (cx->isExceptionPending()) return false; uint32_t begin = module.offsetToEndOfUseAsm(); uint32_t end = module.funcEndBeforeCurly(); Rooted<JSFlatString*> src(cx, module.scriptSource()->substring(cx, begin, end)); if (!src) return false; RootedFunction fun(cx, NewFunction(cx, NullPtr(), nullptr, 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.setOriginPrincipals(module.scriptSource()->originPrincipals()) .setFile(module.scriptSource()->filename()) .setCompileAndGo(false) .setNoScriptRval(false); // The exported function inherits an implicit strict context if the module // also inherited it somehow. if (module.strict()) options.strictOption = true; SourceBufferHolder srcBuf(src->chars(), end - begin, SourceBufferHolder::NoOwnership); if (!frontend::CompileFunctionBody(cx, &fun, options, formals, srcBuf)) return false; // Call the function we just recompiled. args.setCallee(ObjectValue(*fun)); return Invoke(cx, args, args.isConstructing() ? CONSTRUCT : NO_CONSTRUCT); }
static bool HandleDynamicLinkFailure(JSContext* cx, const CallArgs& args, AsmJSModule& module, HandlePropertyName name) { if (cx->isExceptionPending()) return false; // Source discarding is allowed to affect JS semantics because it is never // enabled for normal JS content. bool haveSource = module.scriptSource()->hasSourceData(); if (!haveSource && !JSScript::loadSource(cx, module.scriptSource(), &haveSource)) return false; if (!haveSource) { JS_ReportError(cx, "asm.js link failure with source discarding enabled"); return false; } uint32_t begin = module.srcBodyStart(); // starts right after 'use asm' uint32_t end = module.srcEndBeforeCurly(); Rooted<JSFlatString*> src(cx, module.scriptSource()->substringDontDeflate(cx, begin, end)); if (!src) return false; RootedFunction fun(cx, NewScriptedFunction(cx, 0, JSFunction::INTERPRETED_NORMAL, name, gc::AllocKind::FUNCTION, TenuredObject)); if (!fun) return false; Rooted<PropertyNameVector> formals(cx, PropertyNameVector(cx)); if (!formals.reserve(3)) return false; 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.setMutedErrors(module.scriptSource()->mutedErrors()) .setFile(module.scriptSource()->filename()) .setNoScriptRval(false); // The exported function inherits an implicit strict context if the module // also inherited it somehow. if (module.strict()) options.strictOption = true; AutoStableStringChars stableChars(cx); if (!stableChars.initTwoByte(cx, src)) return false; const char16_t* chars = stableChars.twoByteRange().start().get(); SourceBufferHolder::Ownership ownership = stableChars.maybeGiveOwnershipToCaller() ? SourceBufferHolder::GiveOwnership : SourceBufferHolder::NoOwnership; SourceBufferHolder srcBuf(chars, end - begin, ownership); if (!frontend::CompileFunctionBody(cx, &fun, options, formals, srcBuf, /* enclosingScope = */ nullptr)) return false; // Call the function we just recompiled. args.setCallee(ObjectValue(*fun)); return Invoke(cx, args, args.isConstructing() ? CONSTRUCT : NO_CONSTRUCT); }