1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Replace JS-side use of SQLITE_TRANSIENT with the new SQLITE_WASM_DEALLOC, reducing the amount allocation/copying required by sqlite3_bind_blob/text() and sqlite3_result_blob/text(). Remove the 'experimental' log message from the virtual table tests.

FossilOrigin-Name: ffe2999a91a7dec129a38afb675fe9e539d7c347886bfea85cba55f6367d54d1
This commit is contained in:
stephan
2022-12-24 15:28:45 +00:00
parent cede6384fd
commit 4099b3cab3
7 changed files with 84 additions and 52 deletions

View File

@ -24,6 +24,33 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
self.WhWasmUtilInstaller(wasm);
delete self.WhWasmUtilInstaller;
{
/**
Find a mapping for SQLITE_WASM_DEALLOC, which the API
guarantees is a WASM pointer to the same underlying function as
wasm.dealloc() (noting that wasm.dealloc() is permitted to be a
JS wrapper around the WASM function). There is unfortunately no
O(1) algorithm for finding this pointer: we have to walk the
WASM indirect function table to find it. However, experience
indicates that that particular function is always very close to
the front of the table (it's been entry #3 in all relevant
tests).
*/
const dealloc = wasm.exports[sqlite3.config.deallocExportName];
const nFunc = wasm.functionTable().length;
let i;
for(i = 0; i < nFunc; ++i){
const e = wasm.functionEntry(i);
if(dealloc === e){
capi.SQLITE_WASM_DEALLOC = i;
break;
}
}
if(dealloc !== wasm.functionEntry(capi.SQLITE_WASM_DEALLOC)){
toss("Internal error: cannot find function pointer for SQLITE_WASM_DEALLOC.");
}
}
/**
Signatures for the WASM-exported C-side functions. Each entry
is an array with 2+ elements:
@ -874,7 +901,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
text = pMem.join('');
}
let p, n;
try {
try{
if(util.isSQLableTypedArray(text)){
p = wasm.allocFromTypedArray(text);
n = text.byteLength;
@ -886,9 +913,12 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
"Invalid 3rd argument type for sqlite3_bind_text()."
);
}
return __bindText(pStmt, iCol, p, n, capi.SQLITE_TRANSIENT);
}finally{
return __bindText(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
}catch(e){
wasm.dealloc(p);
return util.sqlite3_wasm_db_error(
capi.sqlite3_db_handle(pStmt), e
);
}
}/*sqlite3_bind_text()*/;
@ -917,9 +947,12 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
"Invalid 3rd argument type for sqlite3_bind_blob()."
);
}
return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_TRANSIENT);
}finally{
return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC);
}catch(e){
wasm.dealloc(p);
return util.sqlite3_wasm_db_error(
capi.sqlite3_db_handle(pStmt), e
);
}
}/*sqlite3_bind_blob()*/;

View File

@ -1285,7 +1285,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
success.
*/
const bindOne = function f(stmt,ndx,bindType,val){
affirmUnlocked(stmt, 'bind()');
affirmUnlocked(affirmStmtOpen(stmt), 'bind()');
if(!f._){
f._tooBigInt = (v)=>toss3(
"BigInt value is too big to store without precision loss:", v
@ -1295,14 +1295,9 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
so we have no range checking. */
f._ = {
string: function(stmt, ndx, val, asBlob){
const stack = wasm.scopedAllocPush();
try{
const [pStr, n] = wasm.scopedAllocCString(val, true);
const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text;
return f(stmt.pointer, ndx, pStr, n, capi.SQLITE_TRANSIENT);
}finally{
wasm.scopedAllocPop(stack);
}
const [pStr, n] = wasm.allocCString(val, true);
const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text;
return f(stmt.pointer, ndx, pStr, n, capi.SQLITE_WASM_DEALLOC);
}
};
}/* static init */
@ -1354,15 +1349,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
toss3("Binding a value as a blob requires",
"that it be a string, Uint8Array, Int8Array, or ArrayBuffer.");
}
const stack = wasm.scopedAllocPush();
try{
const pBlob = wasm.scopedAlloc(val.byteLength || 1);
wasm.heap8().set(val.byteLength ? val : [0], pBlob)
rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
capi.SQLITE_TRANSIENT);
}finally{
wasm.scopedAllocPop(stack);
}
const pBlob = wasm.alloc(val.byteLength || 1);
wasm.heap8().set(val.byteLength ? val : [0], pBlob)
rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength,
capi.SQLITE_WASM_DEALLOC);
break;
}
default:

