@@ -108,6 +108,7 @@ struct TSWasmStore {
108108 LanguageWasmInstance * current_instance ;
109109 Array (LanguageWasmInstance ) language_instances ;
110110 uint32_t current_memory_offset ;
111+ uint32_t current_memory_size ;
111112 uint32_t current_function_table_offset ;
112113 uint16_t fn_indices [STDLIB_SYMBOL_COUNT ];
113114 wasm_globaltype_t * const_i32_type ;
@@ -172,20 +173,22 @@ typedef struct {
172173static volatile uint32_t NEXT_LANGUAGE_ID ;
173174
174175// Linear memory layout:
175- // [ <-- stack grows down | fixed data | heap grows up --> | per-language static data ]
176+ // [ <-- stack | built-in data | heap --> | static data ]
176177#define STACK_SIZE (64 * 1024)
177178#define HEAP_SIZE (1024 * 1024)
178- #define SERIALIZATION_BUFFER_ADDRESS (STACK_SIZE - TREE_SITTER_SERIALIZATION_BUFFER_SIZE)
179- #define LEXER_ADDRESS (SERIALIZATION_BUFFER_ADDRESS - sizeof(LexerInWasmMemory))
180- #define INITIAL_STACK_POINTER_ADDRESS (LEXER_ADDRESS)
181- #define HEAP_START_ADDRESS (STACK_SIZE)
182- #define DATA_START_ADDRESS (STACK_SIZE + HEAP_SIZE)
179+ #define INITIAL_MEMORY_SIZE (4 * 1024 * 1024 / MEMORY_PAGE_SIZE)
180+ #define MAX_MEMORY_SIZE 32768
181+ #define SERIALIZATION_BUFFER_ADDRESS (STACK_SIZE)
182+ #define LEXER_ADDRESS (SERIALIZATION_BUFFER_ADDRESS + TREE_SITTER_SERIALIZATION_BUFFER_SIZE)
183+ #define HEAP_START_ADDRESS (LEXER_ADDRESS + sizeof(LexerInWasmMemory))
184+ #define DATA_START_ADDRESS (HEAP_START_ADDRESS + HEAP_SIZE)
183185
184186enum FunctionIx {
185187 NULL_IX = 0 ,
186188 PROC_EXIT_IX ,
187189 ABORT_IX ,
188190 ASSERT_FAIL_IX ,
191+ NOTIFY_MEMORY_GROWTH_IX ,
189192 AT_EXIT_IX ,
190193 LEXER_ADVANCE_IX ,
191194 LEXER_MARK_END_IX ,
@@ -280,6 +283,16 @@ static bool wasm_dylink_info__parse(
280283 abort ();
281284}
282285
286+ static wasm_trap_t * callback__notify_memory_growth (
287+ void * env ,
288+ wasmtime_caller_t * caller ,
289+ wasmtime_val_raw_t * args_and_results ,
290+ size_t args_and_results_len
291+ ) {
292+ fprintf (stderr , "wasm module called exit" );
293+ abort ();
294+ }
295+
283296static wasm_trap_t * callback__at_exit (
284297 void * env ,
285298 wasmtime_caller_t * caller ,
@@ -486,7 +499,7 @@ static bool ts_wasm_store__provide_builtin_import(
486499 assert (!error );
487500 * import = (wasmtime_extern_t ) {.kind = WASMTIME_EXTERN_GLOBAL , .of .global = global };
488501 } else if (name_eq (import_name , "__stack_pointer" )) {
489- wasmtime_val_t value = WASM_I32_VAL (INITIAL_STACK_POINTER_ADDRESS );
502+ wasmtime_val_t value = WASM_I32_VAL (STACK_SIZE );
490503 wasmtime_global_t global ;
491504 error = wasmtime_global_new (context , self -> var_i32_type , & value , & global );
492505 assert (!error );
@@ -506,6 +519,8 @@ static bool ts_wasm_store__provide_builtin_import(
506519 * import = get_builtin_func_extern (context , & self -> function_table , ABORT_IX );
507520 } else if (name_eq (import_name , "proc_exit" )) {
508521 * import = get_builtin_func_extern (context , & self -> function_table , PROC_EXIT_IX );
522+ } else if (name_eq (import_name , "emscripten_notify_memory_growth" )) {
523+ * import = get_builtin_func_extern (context , & self -> function_table , NOTIFY_MEMORY_GROWTH_IX );
509524 } else {
510525 return false;
511526 }
@@ -543,7 +558,7 @@ TSWasmStore *ts_wasm_store_new(TSWasmEngine *engine, TSWasmError *wasm_error) {
543558 wasm_exporttype_vec_t export_types = WASM_EMPTY_VEC ;
544559
545560 // Initialize store's memory
546- wasm_limits_t memory_limits = {.min = 256 , .max = 256 };
561+ wasm_limits_t memory_limits = {.min = INITIAL_MEMORY_SIZE , .max = MAX_MEMORY_SIZE };
547562 wasm_memorytype_t * memory_type = wasm_memorytype_new (& memory_limits );
548563 wasmtime_memory_t memory ;
549564 error = wasmtime_memory_new (context , memory_type , & memory );
@@ -578,6 +593,7 @@ TSWasmStore *ts_wasm_store_new(TSWasmEngine *engine, TSWasmError *wasm_error) {
578593 [PROC_EXIT_IX ] = {callback__exit , wasm_functype_new_1_0 (wasm_valtype_new_i32 ())},
579594 [ABORT_IX ] = {callback__exit , wasm_functype_new_0_0 ()},
580595 [ASSERT_FAIL_IX ] = {callback__exit , wasm_functype_new_4_0 (wasm_valtype_new_i32 (), wasm_valtype_new_i32 (), wasm_valtype_new_i32 (), wasm_valtype_new_i32 ())},
596+ [NOTIFY_MEMORY_GROWTH_IX ] = {callback__notify_memory_growth , wasm_functype_new_1_0 (wasm_valtype_new_i32 ())},
581597 [AT_EXIT_IX ] = {callback__at_exit , wasm_functype_new_3_1 (wasm_valtype_new_i32 (), wasm_valtype_new_i32 (), wasm_valtype_new_i32 (), wasm_valtype_new_i32 ())},
582598 [LEXER_ADVANCE_IX ] = {callback__lexer_advance , wasm_functype_new_2_0 (wasm_valtype_new_i32 (), wasm_valtype_new_i32 ())},
583599 [LEXER_MARK_END_IX ] = {callback__lexer_mark_end , wasm_functype_new_1_0 (wasm_valtype_new_i32 ())},
@@ -634,7 +650,8 @@ TSWasmStore *ts_wasm_store_new(TSWasmEngine *engine, TSWasmError *wasm_error) {
634650 .memory = memory ,
635651 .language_instances = array_new (),
636652 .function_table = function_table ,
637- .current_memory_offset = DATA_START_ADDRESS ,
653+ .current_memory_offset = 0 ,
654+ .current_memory_size = 64 * MEMORY_PAGE_SIZE ,
638655 .current_function_table_offset = definitions_len ,
639656 .const_i32_type = wasm_globaltype_new (wasm_valtype_new_i32 (), WASM_CONST ),
640657 .var_i32_type = wasm_globaltype_new (wasm_valtype_new_i32 (), WASM_VAR ),
@@ -703,7 +720,7 @@ TSWasmStore *ts_wasm_store_new(TSWasmEngine *engine, TSWasmError *wasm_error) {
703720 }
704721 wasm_importtype_vec_delete (& import_types );
705722
706- self -> current_memory_offset += dylink_info .memory_size ;
723+ self -> current_memory_offset = DATA_START_ADDRESS + dylink_info .memory_size ;
707724 self -> current_function_table_offset += dylink_info .table_size ;
708725
709726 for (unsigned i = 0 ; i < STDLIB_SYMBOL_COUNT ; i ++ ) {
@@ -794,17 +811,32 @@ static bool ts_wasm_store__instantiate(
794811 wasm_trap_t * trap = NULL ;
795812 wasm_message_t message = WASM_EMPTY_VEC ;
796813 char * language_function_name = NULL ;
814+ wasmtime_context_t * context = wasmtime_store_context (self -> store );
797815
798816 // Grow the function table to make room for the new functions.
799- wasmtime_context_t * context = wasmtime_store_context (self -> store );
800817 wasmtime_val_t initializer = {.kind = WASMTIME_FUNCREF };
801- uint32_t prev_size ;
802- error = wasmtime_table_grow (context , & self -> function_table , dylink_info -> table_size , & initializer , & prev_size );
818+ uint32_t prev_table_size ;
819+ error = wasmtime_table_grow (context , & self -> function_table , dylink_info -> table_size , & initializer , & prev_table_size );
803820 if (error ) {
804821 format (error_message , "invalid function table size %u" , dylink_info -> table_size );
805822 goto error ;
806823 }
807824
825+ // Grow the memory to make room for the new data.
826+ uint32_t needed_memory_size = self -> current_memory_offset + dylink_info -> memory_size ;
827+ if (needed_memory_size > self -> current_memory_size ) {
828+ uint32_t pages_to_grow = (
829+ needed_memory_size - self -> current_memory_size + MEMORY_PAGE_SIZE - 1 ) /
830+ MEMORY_PAGE_SIZE ;
831+ uint64_t prev_memory_size ;
832+ error = wasmtime_memory_grow (context , & self -> memory , pages_to_grow , & prev_memory_size );
833+ if (error ) {
834+ format (error_message , "invalid memory size %u" , dylink_info -> memory_size );
835+ goto error ;
836+ }
837+ self -> current_memory_size += pages_to_grow * MEMORY_PAGE_SIZE ;
838+ }
839+
808840 // Construct the language function name as string.
809841 format (& language_function_name , "tree_sitter_%s" , language_name );
810842
0 commit comments