aboutsummaryrefslogtreecommitdiff
path: root/ext/wasm/api/sqlite3-wasm.c
diff options
context:
space:
mode:
authorstephan <stephan@noemail.net>2022-10-01 18:47:42 +0000
committerstephan <stephan@noemail.net>2022-10-01 18:47:42 +0000
commit3afad4d432c65aeacd038758d21f523c453c4a67 (patch)
tree6a77fd98c317b695a092db597f82b1a2241e00fe /ext/wasm/api/sqlite3-wasm.c
parent32781427d7496d713f9f81e70021a7e20f7586b1 (diff)
downloadsqlite-3afad4d432c65aeacd038758d21f523c453c4a67.tar.gz
sqlite-3afad4d432c65aeacd038758d21f523c453c4a67.zip
wasm: correct a memleak caused by a shadowed var in the previous checkin. Add a stack-like allocator, sqlite3.capi.wasm.pstack, as a faster way of managing short-lived pointers (like the one which got shadowed).
FossilOrigin-Name: 1fa019c88deac6b6e5155b620bdab1d7145846290daafb9adbefcf4f0fe542cf
Diffstat (limited to 'ext/wasm/api/sqlite3-wasm.c')
-rw-r--r--ext/wasm/api/sqlite3-wasm.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/ext/wasm/api/sqlite3-wasm.c b/ext/wasm/api/sqlite3-wasm.c
index a66b51a8f..4cb8cc264 100644
--- a/ext/wasm/api/sqlite3-wasm.c
+++ b/ext/wasm/api/sqlite3-wasm.c
@@ -56,6 +56,7 @@
# define SQLITE_THREADSAFE 0
#endif
+#include <assert.h>
#include "sqlite3.c" /* yes, .c instead of .h. */
/*
@@ -85,6 +86,110 @@
// See also:
//__attribute__((export_name("theExportedName"), used, visibility("default")))
+
+#if 0
+/*
+** An EXPERIMENT in implementing a stack-based allocator analog to
+** Emscripten's stackSave(), stackAlloc(), stackRestore().
+** Unfortunately, this cannot work together with Emscripten because
+** Emscripten defines its own native one and we'd stomp on each
+** other's memory. Other than that complication, basic tests show it
+** to work just fine.
+**
+** Another option is to malloc() a chunk of our own and call that our
+** "stack".
+*/
+WASM_KEEP void * sqlite3_wasm_stack_end(void){
+ extern void __heap_base
+ /* see https://stackoverflow.com/questions/10038964 */;
+ return &__heap_base;
+}
+WASM_KEEP void * sqlite3_wasm_stack_begin(void){
+ extern void __data_end;
+ return &__data_end;
+}
+static void * sq3StackPtr = 0;
+WASM_KEEP void * sqlite3_wasm_stack_ptr(void){
+ if(!sq3StackPtr) sq3StackPtr = sqlite3_wasm_stack_end();
+ return sq3StackPtr;
+}
+WASM_KEEP void sqlite3_wasm_stack_restore(void * p){
+ sq3StackPtr = p;
+}
+WASM_KEEP void * sqlite3_wasm_stack_alloc(int n){
+ if(n<=0) return 0;
+ n = (n + 7) & ~7 /* align to 8-byte boundary */;
+ unsigned char * const p = (unsigned char *)sqlite3_wasm_stack_ptr();
+ unsigned const char * const b = (unsigned const char *)sqlite3_wasm_stack_begin();
+ if(b + n >= p || b + n < b/*overflow*/) return 0;
+ return sq3StackPtr = p - n;
+}
+#endif /* stack allocator experiment */
+
+/*
+** State for the "pseudo-stack" allocator implemented in
+** sqlite3_wasm_pstack_xyz(). In order to avoid colliding with
+** Emscripten-controled stack space, it carves out a bit of stack
+** memory to use for that purpose. This memory ends up in the
+** WASM-managed memory, such that routines which manipulate the wasm
+** heap can also be used to manipulate this memory.
+*/
+static unsigned char PStack_mem[512 * 8] = {0};
+static struct {
+ unsigned char const * pBegin; /* Start (inclusive) of memory range */
+ unsigned char const * pEnd; /* One-after-the-end of memory range */
+ unsigned char * pPos; /* Current "stack pointer" */
+} PStack = {
+ &PStack_mem[0],
+ &PStack_mem[0] + sizeof(PStack_mem),
+ &PStack_mem[0] + sizeof(PStack_mem)
+};
+/*
+** Returns the current pstack position.
+*/
+WASM_KEEP void * sqlite3_wasm_pstack_ptr(void){
+ return PStack.pPos;
+}
+/*
+** Sets the pstack position poitner to p. Results are undefined if the
+** given value did not come from sqlite3_wasm_pstack_ptr().
+*/
+WASM_KEEP void sqlite3_wasm_pstack_restore(unsigned char * p){
+ assert(p>=PStack.pBegin && p<=PStack.pEnd && p>=PStack.pPos);
+ assert(0==(p & 0x7));
+ if(p>=PStack.pBegin && p<=PStack.pEnd /*&& p>=PStack.pPos*/){
+ PStack.pPos = p;
+ }
+}
+/*
+** Allocate and zero out n bytes from the pstack. Returns a pointer to
+** the memory on success, 0 on error (including a negative n value). n
+** is always adjusted to be a multiple of 8 and returned memory is
+** always zeroed out before returning (because this keeps the client
+** JS code from having to do so, and most uses of the pstack will
+** call for doing so).
+*/
+WASM_KEEP void * sqlite3_wasm_pstack_alloc(int n){
+ if( n<=0 ) return 0;
+ //if( n & 0x7 ) n += 8 - (n & 0x7) /* align to 8-byte boundary */;
+ n = (n + 7) & ~7 /* align to 8-byte boundary */;
+ unsigned char * const p = PStack.pPos;
+ unsigned const char * const b = PStack.pBegin;
+ if( b + n > p || b + n <= b/*overflow*/ ) return 0;
+ memset((PStack.pPos = p - n), 0, (unsigned int)n);
+ return PStack.pPos;
+}
+/*
+** Return the number of bytes left which can be
+** sqlite3_wasm_pstack_alloc()'d.
+*/
+WASM_KEEP int sqlite3_wasm_pstack_remaining(void){
+ assert(PStack.pPos >= PStack.pBegin);
+ assert(PStack.pPos <= PStack.pEnd);
+ return (int)(PStack.pPos - PStack.pBegin);
+}
+
+
/*
** This function is NOT part of the sqlite3 public API. It is strictly
** for use by the sqlite project's own JS/WASM bindings.