View File

@ -321,14 +321,17 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
};
/**
Returns true if v appears to be one of our bind()-able TypedArray
types: Uint8Array or Int8Array. Support for TypedArrays with
element sizes >1 is a potential TODO just waiting on a use case
to justify them.
Returns v if v appears to be one of our bind()-able TypedArray
types: Uint8Array or Int8Array or ArrayBuffer. Support for
TypedArrays with element sizes >1 is a potential TODO just
waiting on a use case to justify them. Until then, their `buffer`
property can be used to pass them as an ArrayBuffer. If it's not
a bindable array type, a falsy value is returned.
*/
const isBindableTypedArray = (v)=>{
return v && (v instanceof Uint8Array || v instanceof Int8Array);
//v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
return v && (v instanceof Uint8Array
|| v instanceof Int8Array
|| v instanceof ArrayBuffer);
};
/**
@ -341,8 +344,9 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
isSQLableTypedArray() list.
*/
const isSQLableTypedArray = (v)=>{
return v && (v instanceof Uint8Array || v instanceof Int8Array);
//v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
return v && (v instanceof Uint8Array
|| v instanceof Int8Array
|| v instanceof ArrayBuffer);
};
/** Returns true if isBindableTypedArray(v) does, else throws with a message
@ -439,8 +443,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
- If it's an ArrayBuffer, it gets wrapped in a Uint8Array and
treated as that type.
In all of those cases, the final argument (text destructor) is
ignored and capi.SQLITE_TRANSIENT is assumed.
In all of those cases, the final argument (destructor) is
ignored and capi.SQLITE_WASM_DEALLOC is assumed.
A 3rd argument of `null` is treated as if it were a WASM pointer
of 0.
@ -477,7 +481,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
treated as that type.
In each of those cases, the final argument (text destructor) is
ignored and capi.SQLITE_TRANSIENT is assumed.
ignored and capi.SQLITE_WASM_DEALLOC is assumed.
A 3rd argument of `null` is treated as if it were a WASM pointer
of 0.
@ -1661,7 +1665,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
- `bigint`: similar to `number` but will trigger an error if the
value is too big to store in an int64.
- `string`: `sqlite3_result_text()`
- Uint8Array or Int8Array: `sqlite3_result_blob()`
- Uint8Array or Int8Array or ArrayBuffer: `sqlite3_result_blob()`
- `undefined`: is a no-op provided to simplify certain use cases.
Anything else triggers `sqlite3_result_error()` with a
@ -1712,9 +1716,11 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
f(pCtx, val);
break;
}
case 'string':
capi.sqlite3_result_text(pCtx, val, -1, capi.SQLITE_TRANSIENT);
case 'string': {
const [p, n] = wasm.allocCString(val,true);
capi.sqlite3_result_text(pCtx, p, n, capi.SQLITE_WASM_DEALLOC);
break;
}
case 'object':
if(null===val/*yes, typeof null === 'object'*/) {
capi.sqlite3_result_null(pCtx);
@ -1723,7 +1729,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
const pBlob = wasm.allocFromTypedArray(val);
capi.sqlite3_result_blob(
pCtx, pBlob, val.byteLength,
wasm.exports[sqlite3.config.deallocExportName]
capi.SQLITE_WASM_DEALLOC
);
break;
}

View File

