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 SendModuleToAttachedProfiler(JSContext* cx, AsmJSModule& module) { #if defined(MOZ_VTUNE) if (IsVTuneProfilingActive() && !SendFunctionsToVTune(cx, module)) return false; #endif #if defined(JS_ION_PERF) if (module.numExportedFunctions() > 0) { size_t firstEntryCode = size_t(module.codeBase() + module.functionBytes()); writePerfSpewerAsmJSEntriesAndExits(firstEntryCode, module.codeBytes() - module.functionBytes()); } if (!SendFunctionsToPerf(cx, module)) return false; #endif return true; }
static bool SendFunctionsToVTune(JSContext *cx, AsmJSModule &module) { uint8_t *base = module.codeBase(); for (unsigned i = 0; i < module.numProfiledFunctions(); i++) { const AsmJSModule::ProfiledFunction &func = module.profiledFunction(i); uint8_t *start = base + func.startCodeOffset; uint8_t *end = base + func.endCodeOffset; JS_ASSERT(end >= start); unsigned method_id = iJIT_GetNewMethodID(); if (method_id == 0) return false; JSAutoByteString bytes; const char *method_name = AtomToPrintableString(cx, func.name, &bytes); if (!method_name) return false; iJIT_Method_Load method; method.method_id = method_id; method.method_name = const_cast<char *>(method_name); method.method_load_address = (void *)start; method.method_size = unsigned(end - start); method.line_number_size = 0; method.line_number_table = nullptr; method.class_id = 0; method.class_file_name = nullptr; method.source_file_name = nullptr; iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void *)&method); } return true; }
static bool DynamicallyLinkModule(JSContext* cx, const CallArgs& args, AsmJSModule& module) { module.setIsDynamicallyLinked(cx->runtime()); HandleValue globalVal = args.get(0); HandleValue importVal = args.get(1); HandleValue bufferVal = args.get(2); Rooted<ArrayBufferObjectMaybeShared*> heap(cx); if (module.hasArrayView()) { if (module.isSharedView() && !IsSharedArrayBuffer(bufferVal)) return LinkFail(cx, "shared views can only be constructed onto SharedArrayBuffer"); if (!module.isSharedView() && !IsArrayBuffer(bufferVal)) return LinkFail(cx, "unshared views can only be constructed onto ArrayBuffer"); heap = &AsAnyArrayBuffer(bufferVal); if (!LinkModuleToHeap(cx, module, heap)) return false; } AutoObjectVector ffis(cx); if (!ffis.resize(module.numFFIs())) return false; for (unsigned i = 0; i < module.numGlobals(); i++) { AsmJSModule::Global& global = module.global(i); switch (global.which()) { case AsmJSModule::Global::Variable: if (!ValidateGlobalVariable(cx, module, global, importVal)) return false; break; case AsmJSModule::Global::FFI: if (!ValidateFFI(cx, global, importVal, &ffis)) return false; break; case AsmJSModule::Global::ArrayView: case AsmJSModule::Global::SharedArrayView: case AsmJSModule::Global::ArrayViewCtor: if (!ValidateArrayView(cx, global, globalVal, module.hasArrayView() && module.isSharedView())) return false; break; case AsmJSModule::Global::ByteLength: if (!ValidateByteLength(cx, globalVal)) return false; break; case AsmJSModule::Global::MathBuiltinFunction: if (!ValidateMathBuiltinFunction(cx, global, globalVal)) return false; break; case AsmJSModule::Global::AtomicsBuiltinFunction: if (!ValidateAtomicsBuiltinFunction(cx, global, globalVal)) return false; break; case AsmJSModule::Global::Constant: if (!ValidateConstant(cx, global, globalVal)) return false; break; case AsmJSModule::Global::SimdCtor: if (!ValidateSimdType(cx, global, globalVal)) return false; break; case AsmJSModule::Global::SimdOperation: if (!ValidateSimdOperation(cx, global, globalVal)) return false; break; } } for (unsigned i = 0; i < module.numExits(); i++) module.exitIndexToGlobalDatum(i).fun = &ffis[module.exit(i).ffiIndex()]->as<JSFunction>(); module.initGlobalNaN(); // See the comment in AllocateExecutableMemory. ExecutableAllocator::makeExecutable(module.codeBase(), module.codeBytes()); return true; }