Browse Source

handle arguments more efficiently

master
Martin Dørum 3 years ago
parent
commit
a47c9f918f
7 changed files with 43 additions and 15 deletions
  1. 5
    0
      include/lang2/bytecode.h
  2. 1
    0
      include/lang2/gen/gen.h
  3. 1
    0
      include/lang2/vm/vm.h
  4. 4
    0
      lib/gen/gen.c
  5. 10
    9
      lib/parse/parse.c
  6. 7
    2
      lib/vm/print.c
  7. 15
    4
      lib/vm/vm.c

+ 5
- 0
include/lang2/bytecode.h View File

L2_OP_RJMP_U4, L2_OP_RJMP_U4,
L2_OP_RJMP_U1, L2_OP_RJMP_U1,


/* Get the arguments array from the stack frame
* Push <arguments array>
*/
L2_OP_STACK_FRAME_GET_ARGS,

/* /*
* Look up a value from the current stack frame; stack_frame_lookup <key> * Look up a value from the current stack frame; stack_frame_lookup <key>
* Find <val> in stack frame using <key> * Find <val> in stack frame using <key>

+ 1
- 0
include/lang2/gen/gen.h View File

void l2_gen_array_set(struct l2_generator *gen, int number); void l2_gen_array_set(struct l2_generator *gen, int number);
void l2_gen_dynamic_lookup(struct l2_generator *gen); void l2_gen_dynamic_lookup(struct l2_generator *gen);
void l2_gen_dynamic_set(struct l2_generator *gen); void l2_gen_dynamic_set(struct l2_generator *gen);
void l2_gen_stack_frame_get_args(struct l2_generator *gen);
void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident); void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident);
void l2_gen_stack_frame_lookup_copy(struct l2_generator *gen, char *ident); void l2_gen_stack_frame_lookup_copy(struct l2_generator *gen, char *ident);
void l2_gen_stack_frame_set(struct l2_generator *gen, char **ident); void l2_gen_stack_frame_set(struct l2_generator *gen, char **ident);

+ 1
- 0
include/lang2/vm/vm.h View File

l2_word ns; l2_word ns;
l2_word sptr; l2_word sptr;
l2_word retptr; l2_word retptr;
l2_word args;
}; };


l2_word l2_vm_namespace_get(struct l2_vm *vm, struct l2_vm_value *ns, l2_word key); l2_word l2_vm_namespace_get(struct l2_vm *vm, struct l2_vm_value *ns, l2_word key);

+ 4
- 0
lib/gen/gen.c View File

put(gen, L2_OP_DYNAMIC_SET); put(gen, L2_OP_DYNAMIC_SET);
} }


void l2_gen_stack_frame_get_args(struct l2_generator *gen) {
put(gen, L2_OP_STACK_FRAME_GET_ARGS);
}

void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident) { void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident) {
size_t atom_id = l2_strset_put(&gen->atomset, ident); size_t atom_id = l2_strset_put(&gen->atomset, ident);
if (atom_id <= 0xff) { if (atom_id <= 0xff) {

+ 10
- 9
lib/parse/parse.c View File

l2_trace_scope("function literal"); l2_trace_scope("function literal");
// '{' and EOL already skipped by parse_object_or_function_literal // '{' and EOL already skipped by parse_object_or_function_literal


// The arguments array will be at the top of the stack
char *ident = "$";
l2_gen_stack_frame_set_copy(gen, ident);

int first = 1; int first = 1;
while (1) { while (1) {
if (l2_token_get_kind(l2_lexer_peek(lexer, 1)) == L2_TOK_CLOSE_BRACE) { if (l2_token_get_kind(l2_lexer_peek(lexer, 1)) == L2_TOK_CLOSE_BRACE) {
l2_trace_scope("ident"); l2_trace_scope("ident");
l2_trace("ident '%s'", l2_token_get_str(tok)); l2_trace("ident '%s'", l2_token_get_str(tok));
struct l2_token_value ident = l2_token_extract_val(tok); struct l2_token_value ident = l2_token_extract_val(tok);
l2_lexer_consume(lexer); // ident

if (ident.flags & L2_TOK_SMALL) {
l2_gen_stack_frame_lookup_copy(gen, ident.strbuf);
if (strcmp(l2_token_get_str(tok), "$") == 0) {
l2_lexer_consume(lexer); // ident
l2_gen_stack_frame_get_args(gen);
} else { } else {
l2_gen_stack_frame_lookup(gen, &ident.str);
l2_lexer_consume(lexer); // ident

if (ident.flags & L2_TOK_SMALL) {
l2_gen_stack_frame_lookup_copy(gen, ident.strbuf);
} else {
l2_gen_stack_frame_lookup(gen, &ident.str);
}
} }
} else if (l2_token_get_kind(tok) == L2_TOK_NUMBER) { } else if (l2_token_get_kind(tok) == L2_TOK_NUMBER) {
l2_trace_scope("number literal"); l2_trace_scope("number literal");

+ 7
- 2
lib/vm/print.c View File



void l2_vm_print_fstack(struct l2_vm *vm) { void l2_vm_print_fstack(struct l2_vm *vm) {
for (l2_word i = 0; i < vm->fsptr; ++i) { for (l2_word i = 0; i < vm->fsptr; ++i) {
printf(" %i: %i, ret %i, stack base %u\n",
i, vm->fstack[i].ns, (int)vm->fstack[i].retptr, vm->fstack[i].sptr);
printf(" %i: %i, ret %i, stack base %u, args %u\n",
i, vm->fstack[i].ns, (int)vm->fstack[i].retptr,
vm->fstack[i].sptr, vm->fstack[i].args);
} }
} }


printf("RJMP %u\n", read_u1le(ops, ptr)); printf("RJMP %u\n", read_u1le(ops, ptr));
return; return;


case L2_OP_STACK_FRAME_GET_ARGS:
printf("STACK_FRAME_GET_ARGS\n");
return;

case L2_OP_STACK_FRAME_LOOKUP_U4: case L2_OP_STACK_FRAME_LOOKUP_U4:
printf("STACK_FRAME_LOOKUP %u\n", read_u4le(ops, ptr)); printf("STACK_FRAME_LOOKUP %u\n", read_u4le(ops, ptr));
return; return;

+ 15
- 4
lib/vm/vm.c View File

vm->fstack[vm->fsptr].ns = builtins; vm->fstack[vm->fsptr].ns = builtins;
vm->fstack[vm->fsptr].retptr = 0; vm->fstack[vm->fsptr].retptr = 0;
vm->fstack[vm->fsptr].sptr = 0; vm->fstack[vm->fsptr].sptr = 0;
vm->fstack[vm->fsptr].args = 0;
vm->fsptr += 1; vm->fsptr += 1;


// Need to allocate a root namespace // Need to allocate a root namespace
vm->fstack[vm->fsptr].ns = root; vm->fstack[vm->fsptr].ns = root;
vm->fstack[vm->fsptr].retptr = ~(l2_word)0; vm->fstack[vm->fsptr].retptr = ~(l2_word)0;
vm->fstack[vm->fsptr].sptr = 0; vm->fstack[vm->fsptr].sptr = 0;
vm->fstack[vm->fsptr].args = 0;
vm->fsptr += 1; vm->fsptr += 1;


// None is always at 0 // None is always at 0
// builtins live, and they aren't sweeped anyways // builtins live, and they aren't sweeped anyways
for (l2_word fsptr = 1; fsptr < vm->fsptr; ++fsptr) { for (l2_word fsptr = 1; fsptr < vm->fsptr; ++fsptr) {
gc_mark(vm, vm->fstack[fsptr].ns); gc_mark(vm, vm->fstack[fsptr].ns);
gc_mark(vm, vm->fstack[fsptr].args);
} }


return gc_sweep(vm); return gc_sweep(vm);
} }


static void call_func_with_args(struct l2_vm *vm, l2_word func_id, l2_word args_id) { static void call_func_with_args(struct l2_vm *vm, l2_word func_id, l2_word args_id) {
l2_word stack_base = vm->sptr;
vm->stack[vm->sptr++] = args_id;

l2_word ns_id = alloc_val(vm); l2_word ns_id = alloc_val(vm);
struct l2_vm_value *func = &vm->values[func_id]; // func might be stale after alloc_val struct l2_vm_value *func = &vm->values[func_id]; // func might be stale after alloc_val
vm->values[ns_id].extra.ns_parent = func->func.ns; vm->values[ns_id].extra.ns_parent = func->func.ns;
vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE; vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE;
vm->fstack[vm->fsptr].ns = ns_id; vm->fstack[vm->fsptr].ns = ns_id;
vm->fstack[vm->fsptr].retptr = vm->iptr; vm->fstack[vm->fsptr].retptr = vm->iptr;
vm->fstack[vm->fsptr].sptr = stack_base;
vm->fstack[vm->fsptr].sptr = vm->sptr;
vm->fstack[vm->fsptr].args = args_id;
vm->fsptr += 1; vm->fsptr += 1;


vm->iptr = func->func.pos; vm->iptr = func->func.pos;

// We need one value as a buffer between the previous stack frame and the new.
// This is mostly due to the way continuations are handled.
// This wouldn't be necessary if continuations were stored in the stack
// frame struct rather than as a value on the stack.
vm->stack[vm->sptr++] = vm->knone;
} }


// The 'call_func' function assumes that all relevant values have been popped off // The 'call_func' function assumes that all relevant values have been popped off
case L2_OP_RJMP_U1: { X(read_u1le); } break; case L2_OP_RJMP_U1: { X(read_u1le); } break;
#undef X #undef X


case L2_OP_STACK_FRAME_GET_ARGS:
vm->stack[vm->sptr++] = vm->fstack[vm->fsptr - 1].args;
break;

#define X(read) \ #define X(read) \
l2_word key = read(vm); \ l2_word key = read(vm); \
struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \ struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \

Loading…
Cancel
Save