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

Minor cleanups and additions in sqlite3.capi.wasm.pstack.

FossilOrigin-Name: 97bd670d3859bd3f2e62c15065b238b85ef614f26479e56a14be42c5784aedf4
This commit is contained in:
stephan
2022-10-04 01:11:10 +00:00
parent 3c272ba380
commit 2b776ee2d6
6 changed files with 159 additions and 138 deletions

View File

@ -560,56 +560,6 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
}; };
}/*sqlite3_prepare_v2/v3()*/; }/*sqlite3_prepare_v2/v3()*/;
if(1){// Extend wasm.pstack, now that the wasm utils are installed
/**
Allocates n chunks, each sz bytes, as a single memory block and
returns the addresses as an array of n element, each holding
the address of one chunk.
Throws a WasmAllocError if allocation fails.
Example:
```
const [p1, p2, p3] = wasm.pstack.allocChunks(3,4);
```
*/
wasm.pstack.allocChunks = (n,sz)=>{
const mem = wasm.pstack.alloc(n * sz);
const rc = [];
let i = 0, offset = 0;
for(; i < n; offset = (sz * ++i)){
rc.push(mem + offset);
}
return rc;
};
/**
A convenience wrapper for allocChunks() which sizes each chunks
as either 8 bytes (safePtrSize is truthy) or wasm.ptrSizeof (if
safePtrSize is falsy).
How it returns its result differs depending on its first
argument: if it's 1, it returns a single pointer value. If it's
more than 1, it returns the same as allocChunks().
When a returned pointers will refer to a 64-bit value, e.g. a
double or int64, and that value must be written or fetched,
e.g. using wasm.setMemValue() or wasm.getMemValue(), it is
important that the pointer in question be aligned to an 8-byte
boundary or else it will not be fetched or written properly and
will corrupt or read neighboring memory.
However, when all pointers involved point to "small" data, it
is safe to pass a falsy value to save to memory.
*/
wasm.pstack.allocPtr = (n=1,safePtrSize=true) =>{
return 1===n
? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptrSizeof)
: wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptrSizeof);
};
}/*wasm.pstack filler*/
{/* Import C-level constants and structs... */ {/* Import C-level constants and structs... */
const cJson = wasm.xCall('sqlite3_wasm_enum_json'); const cJson = wasm.xCall('sqlite3_wasm_enum_json');
if(!cJson){ if(!cJson){

View File

@ -610,12 +610,14 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
}/*wasm*/ }/*wasm*/
}/*capi*/; }/*capi*/;
const wasm = capi.wasm;
/** /**
capi.wasm.alloc()'s srcTypedArray.byteLength bytes, wasm.alloc()'s srcTypedArray.byteLength bytes,
populates them with the values from the source populates them with the values from the source
TypedArray, and returns the pointer to that memory. The TypedArray, and returns the pointer to that memory. The
returned pointer must eventually be passed to returned pointer must eventually be passed to
capi.wasm.dealloc() to clean it up. wasm.dealloc() to clean it up.
As a special case, to avoid further special cases where As a special case, to avoid further special cases where
this is used, if srcTypedArray.byteLength is 0, it this is used, if srcTypedArray.byteLength is 0, it
@ -628,27 +630,27 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
Int8Array types and will throw if srcTypedArray is of Int8Array types and will throw if srcTypedArray is of
any other type. any other type.
*/ */
capi.wasm.allocFromTypedArray = function(srcTypedArray){ wasm.allocFromTypedArray = function(srcTypedArray){
affirmBindableTypedArray(srcTypedArray); affirmBindableTypedArray(srcTypedArray);
const pRet = capi.wasm.alloc(srcTypedArray.byteLength || 1); const pRet = wasm.alloc(srcTypedArray.byteLength || 1);
capi.wasm.heapForSize(srcTypedArray.constructor).set(srcTypedArray.byteLength ? srcTypedArray : [0], pRet); wasm.heapForSize(srcTypedArray.constructor).set(srcTypedArray.byteLength ? srcTypedArray : [0], pRet);
return pRet; return pRet;
}; };
const keyAlloc = config.allocExportName || 'malloc', const keyAlloc = config.allocExportName || 'malloc',
keyDealloc = config.deallocExportName || 'free'; keyDealloc = config.deallocExportName || 'free';
for(const key of [keyAlloc, keyDealloc]){ for(const key of [keyAlloc, keyDealloc]){
const f = capi.wasm.exports[key]; const f = wasm.exports[key];
if(!(f instanceof Function)) toss("Missing required exports[",key,"] function."); if(!(f instanceof Function)) toss("Missing required exports[",key,"] function.");
} }
capi.wasm.alloc = function(n){ wasm.alloc = function(n){
const m = capi.wasm.exports[keyAlloc](n); const m = wasm.exports[keyAlloc](n);
if(!m) throw new WasmAllocError("Failed to allocate "+n+" bytes."); if(!m) throw new WasmAllocError("Failed to allocate "+n+" bytes.");
return m; return m;
}; };
capi.wasm.dealloc = (m)=>capi.wasm.exports[keyDealloc](m); wasm.dealloc = (m)=>wasm.exports[keyDealloc](m);
/** /**
Reports info about compile-time options using Reports info about compile-time options using
@ -679,7 +681,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
"SQLITE_" prefix. When it returns an object of all options, "SQLITE_" prefix. When it returns an object of all options,
the prefix is elided. the prefix is elided.
*/ */
capi.wasm.compileOptionUsed = function f(optName){ wasm.compileOptionUsed = function f(optName){
if(!arguments.length){ if(!arguments.length){
if(f._result) return f._result; if(f._result) return f._result;
else if(!f._opt){ else if(!f._opt){
@ -720,7 +722,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
is an array with 2+ elements: is an array with 2+ elements:
[ "c-side name", [ "c-side name",
"result type" (capi.wasm.xWrap() syntax), "result type" (wasm.xWrap() syntax),
[arg types in xWrap() syntax] [arg types in xWrap() syntax]
// ^^^ this needn't strictly be an array: it can be subsequent // ^^^ this needn't strictly be an array: it can be subsequent
// elements instead: [x,y,z] is equivalent to x,y,z // elements instead: [x,y,z] is equivalent to x,y,z
@ -730,7 +732,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
result/argument type strings gets plugged in at a later phase in result/argument type strings gets plugged in at a later phase in
the API initialization process. the API initialization process.
*/ */
capi.wasm.bindingSignatures = [ wasm.bindingSignatures = [
// Please keep these sorted by function name! // Please keep these sorted by function name!
["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"], ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"],
["sqlite3_bind_blob","int", "sqlite3_stmt*", "int", "*", "int", "*" ["sqlite3_bind_blob","int", "sqlite3_stmt*", "int", "*", "int", "*"
@ -829,13 +831,13 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
["sqlite3_value_type", "int", "sqlite3_value*"], ["sqlite3_value_type", "int", "sqlite3_value*"],
["sqlite3_vfs_find", "*", "string"], ["sqlite3_vfs_find", "*", "string"],
["sqlite3_vfs_register", "int", "*", "int"] ["sqlite3_vfs_register", "int", "*", "int"]
]/*capi.wasm.bindingSignatures*/; ]/*wasm.bindingSignatures*/;
if(false && capi.wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){ if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){
/* ^^^ "the problem" is that this is an option feature and the /* ^^^ "the problem" is that this is an option feature and the
build-time function-export list does not currently take build-time function-export list does not currently take
optional features into account. */ optional features into account. */
capi.wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]); wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]);
} }
/** /**
@ -843,7 +845,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
the others because we need to conditionally bind them or apply the others because we need to conditionally bind them or apply
dummy impls, depending on the capabilities of the environment. dummy impls, depending on the capabilities of the environment.
*/ */
capi.wasm.bindingSignatures.int64 = [ wasm.bindingSignatures.int64 = [
["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]], ["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]],
["sqlite3_changes64","i64", ["sqlite3*"]], ["sqlite3_changes64","i64", ["sqlite3*"]],
["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]], ["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]],
@ -859,18 +861,18 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
/** /**
Functions which are intended solely for API-internal use by the Functions which are intended solely for API-internal use by the
WASM components, not client code. These get installed into WASM components, not client code. These get installed into
capi.wasm. wasm.
TODO: get rid of sqlite3_wasm_vfs_unlink(). It is ill-conceived TODO: get rid of sqlite3_wasm_vfs_unlink(). It is ill-conceived
and only rarely actually useful. and only rarely actually useful.
*/ */
capi.wasm.bindingSignatures.wasm = [ wasm.bindingSignatures.wasm = [
["sqlite3_wasm_vfs_unlink", "int", "string"] ["sqlite3_wasm_vfs_unlink", "int", "string"]
]; ];
/** /**
sqlite3.capi.wasm.pstack (pseudo-stack) holds a special-case sqlite3.wasm.pstack (pseudo-stack) holds a special-case
stack-style allocator intended only for use with _small_ data of stack-style allocator intended only for use with _small_ data of
not more than (in total) a few kb in size, managed as if it were not more than (in total) a few kb in size, managed as if it were
stack-based. stack-based.
@ -900,13 +902,13 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
memory lives in the WASM heap and can be used with routines such memory lives in the WASM heap and can be used with routines such
as wasm.setMemValue() and any wasm.heap8u().slice(). as wasm.setMemValue() and any wasm.heap8u().slice().
*/ */
capi.wasm.pstack = Object.assign(Object.create(null),{ wasm.pstack = Object.assign(Object.create(null),{
/** /**
Sets the current ppstack position to the given pointer. Sets the current ppstack position to the given pointer.
Results are undefined if the passed-in value did not come from Results are undefined if the passed-in value did not come from
this.pointer. this.pointer.
*/ */
restore: capi.wasm.exports.sqlite3_wasm_pstack_restore, restore: wasm.exports.sqlite3_wasm_pstack_restore,
/** /**
Attempts to allocate the given number of bytes from the Attempts to allocate the given number of bytes from the
pstack. On success, it zeroes out a block of memory of the pstack. On success, it zeroes out a block of memory of the
@ -920,31 +922,89 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
heap. heap.
*/ */
alloc: (n)=>{ alloc: (n)=>{
return capi.wasm.exports.sqlite3_wasm_pstack_alloc(n) return wasm.exports.sqlite3_wasm_pstack_alloc(n)
|| WasmAllocError.toss("Could not allocate",n, || WasmAllocError.toss("Could not allocate",n,
"bytes from the pstack."); "bytes from the pstack.");
},
/**
Allocates n chunks, each sz bytes, as a single memory block and
returns the addresses as an array of n element, each holding
the address of one chunk.
Throws a WasmAllocError if allocation fails.
Example:
```
const [p1, p2, p3] = wasm.pstack.allocChunks(3,4);
```
*/
allocChunks: (n,sz)=>{
const mem = wasm.pstack.alloc(n * sz);
const r
= [];
let i = 0, offset = 0;
for(; i < n; offset = (sz * ++i)){
rc.push(mem + offset);
}
return rc;
},
/**
A convenience wrapper for allocChunks() which sizes each chunks
as either 8 bytes (safePtrSize is truthy) or wasm.ptrSizeof (if
safePtrSize is falsy).
How it returns its result differs depending on its first
argument: if it's 1, it returns a single pointer value. If it's
more than 1, it returns the same as allocChunks().
When a returned pointers will refer to a 64-bit value, e.g. a
double or int64, and that value must be written or fetched,
e.g. using wasm.setMemValue() or wasm.getMemValue(), it is
important that the pointer in question be aligned to an 8-byte
boundary or else it will not be fetched or written properly and
will corrupt or read neighboring memory.
However, when all pointers involved point to "small" data, it
is safe to pass a falsy value to save to memory.
*/
allocPtr: (n=1,safePtrSize=true)=>{
return 1===n
? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptrSizeof)
: wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptrSizeof);
} }
// More methods get added after the capi.wasm object is populated })/*wasm.pstack*/;
// by WhWasmUtilInstaller. Object.defineProperties(wasm.pstack, {
}); /**
sqlite3.wasm.pstack.pointer resolves to the current pstack
position pointer. This value is intended _only_ to be passed to
restore().
*/
pointer: {
configurable: false, iterable: true, writeable: false,
get: wasm.exports.sqlite3_wasm_pstack_ptr
//Whether or not a setter as an alternative to restore() is
//clearer or would just lead to confusion is unclear.
//set: wasm.exports.sqlite3_wasm_pstack_restore
},
/**
Resolves to the total number of bytes available in the pstack,
including any space which is currently allocated. This value is
a compile-time constant.
*/
quota: {
configurable: false, iterable: true, writeable: false,
get: wasm.exports.sqlite3_wasm_pstack_quota
}
})/*wasm.pstack properties*/;
/** /**
sqlite3.capi.wasm.pstack.pointer resolves to the current pstack sqlite3.wasm.pstack.remaining resolves to the amount of
position pointer. This value is intended _only_ to be passed to restore().
*/
Object.defineProperty(capi.wasm.pstack, 'pointer', {
configurable: false, iterable: true, writeable: false,
get: capi.wasm.exports.sqlite3_wasm_pstack_ptr
//Whether or not a setter as an alternative to restore() is
//clearer or would just lead to confusion is unclear.
//set: capi.wasm.exports.sqlite3_wasm_pstack_restore
});
/**
sqlite3.capi.wasm.pstack.remaining resolves to the amount of
space remaining in the pstack. space remaining in the pstack.
*/ */
Object.defineProperty(capi.wasm.pstack, 'remaining', { Object.defineProperty(wasm.pstack, 'remaining', {
configurable: false, iterable: true, writeable: false, configurable: false, iterable: true, writeable: false,
get: capi.wasm.exports.sqlite3_wasm_pstack_remaining get: wasm.exports.sqlite3_wasm_pstack_remaining
}); });
/** /**
@ -994,7 +1054,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
return __persistentDir = ""; return __persistentDir = "";
} }
try{ try{
if(pdir && 0===capi.wasm.xCallWrapped( if(pdir && 0===wasm.xCallWrapped(
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
)){ )){
return __persistentDir = pdir; return __persistentDir = pdir;
@ -1024,10 +1084,10 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
}; };
// This bit is highly arguable and is incompatible with the fiddle shell. // This bit is highly arguable and is incompatible with the fiddle shell.
if(false && 0===capi.wasm.exports.sqlite3_vfs_find(0)){ if(false && 0===wasm.exports.sqlite3_vfs_find(0)){
/* Assume that sqlite3_initialize() has not yet been called. /* Assume that sqlite3_initialize() has not yet been called.
This will be the case in an SQLITE_OS_KV build. */ This will be the case in an SQLITE_OS_KV build. */
capi.wasm.exports.sqlite3_initialize(); wasm.exports.sqlite3_initialize();
} }
/** /**
@ -1058,15 +1118,15 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
else if(!pDb){ else if(!pDb){
return capi.sqlite3_vfs_find(0)===pK ? pK : false; return capi.sqlite3_vfs_find(0)===pK ? pK : false;
} }
const ppVfs = capi.wasm.allocPtr(); const ppVfs = wasm.allocPtr();
try{ try{
return ( return (
(0===capi.sqlite3_file_control( (0===capi.sqlite3_file_control(
pDb, dbName, capi.SQLITE_FCNTL_VFS_POINTER, ppVfs pDb, dbName, capi.SQLITE_FCNTL_VFS_POINTER, ppVfs
)) && (capi.wasm.getPtrValue(ppVfs) === pK) )) && (wasm.getPtrValue(ppVfs) === pK)
) ? pK : false; ) ? pK : false;
}finally{ }finally{
capi.wasm.dealloc(ppVfs); wasm.dealloc(ppVfs);
} }
}catch(e){ }catch(e){
/* Ignore - probably bad args to a wasm-bound function. */ /* Ignore - probably bad args to a wasm-bound function. */
@ -1083,7 +1143,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
let pVfs = capi.sqlite3_vfs_find(0); let pVfs = capi.sqlite3_vfs_find(0);
while(pVfs){ while(pVfs){
const oVfs = new capi.sqlite3_vfs(pVfs); const oVfs = new capi.sqlite3_vfs(pVfs);
rc.push(capi.wasm.cstringToJs(oVfs.$zName)); rc.push(wasm.cstringToJs(oVfs.$zName));
pVfs = oVfs.$pNext; pVfs = oVfs.$pNext;
oVfs.dispose(); oVfs.dispose();
} }
@ -1097,7 +1157,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
*/ */
capi.sqlite3_web_db_export = function(pDb){ capi.sqlite3_web_db_export = function(pDb){
if(!pDb) toss('Invalid sqlite3* argument.'); if(!pDb) toss('Invalid sqlite3* argument.');
const wasm = capi.wasm; const wasm = wasm;
if(!wasm.bigIntEnabled) toss('BigInt64 support is not enabled.'); if(!wasm.bigIntEnabled) toss('BigInt64 support is not enabled.');
const stack = wasm.pstack.pointer; const stack = wasm.pstack.pointer;
let pOut; let pOut;
@ -1278,7 +1338,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
Note that the order of insertion into this array is significant for Note that the order of insertion into this array is significant for
some pieces. e.g. sqlite3.capi.wasm cannot be fully utilized until some pieces. e.g. sqlite3.capi.wasm cannot be fully utilized until
the whwasmutil.js part is plugged in. the whwasmutil.js part is plugged in via sqlite3-api-glue.js.
*/ */
self.sqlite3ApiBootstrap.initializers = []; self.sqlite3ApiBootstrap.initializers = [];
/** /**
@ -1290,12 +1350,15 @@ self.sqlite3ApiBootstrap.initializers = [];
Counterpart of self.sqlite3ApiBootstrap.initializers, specifically Counterpart of self.sqlite3ApiBootstrap.initializers, specifically
for initializers which are asynchronous. All functions in this list for initializers which are asynchronous. All functions in this list
take the sqlite3 object as their argument and MUST return a take the sqlite3 object as their argument and MUST return a
Promise. Both the resolved value and rejection cases are ignored. Promise. The resolved value and ignored and rejection will kill the
asyncPostInit() process but will be otherwise ignored because the
post-synchronous-init async initialization parts are (as of this
writing) all optional.
This list is not processed until the client calls This list is not processed until the client calls
sqlite3.asyncPostInit(). This means, for example, that intializers sqlite3.asyncPostInit(). This means, for example, that intializers
added to self.sqlite3ApiBootstrap.initializers may push entries to added to self.sqlite3ApiBootstrap.initializers may push entries to
this list. this list.
*/ */
self.sqlite3ApiBootstrap.initializersAsync = []; self.sqlite3ApiBootstrap.initializersAsync = [];
/** /**

View File

@ -135,13 +135,13 @@ WASM_KEEP void * sqlite3_wasm_stack_begin(void){
extern void __data_end; extern void __data_end;
return &__data_end; return &__data_end;
} }
static void * sq3StackPtr = 0; static void * pWasmStackPtr = 0;
WASM_KEEP void * sqlite3_wasm_stack_ptr(void){ WASM_KEEP void * sqlite3_wasm_stack_ptr(void){
if(!sq3StackPtr) sq3StackPtr = sqlite3_wasm_stack_end(); if(!pWasmStackPtr) pWasmStackPtr = sqlite3_wasm_stack_end();
return sq3StackPtr; return pWasmStackPtr;
} }
WASM_KEEP void sqlite3_wasm_stack_restore(void * p){ WASM_KEEP void sqlite3_wasm_stack_restore(void * p){
sq3StackPtr = p; pWasmStackPtr = p;
} }
WASM_KEEP void * sqlite3_wasm_stack_alloc(int n){ WASM_KEEP void * sqlite3_wasm_stack_alloc(int n){
if(n<=0) return 0; if(n<=0) return 0;
@ -149,7 +149,7 @@ WASM_KEEP void * sqlite3_wasm_stack_alloc(int n){
unsigned char * const p = (unsigned char *)sqlite3_wasm_stack_ptr(); unsigned char * const p = (unsigned char *)sqlite3_wasm_stack_ptr();
unsigned const char * const b = (unsigned const char *)sqlite3_wasm_stack_begin(); unsigned const char * const b = (unsigned const char *)sqlite3_wasm_stack_begin();
if(b + n >= p || b + n < b/*overflow*/) return 0; if(b + n >= p || b + n < b/*overflow*/) return 0;
return sq3StackPtr = p - n; return pWasmStackPtr = p - n;
} }
#endif /* stack allocator experiment */ #endif /* stack allocator experiment */
@ -205,10 +205,9 @@ WASM_KEEP void * sqlite3_wasm_pstack_alloc(int n){
if( n<=0 ) return 0; if( n<=0 ) return 0;
//if( n & 0x7 ) n += 8 - (n & 0x7) /* align to 8-byte boundary */; //if( n & 0x7 ) n += 8 - (n & 0x7) /* align to 8-byte boundary */;
n = (n + 7) & ~7 /* align to 8-byte boundary */; n = (n + 7) & ~7 /* align to 8-byte boundary */;
unsigned char * const p = PStack.pPos; if( PStack.pBegin + n > PStack.pPos /*not enough space left*/
unsigned const char * const b = PStack.pBegin; || PStack.pBegin + n <= PStack.pBegin /*overflow*/ ) return 0;
if( b + n > p || b + n <= b/*overflow*/ ) return 0; memset((PStack.pPos = PStack.pPos - n), 0, (unsigned int)n);
memset((PStack.pPos = p - n), 0, (unsigned int)n);
return PStack.pPos; return PStack.pPos;
} }
/* /*
@ -221,6 +220,14 @@ WASM_KEEP int sqlite3_wasm_pstack_remaining(void){
return (int)(PStack.pPos - PStack.pBegin); return (int)(PStack.pPos - PStack.pBegin);
} }
/*
** Return the total number of bytes available in the pstack, including
** any space which is currently allocated. This value is a
** compile-time constant.
*/
WASM_KEEP int sqlite3_wasm_pstack_quota(void){
return (int)(PStack.pEnd - PStack.pBegin);
}
/* /*
** This function is NOT part of the sqlite3 public API. It is strictly ** This function is NOT part of the sqlite3 public API. It is strictly
@ -254,26 +261,26 @@ int sqlite3_wasm_db_error(sqlite3*db, int err_code, const char *zMsg){
** variadic macros. ** variadic macros.
** **
** Returns a string containing a JSON-format "enum" of C-level ** Returns a string containing a JSON-format "enum" of C-level
** constants intended to be imported into the JS environment. The JSON ** constants and struct-related metadata intended to be imported into
** is initialized the first time this function is called and that ** the JS environment. The JSON is initialized the first time this
** result is reused for all future calls. ** function is called and that result is reused for all future calls.
** **
** If this function returns NULL then it means that the internal ** If this function returns NULL then it means that the internal
** buffer is not large enough for the generated JSON. In debug builds ** buffer is not large enough for the generated JSON and needs to be
** that will trigger an assert(). ** increased. In debug builds that will trigger an assert().
*/ */
WASM_KEEP WASM_KEEP
const char * sqlite3_wasm_enum_json(void){ const char * sqlite3_wasm_enum_json(void){
static char azBuffer[1024 * 12] = {0} /* where the JSON goes */; static char aBuffer[1024 * 12] = {0} /* where the JSON goes */;
int n = 0, nChildren = 0, nStruct = 0 int n = 0, nChildren = 0, nStruct = 0
/* output counters for figuring out where commas go */; /* output counters for figuring out where commas go */;
char * zPos = &azBuffer[1] /* skip first byte for now to help protect char * zPos = &aBuffer[1] /* skip first byte for now to help protect
** against a small race condition */; ** against a small race condition */;
char const * const zEnd = &azBuffer[0] + sizeof(azBuffer) /* one-past-the-end */; char const * const zEnd = &aBuffer[0] + sizeof(aBuffer) /* one-past-the-end */;
if(azBuffer[0]) return azBuffer; if(aBuffer[0]) return aBuffer;
/* Leave azBuffer[0] at 0 until the end to help guard against a tiny /* Leave aBuffer[0] at 0 until the end to help guard against a tiny
** race condition. If this is called twice concurrently, they might ** race condition. If this is called twice concurrently, they might
** end up both writing to azBuffer, but they'll both write the same ** end up both writing to aBuffer, but they'll both write the same
** thing, so that's okay. If we set byte 0 up front then the 2nd ** thing, so that's okay. If we set byte 0 up front then the 2nd
** instance might return and use the string before the 1st instance ** instance might return and use the string before the 1st instance
** is done filling it. */ ** is done filling it. */
@ -680,8 +687,8 @@ const char * sqlite3_wasm_enum_json(void){
out("}"/*top-level object*/); out("}"/*top-level object*/);
*zPos = 0; *zPos = 0;
azBuffer[0] = '{'/*end of the race-condition workaround*/; aBuffer[0] = '{'/*end of the race-condition workaround*/;
return azBuffer; return aBuffer;
#undef StructBinder #undef StructBinder
#undef StructBinder_ #undef StructBinder_
#undef StructBinder__ #undef StructBinder__

View File

@ -1033,9 +1033,10 @@
const stack = P.pointer; const stack = P.pointer;
T.assert(0===stack % 8 /* must be 8-byte aligned */); T.assert(0===stack % 8 /* must be 8-byte aligned */);
try{ try{
const quota = P.remaining; const remaining = P.remaining;
log("pstack quota",quota); log("pstack quota, remaining",P.quota,remaining);
T.assert(quota >= 4096) T.assert(P.quota >= 4096)
.assert(remaining === P.quota)
.mustThrowMatching(()=>P.alloc(0), isAllocErr) .mustThrowMatching(()=>P.alloc(0), isAllocErr)
.mustThrowMatching(()=>P.alloc(-1), isAllocErr); .mustThrowMatching(()=>P.alloc(-1), isAllocErr);
let p1 = P.alloc(12); let p1 = P.alloc(12);
@ -1043,12 +1044,12 @@
.assert(P.pointer === p1); .assert(P.pointer === p1);
let p2 = P.alloc(7); let p2 = P.alloc(7);
T.assert(p2 === p1-8/*8-byte aligned, stack grows downwards*/) T.assert(p2 === p1-8/*8-byte aligned, stack grows downwards*/)
.mustThrowMatching(()=>P.alloc(quota), isAllocErr) .mustThrowMatching(()=>P.alloc(remaining), isAllocErr)
.assert(24 === stack - p2) .assert(24 === stack - p2)
.assert(P.pointer === p2); .assert(P.pointer === p2);
let n = quota - (stack - p2); let n = remaining - (stack - p2);
let p3 = P.alloc(n); let p3 = P.alloc(n);
T.assert(p3 === stack-quota) T.assert(p3 === stack-remaining)
.mustThrowMatching(()=>P.alloc(1), isAllocErr); .mustThrowMatching(()=>P.alloc(1), isAllocErr);
}finally{ }finally{
P.restore(stack); P.restore(stack);

View File

@ -1,5 +1,5 @@
C Add\sa\stest/debug\smechanism\sto\sshut\sdown\sthe\sOPFS\sasync\slistener\sso\sthat\sit\scan\sbe\sinspected\s(it\snormally\scan't\sbe\sbecause\sits\stight\sevent-listening\sloop\sties\sup\sthe\sthread)\sand\sthen\srestarted. C Minor\scleanups\sand\sadditions\sin\ssqlite3.capi.wasm.pstack.
D 2022-10-04T00:54:00.533 D 2022-10-04T01:11:10.003
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -485,13 +485,13 @@ F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba814
F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
F ext/wasm/api/pre-js.js 2db711eb637991b383fc6b5c0f3df65ec48a7201e5730e304beba8de2d3f9b0b F ext/wasm/api/pre-js.js 2db711eb637991b383fc6b5c0f3df65ec48a7201e5730e304beba8de2d3f9b0b
F ext/wasm/api/sqlite3-api-cleanup.js 5d22d1d3818ecacb23bfa223d5970cd0617d8cdbb48c8bc4bbd463f05b021a99 F ext/wasm/api/sqlite3-api-cleanup.js 5d22d1d3818ecacb23bfa223d5970cd0617d8cdbb48c8bc4bbd463f05b021a99
F ext/wasm/api/sqlite3-api-glue.js 24a283a49759914f2433b3118865145efbb2f67f52643e445065e02ccecc081b F ext/wasm/api/sqlite3-api-glue.js a5a1bd620e2e2c26b6e843cf439548b35c5bb5ed21b24b89a412e0b0a8592c42
F ext/wasm/api/sqlite3-api-oo1.js ac1e08d36bdfb5aa0a2d75b7d4c892fd51819d34c932370c3282810672bcc086 F ext/wasm/api/sqlite3-api-oo1.js ac1e08d36bdfb5aa0a2d75b7d4c892fd51819d34c932370c3282810672bcc086
F ext/wasm/api/sqlite3-api-opfs.js d82870cffef9eef6511c650759c3798b59f10c8338587789abd84be2d9d845c3 F ext/wasm/api/sqlite3-api-opfs.js d82870cffef9eef6511c650759c3798b59f10c8338587789abd84be2d9d845c3
F ext/wasm/api/sqlite3-api-prologue.js 61f28bf7a51479c7b401e2da636b2a0710de77d86f68961445d572a3761dd170 F ext/wasm/api/sqlite3-api-prologue.js 8f7e46105f9bea362894725531d6f8aa52981f5ef3f1679dd8caa7c85c135566
F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8 F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 1ed1356752c02a991b2d16c32e3e5c138a03526bb60182f2a751ec5372ecba12 F ext/wasm/api/sqlite3-wasm.c 0c8cb242b80b8de27b74f05ed781f427958e04c9339c4720f30c3a7e78ee6242
F ext/wasm/batch-runner.html cf1a410c92bad50fcec2ddc71390b4e9df63a6ea1bef12a5163a66a0af4d78d9 F ext/wasm/batch-runner.html cf1a410c92bad50fcec2ddc71390b4e9df63a6ea1bef12a5163a66a0af4d78d9
F ext/wasm/batch-runner.js 5bae81684728b6be157d1f92b39824153f0fd019345b39f2ab8930f7ee2a57d8 F ext/wasm/batch-runner.js 5bae81684728b6be157d1f92b39824153f0fd019345b39f2ab8930f7ee2a57d8
F ext/wasm/common/SqliteTestUtil.js 647bf014bd30bdd870a7e9001e251d12fc1c9ec9ce176a1004b838a4b33c5c05 F ext/wasm/common/SqliteTestUtil.js 647bf014bd30bdd870a7e9001e251d12fc1c9ec9ce176a1004b838a4b33c5c05
@ -530,7 +530,7 @@ F ext/wasm/test-opfs-vfs.js 0115d56f3f2a6475040dffe75a6851a353b1690708795944cf0f
F ext/wasm/testing-worker1-promiser.html 6eaec6e04a56cf24cf4fa8ef49d78ce8905dde1354235c9125dca6885f7ce893 F ext/wasm/testing-worker1-promiser.html 6eaec6e04a56cf24cf4fa8ef49d78ce8905dde1354235c9125dca6885f7ce893
F ext/wasm/testing-worker1-promiser.js bd788e33c1807e0a6dda9c9a9d784bd3350ca49c9dd8ae2cc8719b506b6e013e F ext/wasm/testing-worker1-promiser.js bd788e33c1807e0a6dda9c9a9d784bd3350ca49c9dd8ae2cc8719b506b6e013e
F ext/wasm/testing1.html 50575755e43232dbe4c2f97c9086b3118eb91ec2ee1fae931e6d7669fb17fcae F ext/wasm/testing1.html 50575755e43232dbe4c2f97c9086b3118eb91ec2ee1fae931e6d7669fb17fcae
F ext/wasm/testing1.js 0f87073086eff3a152f013874f1c9a710e63d2e069f90dfeb8333ffe82476d04 F ext/wasm/testing1.js 15fc3dca6b2fc22c1458cca2cc2c484281dfc91f01c048ad4e38d5d3924ea961
F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3 F ext/wasm/testing2.html a66951c38137ff1d687df79466351f3c734fa9c6d9cce71d3cf97c291b2167e3
F ext/wasm/testing2.js 88f40ef3cd8201bdadd120a711c36bbf0ce56cc0eab1d5e7debb71fed7822494 F ext/wasm/testing2.js 88f40ef3cd8201bdadd120a711c36bbf0ce56cc0eab1d5e7debb71fed7822494
F ext/wasm/wasmfs.make 3cce1820006196de140f90f2da4b4ea657083fb5bfee7d125be43f7a85748c8f F ext/wasm/wasmfs.make 3cce1820006196de140f90f2da4b4ea657083fb5bfee7d125be43f7a85748c8f
@ -2029,8 +2029,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 72a9e589cc318ec50941739e2edf2c0636284b316c3bf87b71fd363b37619da3 P 7d0bcff4e9b899cd25b393b9f0a02c5dcee2e229f0a0fa01719c7dcd7dcbe7c1
R b598562b6232b1a22591d878d099e519 R 7320921a42fda536d083483db8ee576c
U stephan U stephan
Z 962cbcc757fdf40c47c3a7056efb3d7c Z 3678381f6d3f10154c88d71945cdf539
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
7d0bcff4e9b899cd25b393b9f0a02c5dcee2e229f0a0fa01719c7dcd7dcbe7c1 97bd670d3859bd3f2e62c15065b238b85ef614f26479e56a14be42c5784aedf4