diff options
author | stephan <stephan@noemail.net> | 2022-12-09 05:47:42 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2022-12-09 05:47:42 +0000 |
commit | 464c80d4c22d03840c35b7e3748183b361257a9f (patch) | |
tree | 24c2ff5681ca5720a8deb405f1c425bc245e964e /ext/wasm/common/whwasmutil.js | |
parent | 75f54dba501a5f5d9709956d67db22b29d6ce802 (diff) | |
download | sqlite-464c80d4c22d03840c35b7e3748183b361257a9f.tar.gz sqlite-464c80d4c22d03840c35b7e3748183b361257a9f.zip |
Export sqlite3_status() and sqlite3_stmt_status() to wasm. Expand the arg/return semantics of wasm.get/setPtrValue() and get/setMemValue() to simplify handling of multiple pointers.
FossilOrigin-Name: e144fd5c88fa4151429a2fef3daf389588402e158267f0afa0dfd142527d76b9
Diffstat (limited to 'ext/wasm/common/whwasmutil.js')
-rw-r--r-- | ext/wasm/common/whwasmutil.js | 109 |
1 files changed, 71 insertions, 38 deletions
diff --git a/ext/wasm/common/whwasmutil.js b/ext/wasm/common/whwasmutil.js index 0da1841b6..3f3281876 100644 --- a/ext/wasm/common/whwasmutil.js +++ b/ext/wasm/common/whwasmutil.js @@ -599,6 +599,11 @@ self.WhWasmUtilInstaller = function(target){ type triggers an exception if this.bigIntEnabled is falsy). Throws if given an invalid type. + If the first argument is an array, it is treated as an array of + addresses and the result is an array of the values from each of + those address, using the same 2nd argument for determining the + value type to fetch. + As a special case, if type ends with a `*`, it is considered to be a pointer type and is treated as the WASM numeric type appropriate for the pointer size (`i32`). @@ -641,23 +646,33 @@ self.WhWasmUtilInstaller = function(target){ See: setMemValue() */ - target.getMemValue = function(ptr, type='i8'){ + target.getMemValue = function f(ptr, type='i8'){ if(type.endsWith('*')) type = ptrIR; const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength) ? cache : heapWrappers(); - switch(type){ - case 'i1': - case 'i8': return c.HEAP8[ptr>>0]; - case 'i16': return c.HEAP16[ptr>>1]; - case 'i32': return c.HEAP32[ptr>>2]; - case 'i64': - if(target.bigIntEnabled) return BigInt(c.HEAP64[ptr>>3]); - break; - case 'float': case 'f32': return c.HEAP32F[ptr>>2]; - case 'double': case 'f64': return Number(c.HEAP64F[ptr>>3]); - default: break; - } - toss('Invalid type for getMemValue():',type); + const list = Array.isArray(ptr) ? [] : undefined; + let rc; + do{ + if(list) ptr = arguments[0].shift(); + switch(type){ + case 'i1': + case 'i8': rc = c.HEAP8[ptr>>0]; break; + case 'i16': rc = c.HEAP16[ptr>>1]; break; + case 'i32': rc = c.HEAP32[ptr>>2]; break; + case 'float': case 'f32': rc = c.HEAP32F[ptr>>2]; break; + case 'double': case 'f64': rc = Number(c.HEAP64F[ptr>>3]); break; + case 'i64': + if(target.bigIntEnabled){ + rc = BigInt(c.HEAP64[ptr>>3]); + break; + } + /* fallthru */ + default: + toss('Invalid type for getMemValue():',type); + } + if(list) list.push(rc); + }while(list && arguments[0].length); + return list || rc; }; /** @@ -668,41 +683,59 @@ self.WhWasmUtilInstaller = function(target){ argument ends with `*` then it is treated as a pointer type and this function behaves as if the 3rd argument were `i32`. - This function returns itself. + If the first argument is an array, it is treated like a list + of pointers and the given value is written to each one. + + Returns `this`. (Prior to 2022-12-09 it returns this function.) ACHTUNG: calling this often, e.g. in a loop, can have a noticably painful impact on performance. Rather than doing so, use - heapForSize() to fetch the heap object and assign directly to it. + heapForSize() to fetch the heap object and assign directly to it + or use the heap's set() method. */ - target.setMemValue = function f(ptr, value, type='i8'){ + target.setMemValue = function(ptr, value, type='i8'){ if (type.endsWith('*')) type = ptrIR; const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength) ? cache : heapWrappers(); - switch (type) { - case 'i1': - case 'i8': c.HEAP8[ptr>>0] = value; return f; - case 'i16': c.HEAP16[ptr>>1] = value; return f; - case 'i32': c.HEAP32[ptr>>2] = value; return f; - case 'i64': - if(c.HEAP64){ - c.HEAP64[ptr>>3] = BigInt(value); - return f; - } - break; - case 'float': case 'f32': c.HEAP32F[ptr>>2] = value; return f; - case 'double': case 'f64': c.HEAP64F[ptr>>3] = value; return f; + for(const p of (Array.isArray(ptr) ? ptr : [ptr])){ + switch (type) { + case 'i1': + case 'i8': c.HEAP8[p>>0] = value; continue; + case 'i16': c.HEAP16[p>>1] = value; continue; + case 'i32': c.HEAP32[p>>2] = value; continue; + case 'float': case 'f32': c.HEAP32F[p>>2] = value; continue; + case 'double': case 'f64': c.HEAP64F[p>>3] = value; continue; + case 'i64': + if(c.HEAP64){ + c.HEAP64[p>>3] = BigInt(value); + continue; + } + /* fallthru */ + default: + toss('Invalid type for setMemValue(): ' + type); + } } - toss('Invalid type for setMemValue(): ' + type); + return this; }; + /** + Convenience form of getMemValue() intended for fetching + pointer-to-pointer values. If passed a single non-array argument + it returns the value of that one pointer address. If passed + multiple arguments, or a single array of arguments, it returns an + array of their values. + */ + target.getPtrValue = function(...ptr){ + return target.getMemValue( (1===ptr.length ? ptr[0] : ptr), ptrIR ); + }; - /** Convenience form of getMemValue() intended for fetching - pointer-to-pointer values. */ - target.getPtrValue = (ptr)=>target.getMemValue(ptr, ptrIR); - - /** Convenience form of setMemValue() intended for setting - pointer-to-pointer values. */ - target.setPtrValue = (ptr, value)=>target.setMemValue(ptr, value, ptrIR); + /** + A variant of setMemValue() intended for setting + pointer-to-pointer values. Its differences from setMemValue() are + that (1) it defaults to a value of 0, (2) it always writes + to the pointer-sized heap view, and (3) it returns `this`. + */ + target.setPtrValue = (ptr, value=0)=>target.setMemValue(ptr, value, ptrIR); /** Returns true if the given value appears to be legal for use as |