@ -1621,6 +1621,11 @@ int sqlite3_wasm_test_intptr(int * p){
return *p = *p * 2;
}
SQLITE_WASM_KEEP
void * sqlite3_wasm_test_voidptr(void * p){
return p;
}
SQLITE_WASM_KEEP
int64_t sqlite3_wasm_test_int64_max(void){
return (int64_t)0x7fffffffffffffff;

View File

@ -1987,7 +1987,6 @@ self.sqlite3InitModule = sqlite3InitModule;
name: 'virtual table #1: eponymous w/ manual exception handling',
predicate: ()=>!!capi.sqlite3_index_info,
test: function(sqlite3){
warn("The vtab/module JS bindings are experimental and subject to change.");
const VT = sqlite3.vtab;
const tmplCols = Object.assign(Object.create(null),{
A: 0, B: 1
@ -2185,7 +2184,6 @@ self.sqlite3InitModule = sqlite3InitModule;
name: 'virtual table #2: non-eponymous w/ automated exception wrapping',
predicate: ()=>!!capi.sqlite3_index_info,
test: function(sqlite3){
warn("The vtab/module JS bindings are experimental and subject to change.");
const VT = sqlite3.vtab;
const tmplCols = Object.assign(Object.create(null),{
A: 0, B: 1

View File

@ -1,5 +1,5 @@
C Extend\soo1.Stmt.bind()\sto\saccept\sArrayBuffer\sinstances\sto\sbind\sas\sblobs.
D 2022-12-24T14:16:02.217
C Replace\sJS-side\suse\sof\sSQLITE_TRANSIENT\swith\sthe\snew\sSQLITE_WASM_DEALLOC,\sreducing\sthe\samount\sallocation/copying\srequired\sby\ssqlite3_bind_blob/text()\sand\ssqlite3_result_blob/text().\sRemove\sthe\s'experimental'\slog\smessage\sfrom\sthe\svirtual\stable\stests.
D 2022-12-24T15:28:45.647
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -503,16 +503,16 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
F ext/wasm/api/sqlite3-api-glue.js f0651048a2601bf79f7f39c2c855f6417e65548417f5019ac9ac2ffb2463f2b9
F ext/wasm/api/sqlite3-api-oo1.js 1312eaf2776c957e41a6fd63c31e7487502bf71745805c41f72429e0925802a5
F ext/wasm/api/sqlite3-api-prologue.js 683956ea6ab5e0132db48bb693a6bb9dd92f36c8c0902af36572e9b29006ac6d
F ext/wasm/api/sqlite3-api-glue.js ba532798e577497da9221bf9ac7d286619eec4d16736c927f1d10f3c8d21ada3
F ext/wasm/api/sqlite3-api-oo1.js 5393fb0b325d2fdafada7fdbfb9219af9a865631acb351d5c5196a982b632c8b
F ext/wasm/api/sqlite3-api-prologue.js b0302c61abf21966c8cf9788453fea29c790633f7a14a92e05e6db994b590d11
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
F ext/wasm/api/sqlite3-v-helper.js 6f6c3e390a72e08b0a5b16a0d567d7af3c04d172831853a29d72a6f1dd40ff24
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 66daf6fb6843bea615fe193109e1542efbeca24f560ee9da63375a910bb48115
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c b114bb85cdf8be7b2939ddcc2bbc2f30c190c44b993c34a77b017c978345efb1
F ext/wasm/api/sqlite3-wasm.c 313489816e1733a10ece74a92cbea65d3ee241eb07d98088e96258cc211c9719
F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
F ext/wasm/api/sqlite3-worker1.js 1e54ea3d540161bcfb2100368a2fc0cad871a207b8336afee1c445715851ec54
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
F ext/wasm/tester1.c-pp.js 145c493221727eb40194280bb2852da49f857e850d8394c31b7bd4caeb5d7bed
F ext/wasm/tester1.c-pp.js dec750b65ec33ff267b35370ab746899859beb0a7c695cb9b087663d5b144512
F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@ -2067,8 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 6a37874db04f3b4842994ad17fc74cb6222f8ea0fa1315a23aff1ffa69bcd12a
R b07f6a4d9e30a3f649f5decc82bdf7ef
P f76bd30137fbff981625ffcb28cddd5e8651803dfc3f2d8d7801ead33496311d
R 244f04d134cc6151e3968d82d6c44161
U stephan
Z 934cef85bd1b053ac09da3261d128afb
Z 5d490510463cd36c1f126d30ea32761d
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
f76bd30137fbff981625ffcb28cddd5e8651803dfc3f2d8d7801ead33496311d
ffe2999a91a7dec129a38afb675fe9e539d7c347886bfea85cba55f6367d54d1