This change reduces the complexity of function closure by removing the `closure_size` property on functions, and instead moves this information into the first 8 bytes of the closure block that is allocated. This means that closure blocks are slightly larger, but this extra field that pushes complexity to the end user is eliminated. Net win.
}
CheckStatus check_capture_block(AstCaptureBlock *block) {
- block->total_size_in_bytes = 0;
+ //
+ // Reserve 8 bytes at the beginning of the closure block for the size of the closure.
+ block->total_size_in_bytes = 8;
bh_arr_each(AstCaptureLocal *, capture, block->captures) {
CHECK(expression, (AstTyped **) capture);
case Type_Kind_Basic: return type->Basic.size;
case Type_Kind_MultiPointer:
case Type_Kind_Pointer: return POINTER_SIZE;
- case Type_Kind_Function: return 3 * POINTER_SIZE;
+ case Type_Kind_Function: return 2 * POINTER_SIZE;
case Type_Kind_Array: return type->Array.size;
case Type_Kind_Struct: return type->Struct.size;
case Type_Kind_Enum: return type_size_of(type->Enum.backing);
case Type_Kind_Slice: return POINTER_SIZE * 2; // HACK: These should not have to be 16 bytes in size, they should only have to be 12,
case Type_Kind_VarArgs: return POINTER_SIZE * 2; // but there are alignment issues right now with that so I decided to not fight it and just make them 16 bytes in size.
- case Type_Kind_DynArray: return POINTER_SIZE + 8 + 8 + 2 * POINTER_SIZE; // data (8), count (4), capacity (4), allocator { func (4 + 4 + 8), data (8) }
+ case Type_Kind_DynArray: return POINTER_SIZE * 3 + POINTER_SIZE * 2 + POINTER_SIZE; // data (8), count (4), capacity (4), allocator { func (4 + 4 + 8), data (8) }
case Type_Kind_Compound: return type->Compound.size;
case Type_Kind_Distinct: return type_size_of(type->Distinct.base_type);
case Type_Kind_Union: return type->Union.size;
static const StructMember func_members[] = {
{ 0, 0, &basic_types[Basic_Kind_U32], "__funcidx", NULL, NULL, -1, 0, 0 },
{ POINTER_SIZE, 1, &basic_types[Basic_Kind_Rawptr], "closure", NULL, NULL, -1, 0, 0 },
- { 2 * POINTER_SIZE, 2, &basic_types[Basic_Kind_U32], "closure_size", NULL, NULL, -1, 0, 0 },
};
static const StructMember union_members[] = {
}
case Type_Kind_Function: {
- if (idx > 2) return 0;
+ if (idx > 1) return 0;
*smem = func_members[idx];
return 1;
switch (type->kind) {
case Type_Kind_Slice:
case Type_Kind_VarArgs: return 2;
- case Type_Kind_Function: return 3;
+ case Type_Kind_Function: return 2;
case Type_Kind_Compound: return bh_arr_length(type->Compound.linear_members);
case Type_Kind_Distinct: return type_linear_member_count(type->Distinct.base_type);
default: return 1;
two->type = &basic_types[Basic_Kind_Rawptr];
two->offset = POINTER_SIZE;
}
- if (idx == 2) {
- two->type = &basic_types[Basic_Kind_U32];
- two->offset = 2 * POINTER_SIZE;
- }
return 1;
default: {
case Type_Kind_Function: {
if (offset == 0) return 0;
if (offset == POINTER_SIZE) return 1;
- if (offset == POINTER_SIZE * 2) return 2;
return -1;
}
default:
case Type_Kind_Struct: return type->Struct.mem_count;
case Type_Kind_Slice: return 2;
case Type_Kind_VarArgs: return 2;
- case Type_Kind_Function: return 3;
+ case Type_Kind_Function: return 2;
case Type_Kind_DynArray: return 4;
case Type_Kind_Distinct: return type_structlike_mem_count(type->Distinct.base_type);
case Type_Kind_Union: return 2;
u64 iterator_remove_func = local_raw_allocate(mod->local_alloc, WASM_TYPE_FUNC);
u64 iterator_done_bool = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
WI(for_node->token, WI_DROP);
- WI(for_node->token, WI_DROP);
WIL(for_node->token, WI_LOCAL_SET, iterator_remove_func);
WI(for_node->token, WI_DROP);
- WI(for_node->token, WI_DROP);
WIL(for_node->token, WI_LOCAL_SET, iterator_close_func);
WI(for_node->token, WI_DROP);
- WI(for_node->token, WI_DROP);
WIL(for_node->token, WI_LOCAL_SET, iterator_next_func);
WIL(for_node->token, WI_LOCAL_SET, iterator_data_ptr);
}
emit_expression(mod, &code, binop->left);
- if (binop->left->type->kind == Type_Kind_Function) { // nocheckin
- WI(NULL, WI_DROP);
+ if (binop->left->type->kind == Type_Kind_Function) {
WI(NULL, WI_DROP);
}
emit_expression(mod, &code, binop->right);
- if (binop->right->type->kind == Type_Kind_Function) { // nocheckin
- WI(NULL, WI_DROP);
+ if (binop->right->type->kind == Type_Kind_Function) {
WI(NULL, WI_DROP);
}
emit_expression(mod, &code, call->callee);
u64 global_closure_base_idx = bh_imap_get(&mod->index_map, (u64) &builtin_closure_base);
- WI(NULL, WI_DROP);
WIL(NULL, WI_GLOBAL_SET, global_closure_base_idx);
i32 type_idx = generate_type_idx(mod, call->callee->type);
WID(NULL, WI_I32_CONST, elemidx);
if (!func->captures) {
WIL(NULL, WI_PTR_CONST, 0);
- WIL(NULL, WI_I32_CONST, 0);
break;
}
u64 capture_block_ptr = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
WIL(NULL, WI_LOCAL_TEE, capture_block_ptr);
+ WIL(NULL, WI_LOCAL_GET, capture_block_ptr);
+ WIL(NULL, WI_I32_CONST, func->captures->total_size_in_bytes);
+ emit_store_instruction(mod, &code, &basic_types[Basic_Kind_U32], 0);
+
// Populate the block
bh_arr_each(AstCaptureLocal *, capture, func->captures->captures) {
WIL(NULL, WI_LOCAL_GET, capture_block_ptr);
emit_store_instruction(mod, &code, (*capture)->type, (*capture)->offset);
}
- local_raw_free(mod->local_alloc, WASM_TYPE_PTR);
-
- WIL(NULL, WI_I32_CONST, func->captures->total_size_in_bytes);
break;
}
}
if (to->kind == Type_Kind_Basic && from->kind == Type_Kind_Function) {
- WI(NULL, WI_DROP);
WI(NULL, WI_DROP);
*pcode = code;
return;
} else if (type->kind == Type_Kind_Function) {
WID(NULL, WI_I32_CONST, mod->null_proc_func_idx);
WIL(NULL, WI_I32_CONST, 0);
- WIL(NULL, WI_I32_CONST, 0);
} else if (type->kind == Type_Kind_Distinct) {
emit_zero_value_for_type(mod, &code, type->Distinct.base_type, where, alloc_node);
AstFunction* func = (AstFunction *) node;
CE(u32, 0) = get_element_idx(ctx->module, func);
CE(u32, 4) = 0;
- CE(u32, 8) = 0;
break;
}
u32 func_idx = get_element_idx(module, node);
bh_buffer_write_u32(&table_buffer, func_idx);
bh_buffer_write_u32(&table_buffer, 0);
- bh_buffer_write_u32(&table_buffer, 0);
bh_arr_push(method_data, ((StructMethodData) {
.name_loc = name_loc,
u32 func_idx = 0; // get_element_idx(module, node);
bh_buffer_write_u32(&table_buffer, func_idx);
bh_buffer_write_u32(&table_buffer, 0);
- bh_buffer_write_u32(&table_buffer, 0);
bh_arr_push(method_data, ((StructMethodData) {
.name_loc = name_loc,
bh_buffer_write_u32(&tag_proc_buffer, get_element_idx(module, func));
bh_buffer_write_u32(&tag_proc_buffer, 0);
- bh_buffer_write_u32(&tag_proc_buffer, 0);
bh_buffer_write_u32(&tag_proc_buffer, func->type->id);
WRITE_SLICE(tag_array_base, tag_count);
bh_buffer_write_u32(&tag_proc_buffer, func->entity->package->id);
copy_closure :: (f: $F/type_is_function, a: Allocator) -> F {
if !f.closure do return f;
- new_closure := raw_alloc(a, f.closure_size);
- memory.copy(new_closure, f.closure, f.closure_size);
+ //
+ // The size of the closure block is stored at offset 0 inside of the closure data.
+ closure_size := *cast(&u32, f.closure);
+ new_closure := raw_alloc(a, closure_size);
+ memory.copy(new_closure, f.closure, closure_size);
- return F.{ f.__funcidx, new_closure, f.closure_size };
+ return F.{ f.__funcidx, new_closure };
}
TEMPORARY_ALLOCATOR_SIZE :: 1 << 16; // 16Kb
PollDescription :: struct {
fd: wasi.FileDescriptor;
- in: core.io.PollEvent;
+ input: core.io.PollEvent;
out: core.io.PollEvent;
}
subs := core.alloc.array_from_stack(wasi.Subscription, count);
for i in fds.count {
subs[i].userdata = ~~ i;
- subs[i].u.tag = switch fds[i].in {
+ subs[i].u.tag = switch fds[i].input {
case .None => .FDRead;
case .Read => .FDRead;
case .Write => .FDWrite;
if ev.type !=.Clock {
if ev.fd_readwrite.nbytes > 0 {
i := cast(i32) ev.userdata;
- fds[i].out = fds[i].in;
+ fds[i].out = fds[i].input;
}
if ev.fd_readwrite.flags & .ReadWriteHangUp {
path_symlink :: (old_path: &u8, old_path_len: Size, fd: FileDescriptor, new_path: str) -> Errno #foreign WASI_VERSION "path_symlink" ---
path_unlink_file :: (fd: FileDescriptor, path: str) -> Errno #foreign WASI_VERSION "path_unlink_file" ---
-poll_oneoff :: (in: &Subscription, out: &Event, nsubscriptions: Size, nevents: &Size) -> Errno #foreign WASI_VERSION "poll_oneoff" ---
+poll_oneoff :: (input: &Subscription, out: &Event, nsubscriptions: Size, nevents: &Size) -> Errno #foreign WASI_VERSION "poll_oneoff" ---
proc_exit :: (rval: ExitCode) -> void #foreign WASI_VERSION "proc_exit" ---
proc_raise :: (sig: Signal) -> Errno #foreign WASI_VERSION "proc_raise" ---
poll = (use fs: &os.File, ev: io.PollEvent, timeout: i32) -> (io.Error, bool) {
p: [1] PollDescription = .[.{
fd = data.fd,
- in = ev,
+ input = ev,
}];
runtime.platform.__poll(p, timeout);
#package {
- socket_addr_to_wasix_addr :: (in: &SocketAddress, out: &wasi.AddrPort) {
- switch *in {
+ socket_addr_to_wasix_addr :: (input: &SocketAddress, out: &wasi.AddrPort) {
+ switch *innput {
case .Unix as &path {
*out = .{ Unix = .{ *cast(&[108] u8) path } };
}
}
}
- wasi_addr_to_socket_address :: (in: &wasi.AddrPort, out: &SocketAddress) {
- switch *in {
+ wasi_addr_to_socket_address :: (input: &wasi.AddrPort, out: &SocketAddress) {
+ switch *input {
case .Unspec ---
case .Ipv4 as &inet {
}
}
}
-}
\ No newline at end of file
+}
i32 thread_id = thread->id;
{ // Call the _thread_start procedure
- wasm_val_t args[7] = {
+ wasm_val_t args[6] = {
WASM_I32_VAL(thread_id),
WASM_I32_VAL(thread->tls_base),
WASM_I32_VAL(thread->stack_base),
WASM_I32_VAL(thread->funcidx),
WASM_I32_VAL(thread->closureptr),
- WASM_I32_VAL(0),
WASM_I32_VAL(thread->dataptr)
};
wasm_val_vec_t results = { 0, 0 };
return 0;
}
-ONYX_DEF(__spawn_thread, (WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+ONYX_DEF(__spawn_thread, (WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
if (threads == NULL) bh_arr_new(bh_heap_allocator(), threads, 128);
bh_arr_insert_end(threads, 1);
OnyxThread *thread = &bh_arr_last(threads);
thread->stack_base = params->data[2].of.i32;
thread->funcidx = params->data[3].of.i32;
thread->closureptr = params->data[4].of.i32;
- thread->dataptr = params->data[6].of.i32;
+ thread->dataptr = params->data[5].of.i32;
wasm_trap_t* traps = NULL;
thread->instance = runtime->wasm_instance_new(runtime->wasm_store, runtime->wasm_module, &runtime->wasm_imports, &traps);