From: Brendan Hansen Date: Wed, 14 Feb 2024 05:21:28 +0000 (-0600) Subject: cleaned: implementation details of closures X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=b50dd65eb462bea6d9de3a991d615a286a746791;p=onyx.git cleaned: implementation details of closures 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. --- diff --git a/compiler/src/checker.c b/compiler/src/checker.c index 1760594a..57d436c5 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -2761,7 +2761,9 @@ CheckStatus check_directive_export_name(AstDirectiveExportName *ename) { } 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); diff --git a/compiler/src/types.c b/compiler/src/types.c index 93080800..d886c66a 100644 --- a/compiler/src/types.c +++ b/compiler/src/types.c @@ -259,13 +259,13 @@ u32 type_size_of(Type* type) { 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; @@ -1444,7 +1444,6 @@ static const StructMember array_members[] = { 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[] = { @@ -1550,7 +1549,7 @@ b32 type_lookup_member_by_idx(Type* type, i32 idx, StructMember* smem) { } case Type_Kind_Function: { - if (idx > 2) return 0; + if (idx > 1) return 0; *smem = func_members[idx]; return 1; @@ -1581,7 +1580,7 @@ i32 type_linear_member_count(Type* type) { 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; @@ -1637,10 +1636,6 @@ b32 type_linear_member_lookup(Type* type, i32 idx, TypeWithOffset* two) { 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: { @@ -1682,7 +1677,6 @@ i32 type_get_idx_of_linear_member_with_offset(Type* type, u32 offset) { 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: @@ -1828,7 +1822,7 @@ u32 type_structlike_mem_count(Type* type) { 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; diff --git a/compiler/src/wasm_emit.c b/compiler/src/wasm_emit.c index addef114..0c067fe2 100644 --- a/compiler/src/wasm_emit.c +++ b/compiler/src/wasm_emit.c @@ -1536,13 +1536,10 @@ EMIT_FUNC(for_iterator, AstFor* for_node, u64 iter_local, i64 index_local) { 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); @@ -2044,14 +2041,12 @@ EMIT_FUNC(binop, AstBinaryOp* binop) { } 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); } @@ -2367,7 +2362,6 @@ EMIT_FUNC(call, AstCall* call) { 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); @@ -3666,7 +3660,6 @@ EMIT_FUNC(expression, AstTyped* expr) { WID(NULL, WI_I32_CONST, elemidx); if (!func->captures) { WIL(NULL, WI_PTR_CONST, 0); - WIL(NULL, WI_I32_CONST, 0); break; } @@ -3686,6 +3679,10 @@ EMIT_FUNC(expression, AstTyped* expr) { 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); @@ -3699,9 +3696,6 @@ EMIT_FUNC(expression, AstTyped* expr) { 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; } @@ -4120,7 +4114,6 @@ EMIT_FUNC(cast, AstUnaryOp* cast) { } if (to->kind == Type_Kind_Basic && from->kind == Type_Kind_Function) { - WI(NULL, WI_DROP); WI(NULL, WI_DROP); *pcode = code; return; @@ -4342,7 +4335,6 @@ EMIT_FUNC(zero_value_for_type, Type* type, OnyxToken* where, AstTyped *alloc_nod } 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); @@ -4951,7 +4943,6 @@ static b32 emit_constexpr_(ConstExprContext *ctx, AstTyped *node, u32 offset) { AstFunction* func = (AstFunction *) node; CE(u32, 0) = get_element_idx(ctx->module, func); CE(u32, 4) = 0; - CE(u32, 8) = 0; break; } diff --git a/compiler/src/wasm_type_table.h b/compiler/src/wasm_type_table.h index f72e1b58..9ed96a3d 100644 --- a/compiler/src/wasm_type_table.h +++ b/compiler/src/wasm_type_table.h @@ -415,7 +415,6 @@ static u64 build_type_table(OnyxWasmModule* module) { 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, @@ -679,7 +678,6 @@ static u64 build_type_table(OnyxWasmModule* module) { 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, @@ -1129,7 +1127,6 @@ static u64 build_tagged_procedures(OnyxWasmModule *module) { 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); diff --git a/core/alloc/alloc.onyx b/core/alloc/alloc.onyx index 4b5ab07f..0e0908c4 100644 --- a/core/alloc/alloc.onyx +++ b/core/alloc/alloc.onyx @@ -78,10 +78,13 @@ on_temp :: macro (v: $V) -> &V { 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 diff --git a/core/runtime/platform/wasi/platform.onyx b/core/runtime/platform/wasi/platform.onyx index 17bc1757..918392e7 100644 --- a/core/runtime/platform/wasi/platform.onyx +++ b/core/runtime/platform/wasi/platform.onyx @@ -152,7 +152,7 @@ __random_get :: (buf: [] u8) { PollDescription :: struct { fd: wasi.FileDescriptor; - in: core.io.PollEvent; + input: core.io.PollEvent; out: core.io.PollEvent; } @@ -169,7 +169,7 @@ __poll :: (fds: [] PollDescription, timeout: i32) -> void { 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; @@ -199,7 +199,7 @@ __poll :: (fds: [] PollDescription, timeout: i32) -> void { 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 { diff --git a/core/runtime/platform/wasi/wasi_defs.onyx b/core/runtime/platform/wasi/wasi_defs.onyx index abd1517a..16688d93 100644 --- a/core/runtime/platform/wasi/wasi_defs.onyx +++ b/core/runtime/platform/wasi/wasi_defs.onyx @@ -422,7 +422,7 @@ path_rename :: (fd: FileDescriptor, old_path: str, new_fd: FileDescriptor, new_ 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" --- diff --git a/core/runtime/platform/wasi/wasi_fs.onyx b/core/runtime/platform/wasi/wasi_fs.onyx index ba6f0b86..09300f6a 100644 --- a/core/runtime/platform/wasi/wasi_fs.onyx +++ b/core/runtime/platform/wasi/wasi_fs.onyx @@ -265,7 +265,7 @@ __file_stream_vtable := io.Stream_Vtable.{ 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); diff --git a/core/runtime/platform/wasi/wasix_net.onyx b/core/runtime/platform/wasi/wasix_net.onyx index ee47f6d8..612ca9a4 100644 --- a/core/runtime/platform/wasi/wasix_net.onyx +++ b/core/runtime/platform/wasi/wasix_net.onyx @@ -181,8 +181,8 @@ __net_resolve :: (host: str, port: u16, out_addrs: [] SocketAddress) -> i32 { #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 } }; } @@ -200,8 +200,8 @@ __net_resolve :: (host: str, port: u16, out_addrs: [] SocketAddress) -> i32 { } } - 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 { @@ -218,4 +218,4 @@ __net_resolve :: (host: str, port: u16, out_addrs: [] SocketAddress) -> i32 { } } } -} \ No newline at end of file +} diff --git a/runtime/src/ort_threads.h b/runtime/src/ort_threads.h index 7dc470b3..0cbdcf22 100644 --- a/runtime/src/ort_threads.h +++ b/runtime/src/ort_threads.h @@ -46,13 +46,12 @@ static i32 onyx_run_thread(void *data) { 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 }; @@ -78,7 +77,7 @@ static i32 onyx_run_thread(void *data) { 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); @@ -88,7 +87,7 @@ ONYX_DEF(__spawn_thread, (WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM 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);