static bool SendBlocksToPerf(JSContext *cx, AsmJSModule &module) { if (!PerfBlockEnabled()) return true; unsigned long funcBaseAddress = (unsigned long) module.functionCode(); const char *filename = module.sourceDesc().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.functionCode(); const char *filename = module.sourceDesc().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 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 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 SendFunctionsToVTune(JSContext *cx, AsmJSModule &module) { uint8_t *base = module.functionCode(); 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 = js_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 = NULL; method.class_id = 0; method.class_file_name = NULL; method.source_file_name = NULL; iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void *)&method); } return true; }
static bool DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module) { if (module.isLinked()) return LinkFail(cx, "As a temporary limitation, modules cannot be linked more than " "once. This limitation should be removed in a future release. To " "work around this, compile a second module (e.g., using the " "Function constructor)."); RootedValue globalVal(cx, UndefinedValue()); if (args.length() > 0) globalVal = args[0]; RootedValue importVal(cx, UndefinedValue()); if (args.length() > 1) importVal = args[1]; RootedValue bufferVal(cx, UndefinedValue()); if (args.length() > 2) bufferVal = args[2]; Rooted<ArrayBufferObject*> heap(cx); if (module.hasArrayView()) { if (!IsTypedArrayBuffer(bufferVal)) return LinkFail(cx, "bad ArrayBuffer argument"); heap = &bufferVal.toObject().as<ArrayBufferObject>(); if (!IsPowerOfTwo(heap->byteLength()) || heap->byteLength() < AsmJSAllocationGranularity) return LinkFail(cx, "ArrayBuffer byteLength must be a power of two greater than or equal to 4096"); if (!ArrayBufferObject::prepareForAsmJS(cx, heap)) return LinkFail(cx, "Unable to prepare ArrayBuffer for asm.js use"); #if defined(JS_CPU_X86) void *heapOffset = (void*)heap->dataPointer(); void *heapLength = (void*)heap->byteLength(); uint8_t *code = module.functionCode(); for (unsigned i = 0; i < module.numHeapAccesses(); i++) { const AsmJSHeapAccess &access = module.heapAccess(i); JSC::X86Assembler::setPointer(access.patchLengthAt(code), heapLength); JSC::X86Assembler::setPointer(access.patchOffsetAt(code), heapOffset); } #elif defined(JS_CPU_ARM) // Now the length of the array is know, patch all of the bounds check sites // with the new length. jit::IonContext ic(cx, NULL); module.patchBoundsChecks(heap->byteLength()); #endif } 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: if (!ValidateArrayView(cx, global, globalVal, bufferVal)) return false; break; case AsmJSModule::Global::MathBuiltin: if (!ValidateMathBuiltin(cx, global, globalVal)) return false; break; case AsmJSModule::Global::Constant: if (!ValidateGlobalConstant(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.setIsLinked(heap); return true; }