} njs_code_name_t;
+static void njs_disassemble(njs_vm_code_t *code);
+
+
static njs_code_name_t code_names[] = {
{ NJS_VMCODE_OBJECT, sizeof(njs_vmcode_object_t),
njs_vm_code_t *code;
code = vm->codes->start;
- n = vm->codes->items;
+ code += vm->main_index;
+ n = vm->codes->items - vm->main_index;
while (n != 0) {
njs_printf("%V:%V\n", &code->file, &code->name);
- njs_disassemble(code->start, code->end);
+ njs_disassemble(code);
code++;
n--;
}
}
-void
-njs_disassemble(u_char *start, u_char *end)
+static void
+njs_disassemble(njs_vm_code_t *code)
{
- u_char *p;
+ u_char *p, *start, *end;
+ uint32_t line;
njs_str_t *name;
njs_uint_t n;
njs_code_name_t *code_name;
njs_vmcode_try_trampoline_t *try_tramp;
njs_vmcode_function_frame_t *function;
- p = start;
+ start = code->start;
+ end = code->end;
/*
* On some 32-bit platform uintptr_t is int and compilers warn
* there is no run-time overhead.
*/
+ p = start;
+
while (p < end) {
operation = *(njs_vmcode_operation_t *) p;
+ line = njs_lookup_line(code, p - start);
if (operation == NJS_VMCODE_ARRAY) {
array = (njs_vmcode_array_t *) p;
- njs_printf("%05uz ARRAY %04Xz %uz%s\n",
- p - start, (size_t) array->retval,
+ njs_printf("%5uD | %05uz ARRAY %04Xz %uz%s\n",
+ line, p - start, (size_t) array->retval,
(size_t) array->length, array->ctor ? " INIT" : "");
p += sizeof(njs_vmcode_array_t);
if (operation == NJS_VMCODE_IF_TRUE_JUMP) {
cond_jump = (njs_vmcode_cond_jump_t *) p;
- njs_printf("%05uz JUMP IF TRUE %04Xz %z\n",
- p - start, (size_t) cond_jump->cond,
+ njs_printf("%5uD | %05uz JUMP IF TRUE %04Xz %z\n",
+ line, p - start, (size_t) cond_jump->cond,
(size_t) cond_jump->offset);
p += sizeof(njs_vmcode_cond_jump_t);
if (operation == NJS_VMCODE_IF_FALSE_JUMP) {
cond_jump = (njs_vmcode_cond_jump_t *) p;
- njs_printf("%05uz JUMP IF FALSE %04Xz %z\n",
- p - start, (size_t) cond_jump->cond,
+ njs_printf("%5uD | %05uz JUMP IF FALSE %04Xz %z\n",
+ line, p - start, (size_t) cond_jump->cond,
(size_t) cond_jump->offset);
p += sizeof(njs_vmcode_cond_jump_t);
if (operation == NJS_VMCODE_JUMP) {
jump = (njs_vmcode_jump_t *) p;
- njs_printf("%05uz JUMP %z\n",
- p - start, (size_t) jump->offset);
+ njs_printf("%5uD | %05uz JUMP %z\n",
+ line, p - start, (size_t) jump->offset);
p += sizeof(njs_vmcode_jump_t);
if (operation == NJS_VMCODE_IF_EQUAL_JUMP) {
equal = (njs_vmcode_equal_jump_t *) p;
- njs_printf("%05uz JUMP IF EQUAL %04Xz %04Xz %z\n",
- p - start, (size_t) equal->value1,
+ njs_printf("%5uD | %05uz JUMP IF EQUAL %04Xz %04Xz %z\n",
+ line, p - start, (size_t) equal->value1,
(size_t) equal->value2, (size_t) equal->offset);
p += sizeof(njs_vmcode_equal_jump_t);
if (operation == NJS_VMCODE_TEST_IF_TRUE) {
test_jump = (njs_vmcode_test_jump_t *) p;
- njs_printf("%05uz TEST IF TRUE %04Xz %04Xz %z\n",
- p - start, (size_t) test_jump->retval,
+ njs_printf("%5uD | %05uz TEST IF TRUE %04Xz %04Xz %z\n",
+ line, p - start, (size_t) test_jump->retval,
(size_t) test_jump->value, (size_t) test_jump->offset);
p += sizeof(njs_vmcode_test_jump_t);
if (operation == NJS_VMCODE_TEST_IF_FALSE) {
test_jump = (njs_vmcode_test_jump_t *) p;
- njs_printf("%05uz TEST IF FALSE %04Xz %04Xz %z\n",
- p - start, (size_t) test_jump->retval,
+ njs_printf("%5uD | %05uz TEST IF FALSE %04Xz %04Xz %z\n",
+ line, p - start, (size_t) test_jump->retval,
(size_t) test_jump->value, (size_t) test_jump->offset);
p += sizeof(njs_vmcode_test_jump_t);
if (operation == NJS_VMCODE_COALESCE) {
test_jump = (njs_vmcode_test_jump_t *) p;
- njs_printf("%05uz COALESCE %04Xz %04Xz %z\n",
- p - start, (size_t) test_jump->retval,
+ njs_printf("%5uD | %05uz COALESCE %04Xz %04Xz %z\n",
+ line, p - start, (size_t) test_jump->retval,
(size_t) test_jump->value, (size_t) test_jump->offset);
p += sizeof(njs_vmcode_test_jump_t);
if (operation == NJS_VMCODE_FUNCTION_FRAME) {
function = (njs_vmcode_function_frame_t *) p;
- njs_printf("%05uz FUNCTION FRAME %04Xz %uz%s\n",
- p - start, (size_t) function->name, function->nargs,
- function->ctor ? " CTOR" : "");
+ njs_printf("%5uD | %05uz FUNCTION FRAME %04Xz %uz%s\n",
+ line, p - start, (size_t) function->name,
+ function->nargs, function->ctor ? " CTOR" : "");
p += sizeof(njs_vmcode_function_frame_t);
if (operation == NJS_VMCODE_METHOD_FRAME) {
method = (njs_vmcode_method_frame_t *) p;
- njs_printf("%05uz METHOD FRAME %04Xz %04Xz %uz%s\n",
- p - start, (size_t) method->object,
+ njs_printf("%5uD | %05uz METHOD FRAME %04Xz %04Xz %uz%s\n",
+ line, p - start, (size_t) method->object,
(size_t) method->method, method->nargs,
method->ctor ? " CTOR" : "");
if (operation == NJS_VMCODE_PROPERTY_FOREACH) {
prop_foreach = (njs_vmcode_prop_foreach_t *) p;
- njs_printf("%05uz PROP FOREACH %04Xz %04Xz %z\n",
- p - start, (size_t) prop_foreach->next,
+ njs_printf("%5uD | %05uz PROP FOREACH %04Xz %04Xz %z\n",
+ line, p - start, (size_t) prop_foreach->next,
(size_t) prop_foreach->object,
(size_t) prop_foreach->offset);
if (operation == NJS_VMCODE_PROPERTY_NEXT) {
prop_next = (njs_vmcode_prop_next_t *) p;
- njs_printf("%05uz PROP NEXT %04Xz %04Xz %04Xz %z\n",
- p - start, (size_t) prop_next->retval,
+ njs_printf("%5uD | %05uz PROP NEXT %04Xz %04Xz %04Xz %z\n",
+ line, p - start, (size_t) prop_next->retval,
(size_t) prop_next->object, (size_t) prop_next->next,
(size_t) prop_next->offset);
if (operation == NJS_VMCODE_PROPERTY_ACCESSOR) {
prop_accessor = (njs_vmcode_prop_accessor_t *) p;
- njs_printf("%05uz PROP %s ACCESSOR %04Xz %04Xz %04Xz\n",
- p - start,
+ njs_printf("%5uD | %05uz PROP %s ACCESSOR %04Xz %04Xz %04Xz\n",
+ line, p - start,
(prop_accessor->type == NJS_OBJECT_PROP_GETTER)
? "GET" : "SET",
(size_t) prop_accessor->value,
if (operation == NJS_VMCODE_TRY_START) {
try_start = (njs_vmcode_try_start_t *) p;
- njs_printf("%05uz TRY START %04Xz %04Xz %z\n",
- p - start, (size_t) try_start->exception_value,
+ njs_printf("%5uD | %05uz TRY START %04Xz %04Xz %z\n",
+ line, p - start, (size_t) try_start->exception_value,
(size_t) try_start->exit_value,
(size_t) try_start->offset);
if (operation == NJS_VMCODE_TRY_BREAK) {
try_tramp = (njs_vmcode_try_trampoline_t *) p;
- njs_printf("%05uz TRY BREAK %04Xz %z\n",
- p - start, (size_t) try_tramp->exit_value,
+ njs_printf("%5uD | %05uz TRY BREAK %04Xz %z\n",
+ line, p - start, (size_t) try_tramp->exit_value,
(size_t) try_tramp->offset);
p += sizeof(njs_vmcode_try_trampoline_t);
if (operation == NJS_VMCODE_TRY_CONTINUE) {
try_tramp = (njs_vmcode_try_trampoline_t *) p;
- njs_printf("%05uz TRY CONTINUE %04Xz %z\n",
- p - start, (size_t) try_tramp->exit_value,
+ njs_printf("%5uD | %05uz TRY CONTINUE %04Xz %z\n",
+ line, p - start, (size_t) try_tramp->exit_value,
(size_t) try_tramp->offset);
p += sizeof(njs_vmcode_try_trampoline_t);
if (operation == NJS_VMCODE_TRY_RETURN) {
try_return = (njs_vmcode_try_return_t *) p;
- njs_printf("%05uz TRY RETURN %04Xz %04Xz %z\n",
- p - start, (size_t) try_return->save,
+ njs_printf("%5uD | %05uz TRY RETURN %04Xz %04Xz %z\n",
+ line, p - start, (size_t) try_return->save,
(size_t) try_return->retval,
(size_t) try_return->offset);
if (operation == NJS_VMCODE_CATCH) {
catch = (njs_vmcode_catch_t *) p;
- njs_printf("%05uz CATCH %04Xz %z\n",
- p - start, (size_t) catch->exception,
+ njs_printf("%5uD | %05uz CATCH %04Xz %z\n",
+ line, p - start, (size_t) catch->exception,
(size_t) catch->offset);
p += sizeof(njs_vmcode_catch_t);
if (operation == NJS_VMCODE_TRY_END) {
try_end = (njs_vmcode_try_end_t *) p;
- njs_printf("%05uz TRY END %z\n",
- p - start, (size_t) try_end->offset);
+ njs_printf("%5uD | %05uz TRY END %z\n",
+ line, p - start, (size_t) try_end->offset);
p += sizeof(njs_vmcode_try_end_t);
if (operation == NJS_VMCODE_FINALLY) {
finally = (njs_vmcode_finally_t *) p;
- njs_printf("%05uz TRY FINALLY %04Xz %04Xz %z %z\n",
- p - start, (size_t) finally->retval,
+ njs_printf("%5uD | %05uz TRY FINALLY %04Xz %04Xz %z %z\n",
+ line, p - start, (size_t) finally->retval,
(size_t) finally->exit_value,
(size_t) finally->continue_offset,
(size_t) finally->break_offset);
}
if (operation == NJS_VMCODE_REFERENCE_ERROR) {
- njs_printf("%05uz REFERENCE ERROR\n", p - start);
+ njs_printf("%5uD | %05uz REFERENCE ERROR\n", line, p - start);
p += sizeof(njs_vmcode_reference_error_t);
if (code_name->size == sizeof(njs_vmcode_3addr_t)) {
code3 = (njs_vmcode_3addr_t *) p;
- njs_printf("%05uz %*s %04Xz %04Xz %04Xz\n",
- p - start, name->length, name->start,
+ njs_printf("%5uD | %05uz %*s %04Xz %04Xz %04Xz\n",
+ line, p - start, name->length, name->start,
(size_t) code3->dst, (size_t) code3->src1,
(size_t) code3->src2);
} else if (code_name->size == sizeof(njs_vmcode_2addr_t)) {
code2 = (njs_vmcode_2addr_t *) p;
- njs_printf("%05uz %*s %04Xz %04Xz\n",
- p - start, name->length, name->start,
+ njs_printf("%5uD | %05uz %*s %04Xz %04Xz\n",
+ line, p - start, name->length, name->start,
(size_t) code2->dst, (size_t) code2->src);
} else if (code_name->size == sizeof(njs_vmcode_1addr_t)) {
code1 = (njs_vmcode_1addr_t *) p;
- njs_printf("%05uz %*s %04Xz\n",
- p - start, name->length, name->start,
+ njs_printf("%5uD | %05uz %*s %04Xz\n",
+ line, p - start, name->length, name->start,
(size_t) code1->index);
}
} while (n != 0);
- njs_printf("%05uz UNKNOWN %04Xz\n",
+ njs_printf("%5uD | %05uz UNKNOWN %04Xz\n", line,
p - start, (size_t) (uintptr_t) operation);
p += sizeof(njs_vmcode_operation_t);
njs_parser_node_t *node);
static u_char *njs_generate_reserve(njs_vm_t *vm, njs_generator_t *generator,
size_t size);
+static njs_int_t njs_generate_code_map(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node, u_char *code);
static njs_int_t njs_generate_name(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node);
static njs_int_t njs_generate_variable(njs_vm_t *vm, njs_generator_t *generator,
static njs_int_t njs_generate_reference_error(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
-static njs_int_t njs_generate_function_debug(njs_vm_t *vm,
- const njs_str_t *name, njs_function_lambda_t *lambda,
- njs_parser_node_t *node);
-
-#define njs_generate_code(generator, type, _code, _op, nargs) \
+#define njs_generate_code(generator, type, _code, _op, nargs, nd) \
do { \
_code = (type *) njs_generate_reserve(vm, generator, sizeof(type)); \
if (njs_slow_path(_code == NULL)) { \
return NJS_ERROR; \
} \
\
+ if (njs_generate_code_map(vm, generator, nd, (u_char *) _code) \
+ != NJS_OK) \
+ { \
+ return NJS_ERROR; \
+ } \
+ \
generator->code_end += sizeof(type); \
\
_code->code.operation = _op; \
#define njs_generate_code_jump(generator, _code, _offset) \
do { \
njs_generate_code(generator, njs_vmcode_jump_t, _code, \
- NJS_VMCODE_JUMP, 0); \
+ NJS_VMCODE_JUMP, 0, NULL); \
_code->offset = _offset; \
} while (0)
-#define njs_generate_code_move(generator, _code, _dst, _src) \
+#define njs_generate_code_move(generator, _code, _dst, _src, node) \
do { \
njs_generate_code(generator, njs_vmcode_move_t, _code, \
- NJS_VMCODE_MOVE, 2); \
+ NJS_VMCODE_MOVE, 2, node); \
_code->dst = _dst; \
_code->src = _src; \
} while (0)
}
+static njs_int_t
+njs_generate_code_map(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node, u_char *code)
+{
+ njs_arr_t *map;
+ njs_vm_line_num_t *last;
+
+ map = generator->lines;
+
+ if (map != NULL && node != NULL) {
+ last = (map->items != 0) ? njs_arr_last(map) : NULL;
+ if (last == NULL || (node->token_line != last->line)) {
+ last = njs_arr_add(map);
+ if (njs_slow_path(last == NULL)) {
+ return NJS_ERROR;
+ }
+
+ last->line = node->token_line;
+ last->offset = njs_code_offset(generator, code);
+ }
+ }
+
+ return NJS_OK;
+}
+
+
+uint32_t
+njs_lookup_line(njs_vm_code_t *code, uint32_t offset)
+{
+ njs_uint_t n;
+ njs_vm_line_num_t *map;
+
+ n = (code->lines != NULL) ? code->lines->items : 0;
+ map = (njs_vm_line_num_t *) code->lines->start;
+
+ while (n != 0) {
+ if (offset >= map->offset && (n == 1 || offset < map[1].offset)) {
+ return map->line;
+ }
+
+ map++;
+ n--;
+ }
+
+ return 0;
+}
+
+
static njs_int_t
njs_generate_name(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
}
njs_generate_code(generator, njs_vmcode_object_copy_t, copy,
- NJS_VMCODE_OBJECT_COPY, 2);
+ NJS_VMCODE_OBJECT_COPY, 2, node);
copy->retval = node->index;
copy->object = var->index;
* empty object or expression result is stored directly in variable.
*/
if (lvalue->index != expr->index) {
- njs_generate_code_move(generator, move, lvalue->index, expr->index);
+ njs_generate_code_move(generator, move, lvalue->index, expr->index,
+ lvalue);
}
node->index = expr->index;
}
njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump,
- NJS_VMCODE_IF_FALSE_JUMP, 2);
+ NJS_VMCODE_IF_FALSE_JUMP, 2, node);
cond_jump->cond = node->left->index;
ret = njs_generate_node_index_release(vm, generator, node->left);
}
njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump,
- NJS_VMCODE_IF_FALSE_JUMP, 2);
+ NJS_VMCODE_IF_FALSE_JUMP, 2, node);
cond_jump_offset = njs_code_offset(generator, cond_jump);
cond_jump->cond = node->left->index;
if (node->index != branch->left->index) {
njs_generate_code_move(generator, move, node->index,
- branch->left->index);
+ branch->left->index, node);
}
ret = njs_generate_node_index_release(vm, generator, branch->left);
if (node->index != branch->right->index) {
njs_generate_code_move(generator, move, node->index,
- branch->right->index);
+ branch->right->index, node);
}
njs_code_set_jump_offset(generator, njs_vmcode_cond_jump_t, jump_offset);
return NJS_ERROR;
}
- njs_generate_code_move(generator, move, index, expr->index);
+ njs_generate_code_move(generator, move, index, expr->index, swtch);
}
ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_SWITCH,
}
njs_generate_code(generator, njs_vmcode_equal_jump_t, equal,
- NJS_VMCODE_IF_EQUAL_JUMP, 3);
+ NJS_VMCODE_IF_EQUAL_JUMP, 3, branch);
equal->offset = offsetof(njs_vmcode_equal_jump_t, offset);
equal->value1 = index;
equal->value2 = node->left->index;
}
njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump,
- NJS_VMCODE_IF_TRUE_JUMP, 2);
+ NJS_VMCODE_IF_TRUE_JUMP, 2, condition);
cond_jump->offset = loop_offset - njs_code_offset(generator, cond_jump);
cond_jump->cond = condition->index;
}
njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump,
- NJS_VMCODE_IF_TRUE_JUMP, 2);
+ NJS_VMCODE_IF_TRUE_JUMP, 2, condition);
cond_jump->offset = loop_offset - njs_code_offset(generator, cond_jump);
cond_jump->cond = condition->index;
}
njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump,
- NJS_VMCODE_IF_TRUE_JUMP, 2);
+ NJS_VMCODE_IF_TRUE_JUMP, 2, condition);
cond_jump->offset = loop_offset - njs_code_offset(generator, cond_jump);
cond_jump->cond = condition->index;
}
njs_generate_code(generator, njs_vmcode_prop_foreach_t, prop_foreach,
- NJS_VMCODE_PROPERTY_FOREACH, 2);
+ NJS_VMCODE_PROPERTY_FOREACH, 2, foreach);
prop_offset = njs_code_offset(generator, prop_foreach);
prop_foreach->object = foreach->right->index;
}
njs_generate_code(generator, njs_vmcode_prop_next_t, prop_next,
- NJS_VMCODE_PROPERTY_NEXT, 3);
+ NJS_VMCODE_PROPERTY_NEXT, 3, node->left->left);
prop_offset = njs_code_offset(generator, prop_next);
prop_next->retval = foreach->left->index;
prop_next->object = foreach->right->index;
if (njs_fast_path(ret == NJS_OK)) {
njs_generate_code(generator, njs_vmcode_stop_t, stop,
- NJS_VMCODE_STOP, 1);
+ NJS_VMCODE_STOP, 1, node);
index = NJS_INDEX_NONE;
node = node->right;
* empty object or expression result is stored directly in variable.
*/
if (lvalue->index != expr->index) {
- njs_generate_code_move(generator, move, lvalue->index, expr->index);
+ njs_generate_code_move(generator, move, lvalue->index, expr->index,
+ expr);
}
node->index = expr->index;
return NJS_ERROR;
}
- njs_generate_code_move(generator, move, index, src);
+ njs_generate_code_move(generator, move, index, src, object);
}
if (property->token_type == NJS_TOKEN_NAME) {
return NJS_ERROR;
}
- njs_generate_code_move(generator, move, index, src);
+ njs_generate_code_move(generator, move, index, src, property);
}
}
switch (lvalue->token_type) {
case NJS_TOKEN_PROPERTY_INIT:
njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set,
- NJS_VMCODE_PROPERTY_INIT, 3);
+ NJS_VMCODE_PROPERTY_INIT, 3, expr);
break;
case NJS_TOKEN_PROTO_INIT:
njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set,
- NJS_VMCODE_PROTO_INIT, 3);
+ NJS_VMCODE_PROTO_INIT, 3, expr);
break;
default:
/* NJS_VMCODE_PROPERTY_SET */
njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set,
- NJS_VMCODE_PROPERTY_SET, 3);
+ NJS_VMCODE_PROPERTY_SET, 3, expr);
}
prop_set->value = expr->index;
/* Preserve variable value if it may be changed by expression. */
njs_generate_code(generator, njs_vmcode_move_t, move,
- NJS_VMCODE_MOVE, 2);
+ NJS_VMCODE_MOVE, 2, expr);
move->src = lvalue->index;
index = njs_generate_temp_index_get(vm, generator, expr);
}
njs_generate_code(generator, njs_vmcode_3addr_t, code,
- node->u.operation, 3);
+ node->u.operation, 3, expr);
code->dst = lvalue->index;
code->src1 = index;
code->src2 = expr->index;
}
njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get,
- NJS_VMCODE_PROPERTY_GET, 3);
+ NJS_VMCODE_PROPERTY_GET, 3, property);
prop_get->value = index;
prop_get->object = object->index;
prop_get->property = property->index;
}
njs_generate_code(generator, njs_vmcode_3addr_t, code,
- node->u.operation, 3);
+ node->u.operation, 3, expr);
code->dst = node->index;
code->src1 = node->index;
code->src2 = expr->index;
njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set,
- NJS_VMCODE_PROPERTY_SET, 3);
+ NJS_VMCODE_PROPERTY_SET, 3, expr);
prop_set->value = node->index;
prop_set->object = object->index;
prop_set->property = property->index;
}
njs_generate_code(generator, njs_vmcode_object_t, object,
- NJS_VMCODE_OBJECT, 1);
+ NJS_VMCODE_OBJECT, 1, node);
object->retval = node->index;
/* Initialize object. */
}
njs_generate_code(generator, njs_vmcode_prop_accessor_t, accessor,
- NJS_VMCODE_PROPERTY_ACCESSOR, 3);
+ NJS_VMCODE_PROPERTY_ACCESSOR, 3, function);
accessor->value = function->index;
accessor->object = object->index;
}
njs_generate_code(generator, njs_vmcode_array_t, array,
- NJS_VMCODE_ARRAY, 1);
+ NJS_VMCODE_ARRAY, 1, node);
array->ctor = node->ctor;
array->retval = node->index;
array->length = node->u.length;
name = module ? &njs_entry_module : &njs_entry_anonymous;
ret = njs_generate_function_scope(vm, lambda, node, name);
-
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- if (vm->debug != NULL) {
- ret = njs_generate_function_debug(vm, name, lambda,
- module ? node->right : node);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
- }
-
njs_generate_code(generator, njs_vmcode_function_t, function,
- NJS_VMCODE_FUNCTION, 1);
+ NJS_VMCODE_FUNCTION, 1, node);
function->lambda = lambda;
node->index = njs_generate_object_dest_index(vm, generator, node);
}
njs_generate_code(generator, njs_vmcode_regexp_t, regexp,
- NJS_VMCODE_REGEXP, 1);
+ NJS_VMCODE_REGEXP, 1, node);
regexp->retval = node->index;
regexp->pattern = node->u.value.data.u.data;
}
njs_generate_code(generator, njs_vmcode_template_literal_t, code,
- NJS_VMCODE_TEMPLATE_LITERAL, 1);
+ NJS_VMCODE_TEMPLATE_LITERAL, 1, node);
code->retval = node->left->index;
node->index = node->left->index;
}
njs_generate_code(generator, njs_vmcode_test_jump_t, test_jump,
- node->u.operation, 2);
+ node->u.operation, 2, node);
jump_offset = njs_code_offset(generator, test_jump);
test_jump->value = node->left->index;
if (node->index != node->right->index) {
njs_generate_code_move(generator, move, node->index,
- node->right->index);
+ node->right->index, node);
}
njs_code_set_jump_offset(generator, njs_vmcode_test_jump_t, jump_offset);
if (njs_slow_path(njs_parser_has_side_effect(right))) {
njs_generate_code(generator, njs_vmcode_move_t, move,
- NJS_VMCODE_MOVE, 2);
+ NJS_VMCODE_MOVE, 2, node);
move->src = left->index;
index = njs_generate_node_temp_index_get(vm, generator, left);
}
njs_generate_code(generator, njs_vmcode_3addr_t, code,
- node->u.operation, 3);
+ node->u.operation, 3, node);
if (!swap) {
code->src1 = left->index;
}
njs_generate_code(generator, njs_vmcode_2addr_t, code,
- node->u.operation, 2);
+ node->u.operation, 2, node);
code->src = node->left->index;
node->index = njs_generate_dest_index(vm, generator, node);
}
njs_generate_code(generator, njs_vmcode_2addr_t, code,
- node->u.operation, 2);
+ node->u.operation, 2, expr);
code->src = node->left->index;
node->index = njs_generate_dest_index(vm, generator, node);
node->index = index;
njs_generate_code(generator, njs_vmcode_3addr_t, code,
- node->u.operation, 3);
+ node->u.operation, 3, node);
code->dst = index;
code->src1 = lvalue->index;
code->src2 = lvalue->index;
}
njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get,
- NJS_VMCODE_PROPERTY_GET, 3);
+ NJS_VMCODE_PROPERTY_GET, 3, node);
prop_get->value = index;
prop_get->object = lvalue->left->index;
prop_get->property = lvalue->right->index;
njs_generate_code(generator, njs_vmcode_3addr_t, code,
- node->u.operation, 3);
+ node->u.operation, 3, node);
code->dst = dest_index;
code->src1 = index;
code->src2 = index;
njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set,
- NJS_VMCODE_PROPERTY_SET, 3);
+ NJS_VMCODE_PROPERTY_SET, 3, node);
prop_set->value = index;
prop_set->object = lvalue->left->index;
prop_set->property = lvalue->right->index;
return ret;
}
- if (vm->debug != NULL) {
- ret = njs_generate_function_debug(vm, &lex_entry->name, lambda, node);
- }
-
return ret;
}
njs_generate_function_scope(njs_vm_t *vm, njs_function_lambda_t *lambda,
njs_parser_node_t *node, const njs_str_t *name)
{
- size_t size;
- njs_arr_t *closure;
- njs_int_t ret;
- njs_generator_t generator;
-
- node = node->right;
+ size_t size;
+ njs_arr_t *closure;
+ njs_bool_t module;
+ njs_vm_code_t *code;
+ njs_generator_t generator;
+ njs_parser_node_t *file_node;
njs_memzero(&generator, sizeof(njs_generator_t));
- ret = njs_generate_scope(vm, &generator, node->scope, name);
+ module = node->right->scope->module;
+ file_node = module ? node->right : node;
- if (njs_fast_path(ret == NJS_OK)) {
- size = 0;
- closure = node->scope->values[1];
+ node = node->right;
- if (closure != NULL) {
- lambda->block_closures = 1;
- lambda->closure_scope = closure->start;
- size = (1 + closure->items) * sizeof(njs_value_t);
+ code = njs_generate_scope(vm, &generator, node->scope, name);
+ if (njs_slow_path(code == NULL)) {
+ if (!njs_is_error(&vm->retval)) {
+ njs_internal_error(vm, "njs_generate_scope() failed");
}
- lambda->closure_size = size;
+ return NJS_ERROR;
+ }
+
+ code->file = file_node->scope->file;
- lambda->nesting = node->scope->nesting;
+ size = 0;
+ closure = node->scope->values[1];
- lambda->start = generator.code_start;
- lambda->local_size = generator.scope_size;
- lambda->local_scope = generator.local_scope;
+ if (closure != NULL) {
+ lambda->block_closures = 1;
+ lambda->closure_scope = closure->start;
+ size = (1 + closure->items) * sizeof(njs_value_t);
}
- return ret;
+ lambda->closure_size = size;
+
+ lambda->nesting = node->scope->nesting;
+
+ lambda->start = generator.code_start;
+ lambda->local_size = generator.scope_size;
+ lambda->local_scope = generator.local_scope;
+
+ return NJS_OK;
}
-njs_int_t
+njs_vm_code_t *
njs_generate_scope(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_scope_t *scope, const njs_str_t *name)
{
size_t size;
uintptr_t scope_size;
njs_int_t ret;
- njs_uint_t n;
+ njs_uint_t n, index;
njs_value_t *value;
njs_vm_code_t *code;
p = njs_mp_alloc(vm->mem_pool, generator->code_size);
if (njs_slow_path(p == NULL)) {
- return NJS_ERROR;
+ njs_memory_error(vm);
+ return NULL;
}
generator->code_start = p;
ret = njs_generate_lambda_variables(vm, generator, scope->top);
if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
+ return NULL;
+ }
+
+ if (vm->codes == NULL) {
+ vm->codes = njs_arr_create(vm->mem_pool, 4, sizeof(njs_vm_code_t));
+ if (njs_slow_path(vm->codes == NULL)) {
+ return NULL;
+ }
+ }
+
+ index = vm->codes->items;
+ code = njs_arr_add(vm->codes);
+ if (njs_slow_path(code == NULL)) {
+ njs_memory_error(vm);
+ return NULL;
+ }
+
+ code->lines = NULL;
+
+ if (vm->options.backtrace) {
+ code->lines = njs_arr_create(vm->mem_pool, 4,
+ sizeof(njs_vm_line_num_t));
+ if (njs_slow_path(code->lines == NULL)) {
+ njs_memory_error(vm);
+ return NULL;
+ }
+
+ generator->lines = code->lines;
}
if (njs_slow_path(njs_generator(vm, generator, scope->top) != NJS_OK)) {
- return NJS_ERROR;
+ return NULL;
}
+ code = njs_arr_item(vm->codes, index);
+ code->start = generator->code_start;
+ code->end = generator->code_end;
+ code->file = scope->file;
+ code->name = *name;
+
generator->code_size = generator->code_end - generator->code_start;
scope_size = njs_scope_offset(scope->next_index[0]);
generator->local_scope = njs_mp_alloc(vm->mem_pool, scope_size);
if (njs_slow_path(generator->local_scope == NULL)) {
- return NJS_ERROR;
+ return NULL;
}
generator->scope_size = scope_size;
njs_set_undefined(value++);
}
- if (vm->codes == NULL) {
- vm->codes = njs_arr_create(vm->mem_pool, 4, sizeof(njs_vm_code_t));
- if (njs_slow_path(vm->codes == NULL)) {
- return NJS_ERROR;
- }
- }
-
- code = njs_arr_add(vm->codes);
- if (njs_slow_path(code == NULL)) {
- return NJS_ERROR;
- }
-
- code->start = generator->code_start;
- code->end = generator->code_end;
- code->file = scope->file;
- code->name = *name;
-
- return NJS_OK;
+ return code;
}
if (var->argument != 0) {
index = njs_scope_index((var->argument - 1), NJS_SCOPE_ARGUMENTS);
- njs_generate_code_move(generator, move, var->index, index);
+ njs_generate_code_move(generator, move, var->index, index, node);
}
if (var->this_object) {
njs_generate_code(generator, njs_vmcode_this_t, this,
- NJS_VMCODE_THIS, 1);
+ NJS_VMCODE_THIS, 1, NULL);
this->dst = var->index;
}
if (var->arguments_object) {
njs_generate_code(generator, njs_vmcode_arguments_t, arguments,
- NJS_VMCODE_ARGUMENTS, 1);
+ NJS_VMCODE_ARGUMENTS, 1, NULL);
arguments->dst = var->index;
}
if (njs_fast_path(immediate == NULL)) {
njs_generate_code(generator, njs_vmcode_return_t, code,
- NJS_VMCODE_RETURN, 1);
+ NJS_VMCODE_RETURN, 1, node);
code->retval = index;
node->index = index;
}
njs_generate_code(generator, njs_vmcode_try_return_t, try_return,
- NJS_VMCODE_TRY_RETURN, 2);
+ NJS_VMCODE_TRY_RETURN, 2, node);
try_return->retval = index;
try_return->save = top->index;
try_return->offset = offsetof(njs_vmcode_try_return_t, offset);
}
njs_generate_code(generator, njs_vmcode_function_frame_t, func,
- NJS_VMCODE_FUNCTION_FRAME, 2);
+ NJS_VMCODE_FUNCTION_FRAME, 2, node);
func_offset = njs_code_offset(generator, func);
func->ctor = node->ctor;
func->name = name->index;
}
njs_generate_code(generator, njs_vmcode_method_frame_t, method,
- NJS_VMCODE_METHOD_FRAME, 3);
+ NJS_VMCODE_METHOD_FRAME, 3, prop);
method_offset = njs_code_offset(generator, method);
method->ctor = node->ctor;
method->object = prop->left->index;
if (arg->index != arg->left->index) {
njs_generate_code_move(generator, move, arg->index,
- arg->left->index);
+ arg->left->index, node);
}
}
node->index = retval;
njs_generate_code(generator, njs_vmcode_function_call_t, call,
- NJS_VMCODE_FUNCTION_CALL, 1);
+ NJS_VMCODE_FUNCTION_CALL, 1, node);
call->retval = retval;
return nargs;
}
-#define njs_generate_code_catch(generator, _code, _exception) \
+#define njs_generate_code_catch(generator, _code, _exception, node) \
do { \
njs_generate_code(generator, njs_vmcode_catch_t, _code, \
- NJS_VMCODE_CATCH, 2); \
+ NJS_VMCODE_CATCH, 2, node); \
_code->offset = sizeof(njs_vmcode_catch_t); \
_code->exception = _exception; \
} while (0)
-#define njs_generate_code_finally(generator, _code, _retval, _exit) \
+#define njs_generate_code_finally(generator, _code, _retval, _exit, node) \
do { \
njs_generate_code(generator, njs_vmcode_finally_t, _code, \
- NJS_VMCODE_FINALLY, 2); \
+ NJS_VMCODE_FINALLY, 2, node); \
_code->retval = _retval; \
_code->exit_value = _exit; \
_code->continue_offset = offsetof(njs_vmcode_finally_t, \
njs_vmcode_try_trampoline_t *try_break, *try_continue;
njs_generate_code(generator, njs_vmcode_try_start_t, try_start,
- NJS_VMCODE_TRY_START, 2);
+ NJS_VMCODE_TRY_START, 2, node);
try_offset = njs_code_offset(generator, try_start);
exception_index = njs_generate_temp_index_get(vm, generator, node);
try_cont_label = undef_label;
njs_generate_code(generator, njs_vmcode_try_end_t, try_end,
- NJS_VMCODE_TRY_END, 0);
+ NJS_VMCODE_TRY_END, 0, NULL);
try_end_offset = njs_code_offset(generator, try_end);
if (try_block->exit != NULL) {
njs_generate_patch_block(vm, generator, try_block->exit);
njs_generate_code(generator, njs_vmcode_try_trampoline_t, try_break,
- NJS_VMCODE_TRY_BREAK, 2);
+ NJS_VMCODE_TRY_BREAK, 2, NULL);
try_break->exit_value = exit_index;
try_break->offset = -sizeof(njs_vmcode_try_end_t);
njs_generate_patch_block(vm, generator, try_block->continuation);
njs_generate_code(generator, njs_vmcode_try_trampoline_t, try_continue,
- NJS_VMCODE_TRY_CONTINUE, 2);
+ NJS_VMCODE_TRY_CONTINUE, 2, NULL);
try_continue->exit_value = exit_index;
try_continue->offset = -sizeof(njs_vmcode_try_end_t);
return NJS_ERROR;
}
- njs_generate_code_catch(generator, catch, catch_index);
+ njs_generate_code_catch(generator, catch, catch_index, node);
ret = njs_generator(vm, generator, node->right);
if (njs_slow_path(ret != NJS_OK)) {
if (try_block->continuation != NULL || try_block->exit != NULL) {
njs_generate_code_finally(generator, finally, exception_index,
- exit_index);
+ exit_index, NULL);
if (try_block->continuation != NULL) {
/*
return NJS_ERROR;
}
- njs_generate_code_catch(generator, catch, catch_index);
+ njs_generate_code_catch(generator, catch, catch_index, node);
catch_offset = njs_code_offset(generator, catch);
ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_TRY,
}
njs_generate_code(generator, njs_vmcode_try_end_t, catch_end,
- NJS_VMCODE_TRY_END, 0);
+ NJS_VMCODE_TRY_END, 0, node->left->right);
catch_end_offset = njs_code_offset(generator, catch_end);
if (catch_block->exit != NULL) {
njs_generate_patch_block(vm, generator, catch_block->exit);
njs_generate_code(generator, njs_vmcode_try_trampoline_t,
- try_break, NJS_VMCODE_TRY_BREAK, 2);
+ try_break, NJS_VMCODE_TRY_BREAK, 2, NULL);
try_break->exit_value = exit_index;
catch_block->continuation);
njs_generate_code(generator, njs_vmcode_try_trampoline_t,
- try_continue, NJS_VMCODE_TRY_CONTINUE, 2);
+ try_continue, NJS_VMCODE_TRY_CONTINUE, 2,
+ NULL);
try_continue->exit_value = exit_index;
/* TODO: release exception variable index. */
- njs_generate_code_catch(generator, catch, exception_index);
+ njs_generate_code_catch(generator, catch, exception_index, NULL);
njs_code_set_jump_offset(generator, njs_vmcode_try_end_t,
catch_end_offset);
} else {
/* A try/finally case. */
- njs_generate_code_catch(generator, catch, exception_index);
+ njs_generate_code_catch(generator, catch, exception_index, NULL);
catch_block = NULL;
}
}
njs_generate_code_finally(generator, finally, exception_index,
- exit_index);
+ exit_index, node);
if (try_block->continuation != NULL
|| (catch_block && catch_block->continuation != NULL))
if (njs_fast_path(ret == NJS_OK)) {
njs_generate_code(generator, njs_vmcode_throw_t, throw,
- NJS_VMCODE_THROW, 1);
+ NJS_VMCODE_THROW, 1, node);
node->index = node->right->index;
throw->retval = node->index;
module = (njs_module_t *) expr->index;
njs_generate_code(generator, njs_vmcode_object_copy_t, copy,
- NJS_VMCODE_OBJECT_COPY, 2);
+ NJS_VMCODE_OBJECT_COPY, 2, node);
copy->retval = index;
copy->object = module->index;
}
njs_generate_code(generator, njs_vmcode_return_t, code,
- NJS_VMCODE_RETURN, 1);
+ NJS_VMCODE_RETURN, 1, NULL);
code->retval = obj->index;
node->index = obj->index;
}
njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get,
- exception ? NJS_VMCODE_GLOBAL_GET: NJS_VMCODE_PROPERTY_GET, 3);
+ exception ? NJS_VMCODE_GLOBAL_GET: NJS_VMCODE_PROPERTY_GET,
+ 3, node);
prop_get->value = index;
prop_get->object = NJS_INDEX_GLOBAL_OBJECT;
}
njs_generate_code(generator, njs_vmcode_reference_error_t, ref_err,
- NJS_VMCODE_REFERENCE_ERROR, 0);
+ NJS_VMCODE_REFERENCE_ERROR, 0, NULL);
ref_err->token_line = node->token_line;
return njs_name_copy(vm, &ref_err->name, &lex_entry->name);
}
-
-
-static njs_int_t
-njs_generate_function_debug(njs_vm_t *vm, const njs_str_t *name,
- njs_function_lambda_t *lambda, njs_parser_node_t *node)
-{
- njs_function_debug_t *debug;
-
- debug = njs_arr_add(vm->debug);
- if (njs_slow_path(debug == NULL)) {
- return NJS_ERROR;
- }
-
- debug->lambda = lambda;
- debug->line = node->token_line;
-
- if (!vm->options.quiet) {
- debug->file = node->scope->file;
-
- } else {
- debug->file = njs_str_value("");
- }
-
- debug->name = (name != NULL) ? *name : no_label;
-
- return NJS_OK;
-}