Bug 1615066 - Add support for new profiler-get-symbols version which supports partial file reading. r=canaltinova

Differential Revision: https://phabricator.services.mozilla.com/D117938
This commit is contained in:
Markus Stange 2021-07-30 20:39:54 +00:00
Родитель a2997cb1c6
Коммит 124dd3228f
4 изменённых файлов: 485 добавлений и 471 удалений

Просмотреть файл

@ -544,3 +544,16 @@ export type SymbolicationWorkerReplyData<R> =
| {
error: SymbolicationWorkerError;
};
// This type is used in the symbolication worker for the return type of the
// FileAndPathHelper's readFile method.
// FIXME: Or rather, this type *would* be used if the worker code was checked
// by TypeScript.
export interface FileHandle {
// Return the length of the file in bytes.
getLength: () => number;
// Synchronously read the bytes at offset `offset` into the array `dest`.
readBytesInto: (dest: Uint8Array, offset: number) => void;
// Called when the file is no longer needed, to allow closing the file.
drop: () => void;
}

Просмотреть файл

@ -6,213 +6,32 @@
// THIS FILE IS AUTOGENERATED by wasm-bindgen.
//
// Generated from:
// https://github.com/mstange/profiler-get-symbols/commit/90ee39f1d18d2727f07dc57bd93cff6bc73ce8a0
// https://github.com/mstange/profiler-get-symbols/commit/c1dca28a2a506df40f0a6f32c12ba51ec54b02be
// by following the instructions in that repository's Readme.md
//
let wasm_bindgen;
(function() {
const __exports = {};
let wasm;
let cachegetInt32Memory = null;
function getInt32Memory() {
if (cachegetInt32Memory === null || cachegetInt32Memory.buffer !== wasm.memory.buffer) {
cachegetInt32Memory = new Int32Array(wasm.memory.buffer);
}
return cachegetInt32Memory;
}
let cachegetUint32Memory = null;
function getUint32Memory() {
if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== wasm.memory.buffer) {
cachegetUint32Memory = new Uint32Array(wasm.memory.buffer);
}
return cachegetUint32Memory;
}
function getArrayU32FromWasm(ptr, len) {
return getUint32Memory().subarray(ptr / 4, ptr / 4 + len);
}
let cachegetUint8Memory = null;
function getUint8Memory() {
if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== wasm.memory.buffer) {
cachegetUint8Memory = new Uint8Array(wasm.memory.buffer);
}
return cachegetUint8Memory;
}
function getArrayU8FromWasm(ptr, len) {
return getUint8Memory().subarray(ptr / 1, ptr / 1 + len);
}
const heap = new Array(32);
heap.fill(undefined);
const heap = new Array(32).fill(undefined);
heap.push(undefined, null, true, false);
let stack_pointer = 32;
function addBorrowedObject(obj) {
if (stack_pointer == 1) throw new Error('out of js stack');
heap[--stack_pointer] = obj;
return stack_pointer;
}
function _assertClass(instance, klass) {
if (!(instance instanceof klass)) {
throw new Error(`expected instance of ${klass.name}`);
}
return instance.ptr;
}
let WASM_VECTOR_LEN = 0;
let cachedTextEncoder = new TextEncoder('utf-8');
let passStringToWasm;
if (typeof cachedTextEncoder.encodeInto === 'function') {
passStringToWasm = function(arg) {
let size = arg.length;
let ptr = wasm.__wbindgen_malloc(size);
let offset = 0;
{
const mem = getUint8Memory();
for (; offset < arg.length; offset++) {
const code = arg.charCodeAt(offset);
if (code > 0x7F) break;
mem[ptr + offset] = code;
}
}
if (offset !== arg.length) {
arg = arg.slice(offset);
ptr = wasm.__wbindgen_realloc(ptr, size, size = offset + arg.length * 3);
const view = getUint8Memory().subarray(ptr + offset, ptr + size);
const ret = cachedTextEncoder.encodeInto(arg, view);
offset += ret.written;
}
WASM_VECTOR_LEN = offset;
return ptr;
};
} else {
passStringToWasm = function(arg) {
let size = arg.length;
let ptr = wasm.__wbindgen_malloc(size);
let offset = 0;
{
const mem = getUint8Memory();
for (; offset < arg.length; offset++) {
const code = arg.charCodeAt(offset);
if (code > 0x7F) break;
mem[ptr + offset] = code;
}
}
if (offset !== arg.length) {
const buf = cachedTextEncoder.encode(arg.slice(offset));
ptr = wasm.__wbindgen_realloc(ptr, size, size = offset + buf.length);
getUint8Memory().set(buf, ptr + offset);
offset += buf.length;
}
WASM_VECTOR_LEN = offset;
return ptr;
};
}
/**
* @param {WasmMemBuffer} binary_data
* @param {WasmMemBuffer} debug_data
* @param {string} breakpad_id
* @returns {CompactSymbolTable}
*/
__exports.get_compact_symbol_table = function(binary_data, debug_data, breakpad_id) {
_assertClass(binary_data, WasmMemBuffer);
_assertClass(debug_data, WasmMemBuffer);
const ret = wasm.get_compact_symbol_table(binary_data.ptr, debug_data.ptr, passStringToWasm(breakpad_id), WASM_VECTOR_LEN);
return CompactSymbolTable.__wrap(ret);
};
function getObject(idx) { return heap[idx]; }
function debugString(val) {
// primitive types
const type = typeof val;
if (type == 'number' || type == 'boolean' || val == null) {
return `${val}`;
}
if (type == 'string') {
return `"${val}"`;
}
if (type == 'symbol') {
const description = val.description;
if (description == null) {
return 'Symbol';
} else {
return `Symbol(${description})`;
}
}
if (type == 'function') {
const name = val.name;
if (typeof name == 'string' && name.length > 0) {
return `Function(${name})`;
} else {
return 'Function';
}
}
// objects
if (Array.isArray(val)) {
const length = val.length;
let debug = '[';
if (length > 0) {
debug += debugString(val[0]);
}
for(let i = 1; i < length; i++) {
debug += ', ' + debugString(val[i]);
}
debug += ']';
return debug;
}
// Test for built-in
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
let className;
if (builtInMatches.length > 1) {
className = builtInMatches[1];
} else {
// Failed to match the standard '[object ClassName]'
return toString.call(val);
}
if (className == 'Object') {
// we're a user defined class or Object
// JSON.stringify avoids problems with cycles, and is generally much
// easier than looping through ownProperties of `val`.
try {
return 'Object(' + JSON.stringify(val) + ')';
} catch (_) {
return 'Object';
}
}
// errors
if (val instanceof Error) {
return `${val.name}: ${val.message}\n${val.stack}`;
}
// TODO we could test for more things here, like `Set`s and `Map`s.
return className;
}
let cachedTextDecoder = new TextDecoder('utf-8');
function getStringFromWasm(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len));
}
let heap_next = heap.length;
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
heap[idx] = obj;
return idx;
}
function dropObject(idx) {
if (idx < 36) return;
heap[idx] = heap_next;
@ -225,202 +44,413 @@ function takeObject(idx) {
return ret;
}
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
heap[idx] = obj;
return idx;
cachedTextDecoder.decode();
let cachegetUint8Memory0 = null;
function getUint8Memory0() {
if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachegetUint8Memory0;
}
function handleError(e) {
wasm.__wbindgen_exn_store(addHeapObject(e));
function getStringFromWasm0(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
/**
*/
class CompactSymbolTable {
static __wrap(ptr) {
const obj = Object.create(CompactSymbolTable.prototype);
obj.ptr = ptr;
let WASM_VECTOR_LEN = 0;
return obj;
}
let cachedTextEncoder = new TextEncoder('utf-8');
free() {
const ptr = this.ptr;
this.ptr = 0;
wasm.__wbg_compactsymboltable_free(ptr);
}
/**
* @returns {CompactSymbolTable}
*/
constructor() {
const ret = wasm.compactsymboltable_new();
return CompactSymbolTable.__wrap(ret);
}
/**
* @returns {Uint32Array}
*/
take_addr() {
const retptr = 8;
const ret = wasm.compactsymboltable_take_addr(retptr, this.ptr);
const memi32 = getInt32Memory();
const v0 = getArrayU32FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 4);
return v0;
}
/**
* @returns {Uint32Array}
*/
take_index() {
const retptr = 8;
const ret = wasm.compactsymboltable_take_index(retptr, this.ptr);
const memi32 = getInt32Memory();
const v0 = getArrayU32FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 4);
return v0;
}
/**
* @returns {Uint8Array}
*/
take_buffer() {
const retptr = 8;
const ret = wasm.compactsymboltable_take_buffer(retptr, this.ptr);
const memi32 = getInt32Memory();
const v0 = getArrayU8FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 1);
return v0;
}
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
? function (arg, view) {
return cachedTextEncoder.encodeInto(arg, view);
}
__exports.CompactSymbolTable = CompactSymbolTable;
/**
* WasmMemBuffer lets you allocate a chunk of memory on the wasm heap and
* directly initialize it from JS without a copy. The constructor takes the
* allocation size and a callback function which does the initialization.
* This is useful if you need to get very large amounts of data from JS into
* wasm (for example, the contents of a 1.7GB libxul.so).
*/
class WasmMemBuffer {
: function (arg, view) {
const buf = cachedTextEncoder.encode(arg);
view.set(buf);
return {
read: arg.length,
written: buf.length
};
});
static __wrap(ptr) {
const obj = Object.create(WasmMemBuffer.prototype);
obj.ptr = ptr;
function passStringToWasm0(arg, malloc, realloc) {
return obj;
if (realloc === undefined) {
const buf = cachedTextEncoder.encode(arg);
const ptr = malloc(buf.length);
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
WASM_VECTOR_LEN = buf.length;
return ptr;
}
free() {
const ptr = this.ptr;
this.ptr = 0;
let len = arg.length;
let ptr = malloc(len);
wasm.__wbg_wasmmembuffer_free(ptr);
const mem = getUint8Memory0();
let offset = 0;
for (; offset < len; offset++) {
const code = arg.charCodeAt(offset);
if (code > 0x7F) break;
mem[ptr + offset] = code;
}
/**
* Create the buffer and initialize it synchronously in the callback function.
* f is called with one argument: the Uint8Array that wraps our buffer.
* f should not return anything; its return value is ignored.
* f must not call any exported wasm functions! Anything that causes the
* wasm heap to resize will invalidate the typed array\'s internal buffer!
* Do not hold on to the array that is passed to f after f completes.
* @param {number} byte_length
* @param {any} f
* @returns {WasmMemBuffer}
*/
constructor(byte_length, f) {
if (offset !== len) {
if (offset !== 0) {
arg = arg.slice(offset);
}
ptr = realloc(ptr, len, len = offset + arg.length * 3);
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
const ret = encodeString(arg, view);
offset += ret.written;
}
WASM_VECTOR_LEN = offset;
return ptr;
}
function isLikeNone(x) {
return x === undefined || x === null;
}
let cachegetInt32Memory0 = null;
function getInt32Memory0() {
if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) {
cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachegetInt32Memory0;
}
function makeMutClosure(arg0, arg1, dtor, f) {
const state = { a: arg0, b: arg1, cnt: 1, dtor };
const real = (...args) => {
// First up with a closure we increment the internal reference
// count. This ensures that the Rust closure environment won't
// be deallocated while we're invoking it.
state.cnt++;
const a = state.a;
state.a = 0;
try {
const ret = wasm.wasmmembuffer_new(byte_length, addBorrowedObject(f));
return WasmMemBuffer.__wrap(ret);
return f(a, state.b, ...args);
} finally {
heap[stack_pointer++] = undefined;
if (--state.cnt === 0) {
wasm.__wbindgen_export_2.get(state.dtor)(a, state.b);
} else {
state.a = a;
}
}
};
real.original = state;
return real;
}
function __wbg_adapter_18(arg0, arg1, arg2) {
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h0f6e06591fd1eecd(arg0, arg1, addHeapObject(arg2));
}
function handleError(f, args) {
try {
return f.apply(this, args);
} catch (e) {
wasm.__wbindgen_exn_store(addHeapObject(e));
}
}
function __wbg_adapter_33(arg0, arg1, arg2, arg3) {
wasm.wasm_bindgen__convert__closures__invoke2_mut__hb11591fa7d9b8977(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
}
/**
* Usage:
*
* ```js
* async function getSymbolTable(debugName, breakpadId, libKeyToPathMap) {
* const helper = {
* getCandidatePathsForBinaryOrPdb: (debugName, breakpadId) => {
* const path = libKeyToPathMap.get(`${debugName}/${breakpadId}`);
* if (path !== undefined) {
* return [path];
* }
* return [];
* },
* readFile: async (filename) => {
* const byteLength = await getFileSizeInBytes(filename);
* const fileHandle = getFileHandle(filename);
* return {
* getLength: () => byteLength,
* readBytesInto: (array, offset) => {
* syncReadFilePartIntoBuffer(fileHandle, array, offset);
* },
* drop: () => {},
* };
* },
* };
*
* const [addr, index, buffer] = await getCompactSymbolTable(debugName, breakpadId, helper);
* return [addr, index, buffer];
* }
* ```
* @param {string} debug_name
* @param {string} breakpad_id
* @param {any} helper
* @returns {Promise<any>}
*/
__exports.getCompactSymbolTable = function(debug_name, breakpad_id, helper) {
var ptr0 = passStringToWasm0(debug_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
var ptr1 = passStringToWasm0(breakpad_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len1 = WASM_VECTOR_LEN;
var ret = wasm.getCompactSymbolTable(ptr0, len0, ptr1, len1, addHeapObject(helper));
return takeObject(ret);
};
/**
* Usage:
*
* ```js
* async function getSymbolTable(url, requestJSONString, libKeyToPathMap) {
* const helper = {
* getCandidatePathsForBinaryOrPdb: (debugName, breakpadId) => {
* const path = libKeyToPathMap.get(`${debugName}/${breakpadId}`);
* if (path !== undefined) {
* return [path];
* }
* return [];
* },
* readFile: async (filename) => {
* const byteLength = await getFileSizeInBytes(filename);
* const fileHandle = getFileHandle(filename);
* return {
* getLength: () => byteLength,
* readBytesInto: (array, offset) => {
* syncReadFilePartIntoBuffer(fileHandle, array, offset);
* },
* drop: () => {},
* };
* },
* };
*
* const responseJSONString = await queryAPI(deburlugName, requestJSONString, helper);
* return responseJSONString;
* }
* ```
* @param {string} url
* @param {string} request_json
* @param {any} helper
* @returns {Promise<any>}
*/
__exports.queryAPI = function(url, request_json, helper) {
var ptr0 = passStringToWasm0(url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
var ptr1 = passStringToWasm0(request_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len1 = WASM_VECTOR_LEN;
var ret = wasm.queryAPI(ptr0, len0, ptr1, len1, addHeapObject(helper));
return takeObject(ret);
};
async function load(module, imports) {
if (typeof Response === 'function' && module instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
return await WebAssembly.instantiateStreaming(module, imports);
} catch (e) {
if (module.headers.get('Content-Type') != 'application/wasm') {
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
} else {
throw e;
}
}
}
const bytes = await module.arrayBuffer();
return await WebAssembly.instantiate(bytes, imports);
} else {
const instance = await WebAssembly.instantiate(module, imports);
if (instance instanceof WebAssembly.Instance) {
return { instance, module };
} else {
return instance;
}
}
}
__exports.WasmMemBuffer = WasmMemBuffer;
function init(module) {
let result;
async function init(input) {
if (typeof input === 'undefined') {
let src;
if (typeof document === 'undefined') {
src = location.href;
} else {
src = document.currentScript.src;
}
input = src.replace(/\.js$/, '_bg.wasm');
}
const imports = {};
imports.wbg = {};
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
const ret = debugString(getObject(arg1));
const ret0 = passStringToWasm(ret);
const ret1 = WASM_VECTOR_LEN;
getInt32Memory()[arg0 / 4 + 0] = ret0;
getInt32Memory()[arg0 / 4 + 1] = ret1;
};
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm(arg0, arg1));
};
imports.wbg.__wbindgen_rethrow = function(arg0) {
throw takeObject(arg0);
};
imports.wbg.__wbindgen_memory = function() {
const ret = wasm.memory;
return addHeapObject(ret);
};
imports.wbg.__wbg_buffer_aa8ebea80955a01a = function(arg0) {
const ret = getObject(arg0).buffer;
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_3e607c21646a8aef = function(arg0, arg1, arg2) {
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
var ret = getObject(arg0);
return addHeapObject(ret);
};
imports.wbg.__wbg_drop_6095f5f9a28379e4 = function() { return handleError(function (arg0) {
getObject(arg0).drop();
}, arguments) };
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbg_call_9c879b23724d007e = function(arg0, arg1, arg2) {
try {
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
} catch (e) {
handleError(e)
imports.wbg.__wbg_call_3fc07b7d5fc9022d = function() { return handleError(function (arg0, arg1, arg2) {
var ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
var ret = getStringFromWasm0(arg0, arg1);
return addHeapObject(ret);
};
imports.wbg.__wbg_readFile_1005cc171b90cf75 = function(arg0, arg1, arg2) {
var ret = getObject(arg0).readFile(getStringFromWasm0(arg1, arg2));
return addHeapObject(ret);
};
imports.wbg.__wbg_then_6c9a4bf55755f9b8 = function(arg0, arg1, arg2) {
var ret = getObject(arg0).then(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_cb_drop = function(arg0) {
const obj = takeObject(arg0).original;
if (obj.cnt-- == 1) {
obj.a = 0;
return true;
}
var ret = false;
return ret;
};
imports.wbg.__wbg_getLength_83c461bbda972f3b = function() { return handleError(function (arg0) {
var ret = getObject(arg0).getLength();
return ret;
}, arguments) };
imports.wbg.__wbg_name_966f168ad0e59c92 = function(arg0) {
var ret = getObject(arg0).name;
return addHeapObject(ret);
};
imports.wbg.__wbg_message_e440fbd911a845a2 = function(arg0) {
var ret = getObject(arg0).message;
return addHeapObject(ret);
};
imports.wbg.__wbindgen_memory = function() {
var ret = wasm.memory;
return addHeapObject(ret);
};
imports.wbg.__wbg_buffer_9e184d6f785de5ed = function(arg0) {
var ret = getObject(arg0).buffer;
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_d92dfdd78c30c55a = function(arg0, arg1, arg2) {
var ret = new Uint32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_new_71de2365d17503e7 = function(arg0) {
var ret = new Uint32Array(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_e57ad1f2ce812c03 = function(arg0, arg1, arg2) {
var ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_new_e8101319e4cf95fc = function(arg0) {
var ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_of_7c797480f9ceac60 = function(arg0, arg1, arg2) {
var ret = Array.of(getObject(arg0), getObject(arg1), getObject(arg2));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_json_parse = function(arg0, arg1) {
const ret = JSON.parse(getStringFromWasm(arg0, arg1));
var ret = JSON.parse(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbg_readBytesInto_02ee0cacc563822d = function() { return handleError(function (arg0, arg1, arg2) {
getObject(arg0).readBytesInto(takeObject(arg1), arg2);
}, arguments) };
imports.wbg.__wbg_getCandidatePathsForBinaryOrPdb_6ff1ea4b13b7cbee = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
var ret = getObject(arg0).getCandidatePathsForBinaryOrPdb(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_from_f4f6c9225e58242f = function(arg0) {
var ret = Array.from(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_length_555f836564bf148d = function(arg0) {
var ret = getObject(arg0).length;
return ret;
};
imports.wbg.__wbg_get_b7bbf50adcc94294 = function(arg0, arg1) {
var ret = getObject(arg0)[arg1 >>> 0];
return addHeapObject(ret);
};
imports.wbg.__wbg_new_c143a4f563f78c4e = function(arg0, arg1) {
try {
var state0 = {a: arg0, b: arg1};
var cb0 = (arg0, arg1) => {
const a = state0.a;
state0.a = 0;
try {
return __wbg_adapter_33(a, state0.b, arg0, arg1);
} finally {
state0.a = a;
}
};
var ret = new Promise(cb0);
return addHeapObject(ret);
} finally {
state0.a = state0.b = 0;
}
};
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
const obj = getObject(arg1);
var ret = typeof(obj) === 'string' ? obj : undefined;
var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
imports.wbg.__wbg_then_c2361a9d5c9a4fcb = function(arg0, arg1) {
var ret = getObject(arg0).then(getObject(arg1));
return addHeapObject(ret);
};
imports.wbg.__wbg_resolve_cae3d8f752f5db88 = function(arg0) {
var ret = Promise.resolve(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper230 = function(arg0, arg1, arg2) {
var ret = makeMutClosure(arg0, arg1, 70, __wbg_adapter_18);
return addHeapObject(ret);
};
if (module instanceof URL || typeof module === 'string' || module instanceof Request) {
const response = fetch(module);
if (typeof WebAssembly.instantiateStreaming === 'function') {
result = WebAssembly.instantiateStreaming(response, imports)
.catch(e => {
console.warn("`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
return response
.then(r => r.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, imports));
});
} else {
result = response
.then(r => r.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, imports));
}
} else {
result = WebAssembly.instantiate(module, imports)
.then(result => {
if (result instanceof WebAssembly.Instance) {
return { instance: result, module };
} else {
return result;
}
});
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
input = fetch(input);
}
return result.then(({instance, module}) => {
wasm = instance.exports;
init.__wbindgen_wasm_module = module;
return wasm;
});
const { instance, module } = await load(await input, imports);
wasm = instance.exports;
init.__wbindgen_wasm_module = module;
return wasm;
}
self.wasm_bindgen = Object.assign(init, __exports);
wasm_bindgen = Object.assign(init, __exports);
})();

Просмотреть файл

@ -19,6 +19,7 @@ importScripts(
/**
* @typedef {import("./@types/perf").SymbolicationWorkerInitialMessage} SymbolicationWorkerInitialMessage
* @typedef {import("./@types/perf").FileHandle} FileHandle
*/
// This worker uses the wasm module that was generated from https://github.com/mstange/profiler-get-symbols.
@ -29,60 +30,55 @@ importScripts(
// itself.
/* eslint camelcase: 0*/
const { WasmMemBuffer, get_compact_symbol_table } = wasm_bindgen;
const { getCompactSymbolTable } = wasm_bindgen;
// Read an open OS.File instance into the Uint8Array dataBuf.
function readFileInto(file, dataBuf) {
// Ideally we'd be able to call file.readTo(dataBuf) here, but readTo no
// longer exists.
// So instead, we copy the file over into wasm memory in 4MB chunks. This
// will take 425 invocations for a a 1.7GB file (such as libxul.so for a
// Firefox for Android build) and not take up too much memory per call.
const dataBufLen = dataBuf.byteLength;
// Read parts of an open OS.File instance into the Uint8Array dataBuf.
// This reads destBuf.byteLength bytes at offset offset.
function readFileBytesInto(file, offset, destBuf) {
file.setPosition(offset);
// We read the file in 4MB chunks. This limits the amount of temporary
// memory we use while we copy the file contents into wasm memory.
const chunkSize = 4 * 1024 * 1024;
let pos = 0;
while (pos < dataBufLen) {
const chunkData = file.read({ bytes: chunkSize });
let posInDestBuf = 0;
let remainingBytes = destBuf.byteLength;
while (remainingBytes > 0) {
const bytes = remainingBytes > chunkSize ? chunkSize : remainingBytes;
const chunkData = file.read({ bytes });
const chunkBytes = chunkData.byteLength;
if (chunkBytes === 0) {
break;
}
dataBuf.set(chunkData, pos);
pos += chunkBytes;
destBuf.set(chunkData, posInDestBuf);
posInDestBuf += chunkBytes;
remainingBytes -= chunkBytes;
}
}
// Returns a plain object that is Structured Cloneable and has name and
// description properties.
// message properties.
function createPlainErrorObject(e) {
// OS.File.Error has an empty message property; it constructs the error
// message on-demand in its toString() method. So we handle those errors
// specially.
if (!(e instanceof OS.File.Error)) {
// Regular errors: just rewrap the object.
if (e instanceof Error) {
const { name, message, fileName, lineNumber } = e;
return { name, message, fileName, lineNumber };
}
// The WebAssembly code throws errors with fields error_type and error_msg.
if (e.error_type) {
return {
name: e.error_type,
message: e.error_msg,
};
}
if (e instanceof OS.File.Error) {
// OS.File.Error has an empty message property; it constructs the error
// message on-demand in its toString() method. So we handle those errors
// specially.
return {
name: "OSFileError",
message: e.toString(),
fileName: e.fileName,
lineNumber: e.lineNumber,
};
}
return {
name: e instanceof OS.File.Error ? "OSFileError" : "Error",
message: e.toString(),
fileName: e.fileName,
lineNumber: e.lineNumber,
};
// Regular errors: just rewrap the object.
const { name, message, fileName, lineNumber } = e;
return { name, message, fileName, lineNumber };
}
class PathHelper {
/**
* A FileAndPathHelper object is passed to getCompactSymbolTable, which calls
* the methods `getCandidatePathsForBinaryOrPdb` and `readFile` on it.
*/
class FileAndPathHelper {
constructor(libInfoMap, objdirs) {
this._libInfoMap = libInfoMap;
this._objdirs = objdirs;
@ -90,12 +86,13 @@ class PathHelper {
/**
* Enumerate all paths at which we could find files with symbol information.
* This method is called by wasm code (via the bindings).
*
* @param {string} debugName
* @param {string} breakpadId
* @returns {Array<{ path: string, debugPath: string }>}
* @returns {Array<string>}
*/
getCandidatePaths(debugName, breakpadId) {
getCandidatePathsForBinaryOrPdb(debugName, breakpadId) {
const key = `${debugName}:${breakpadId}`;
const lib = this._libInfoMap.get(key);
if (!lib) {
@ -121,91 +118,66 @@ class PathHelper {
// a system library.
for (const objdirPath of this._objdirs) {
// Binaries are usually expected to exist at objdir/dist/bin/filename.
candidatePaths.push({
path: OS.Path.join(objdirPath, "dist", "bin", name),
debugPath: OS.Path.join(objdirPath, "dist", "bin", name),
});
candidatePaths.push(OS.Path.join(objdirPath, "dist", "bin", name));
// Also search in the "objdir" directory itself (not just in dist/bin).
// If, for some unforeseen reason, the relevant binary is not inside the
// objdirs dist/bin/ directory, this provides a way out because it lets the
// user specify the actual location.
candidatePaths.push({
path: OS.Path.join(objdirPath, name),
debugPath: OS.Path.join(objdirPath, name),
});
candidatePaths.push(OS.Path.join(objdirPath, name));
}
// Check the absolute paths of the library file(s) last.
// Check the absolute paths of the library last.
// We do this after the objdir search because the library's path may point
// to a stripped binary, which will have fewer symbols than the original
// binaries in the objdir.
candidatePaths.push({ path, debugPath });
if (debugPath !== path) {
// We're on Windows, and debugPath points to a PDB file.
// On non-Windows, path and debugPath are always the same.
// Check the PDB file before the binary because the PDB has the symbol
// information. The binary is only used as a last-ditch fallback
// for things like Windows system libraries (e.g. graphics drivers).
candidatePaths.push(debugPath);
}
// The location of the binary. If the profile was obtained on this machine
// (and not, for example, on an Android device), this file should always
// exist.
candidatePaths.push(path);
return candidatePaths;
}
}
function getCompactSymbolTableFromPath(binaryPath, debugPath, breakpadId) {
// Read the binary file into WASM memory.
const binaryFile = OS.File.open(binaryPath, { read: true });
const binaryData = new WasmMemBuffer(binaryFile.stat().size, array => {
readFileInto(binaryFile, array);
});
binaryFile.close();
// Do the same for the debug file, if it is supplied and different from the
// binary file. This is only the case on Windows.
let debugData = binaryData;
if (debugPath && debugPath !== binaryPath) {
const debugFile = OS.File.open(debugPath, { read: true });
debugData = new WasmMemBuffer(debugFile.stat().size, array => {
readFileInto(debugFile, array);
});
debugFile.close();
}
try {
const output = get_compact_symbol_table(binaryData, debugData, breakpadId);
const result = [
output.take_addr(),
output.take_index(),
output.take_buffer(),
];
output.free();
return result;
} finally {
binaryData.free();
if (debugData != binaryData) {
debugData.free();
/**
* Asynchronously prepare the file at `path` for synchronous reading.
* This method is called by wasm code (via the bindings).
*
* @param {string} path
* @returns {FileHandle}
*/
async readFile(path) {
const file = OS.File.open(path, { read: true });
const info = file.stat();
if (info.isDir) {
throw new Error(`Path "${path}" is a directory.`);
}
const fileSize = info.size;
// Create and return a FileHandle object. The methods of this object are
// called by wasm code (via the bindings).
return {
getLength: () => fileSize,
readBytesInto: (dest, offset) => {
readFileBytesInto(file, offset, dest);
},
drop: () => {
file.close();
},
};
}
}
function getSymbolTableInWorker(debugName, breakpadId, libInfoMap, objdirs) {
const helper = new PathHelper(libInfoMap, objdirs);
const candidatePaths = helper.getCandidatePaths(debugName, breakpadId);
const errors = [];
for (const { path, debugPath } of candidatePaths) {
try {
return getCompactSymbolTableFromPath(path, debugPath, breakpadId);
} catch (e) {
// getCompactSymbolTableFromPath was unsuccessful. So either the
// file wasn't parseable or its contents didn't match the specified
// breakpadId, or some other error occurred.
// Advance to the next candidate path.
errors.push(e);
}
}
throw new Error(
`Could not obtain symbols for the library ${debugName} ${breakpadId} ` +
`because there was no matching file at any of the candidate paths: ${JSON.stringify(
candidatePaths
)}. Errors: ${errors.map(e => e.message).join(", ")}`
);
}
/** @param {MessageEvent<SymbolicationWorkerInitialMessage>} e */
onmessage = async e => {
try {
@ -218,12 +190,8 @@ onmessage = async e => {
// Instantiate the WASM module.
await wasm_bindgen(module);
const result = getSymbolTableInWorker(
debugName,
breakpadId,
libInfoMap,
objdirs
);
const helper = new FileAndPathHelper(libInfoMap, objdirs);
const result = await getCompactSymbolTable(debugName, breakpadId, helper);
postMessage(
{ result },
result.map(r => r.buffer)

Просмотреть файл

@ -45,12 +45,15 @@ const global = this;
// The hash check ensures that the contents of the wasm module are what we
// expect them to be.
// The source code is at https://github.com/mstange/profiler-get-symbols/ .
// Documentation is at https://docs.rs/profiler-get-symbols/ .
// The sha384 sum can be computed with the following command (tested on macOS):
// shasum -b -a 384 profiler_get_symbols_wasm_bg.wasm | awk '{ print $1 }' | xxd -r -p | base64
// Generated from https://github.com/mstange/profiler-get-symbols/commit/90ee39f1d18d2727f07dc57bd93cff6bc73ce8a0
// Generated from https://github.com/mstange/profiler-get-symbols/commit/c1dca28a2a506df40f0a6f32c12ba51ec54b02be
const WASM_MODULE_URL =
"https://zealous-rosalind-a98ce8.netlify.com/wasm/8f7ca2f70e1cd21b5a2dbe96545672752887bfbd4e7b3b9437e9fc7c3da0a3bedae4584ff734f0c9f08c642e6b66ffab.wasm";
"https://storage.googleapis.com/firefox-profiler-get-symbols/c1dca28a2a506df40f0a6f32c12ba51ec54b02be.wasm";
const WASM_MODULE_INTEGRITY =
"sha384-j3yi9w4c0htaLb6WVFZydSiHv71OezuUN+n8fD2go77a5FhP9zTwyfCMZC5rZv+r";
"sha384-ZWi2jwcKJr20rE2gmHjFQGHgsCF9CagkyPLsrIZfmf5QKD2oXgkLa8tMKHK6zPA1";
const EXPIRY_TIME_IN_MS = 5 * 60 * 1000; // 5 minutes