After
86784a68e8c8 (Computed goto) the size of a stack frame
njs_vmcode_interpreter() when -O0 is specified during compilation
increased significantly. This might cause system stack overflow for very
deep recursive calls because system stack is exausted faster than JS
stack.
It is possible now to specify JS stack size for CLI.
char **argv;
njs_uint_t argc;
+ njs_uint_t max_stack_size;
+
njs_log_level_t log_level;
#define NJS_VM_OPT_UNHANDLED_REJECTION_IGNORE 0
spare_size = size + NJS_FRAME_SPARE_SIZE;
spare_size = njs_align_size(spare_size, NJS_FRAME_SPARE_SIZE);
- if (vm->stack_size + spare_size > NJS_MAX_STACK_SIZE) {
+ if (spare_size > vm->spare_stack_size) {
njs_range_error(vm, "Maximum call stack size exceeded");
return NULL;
}
}
chunk_size = spare_size;
- vm->stack_size += spare_size;
+ vm->spare_stack_size -= spare_size;
}
njs_memzero(frame, sizeof(njs_native_frame_t));
/* GC: free frame->local, etc. */
if (native->size != 0) {
- vm->stack_size -= native->size;
+ vm->spare_stack_size += native->size;
njs_mp_free(vm->mem_pool, native);
}
uint8_t opcode_debug;
uint8_t generator_debug;
int exit_code;
+ int stack_size;
char *file;
char *command;
vm_options.ast = opts.ast;
vm_options.unhandled_rejection = opts.unhandled_rejection;
+ if (opts.stack_size != 0) {
+ vm_options.max_stack_size = opts.stack_size;
+ }
+
#ifdef NJS_HAVE_READLINE
if (opts.interactive) {
" -a print AST.\n"
" -c specify the command to execute.\n"
" -d print disassembled code.\n"
- " -e set failure exit code.\n"
+ " -e <code> set failure exit code.\n"
" -f disabled denormals mode.\n"
#ifdef NJS_DEBUG_GENERATOR
" -g enable generator debug.\n"
#endif
+ " -j <size> set the maximum stack size in bytes.\n"
#ifdef NJS_DEBUG_OPCODE
" -o enable opcode debug.\n"
#endif
- " -p set path prefix for modules.\n"
+ " -p <path> set path prefix for modules.\n"
" -q disable interactive introduction prompt.\n"
" -r ignore unhandled promise rejection.\n"
" -s sandbox mode.\n"
opts->generator_debug = 1;
break;
#endif
+ case 'j':
+ if (++i < argc) {
+ opts->stack_size = atoi(argv[i]);
+ break;
+ }
+
+ njs_stderror("option \"-j\" requires argument\n");
+ return NJS_ERROR;
#ifdef NJS_DEBUG_OPCODE
case 'o':
njs_memzero(options, sizeof(njs_vm_opt_t));
options->log_level = NJS_LOG_LEVEL_INFO;
+ options->max_stack_size = NJS_MAX_STACK_SIZE;
}
vm->external = options->external;
+ vm->spare_stack_size = options->max_stack_size;
+
vm->trace.level = NJS_LEVEL_TRACE;
vm->trace.size = 2048;
vm->trace.data = vm;
#define _NJS_VM_H_INCLUDED_
-#define NJS_MAX_STACK_SIZE (256 * 1024)
+#define NJS_MAX_STACK_SIZE (64 * 1024)
typedef struct njs_frame_s njs_frame_t;
njs_mp_t *mem_pool;
u_char *start;
- size_t stack_size;
+ size_t spare_stack_size;
njs_vm_shared_t *shared;
njs_vm_scopes_restore(vm, native, previous);
if (native->size != 0) {
- vm->stack_size -= native->size;
+ vm->spare_stack_size += native->size;
njs_mp_free(vm->mem_pool, native);
}
for (i = 0; i < njs_nitems(tests); i++) {
- memset(&options, 0, sizeof(njs_vm_opt_t));
+ njs_vm_opt_init(&options);
options.init = 1;
vm = njs_vm_create(&options);