aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-09-11 20:22:49 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-09-12 01:40:58 -0400
commitcf4bccf76566ac112f9142863c3e4dbf81e71d08 (patch)
tree8c0f3565b3a2f233b0b90ac79b752730de7c9774 /src
parent68b49f74c45f9d46ceca0196ad5b2edeee30e26f (diff)
downloadzig-cf4bccf76566ac112f9142863c3e4dbf81e71d08.tar.gz
zig-cf4bccf76566ac112f9142863c3e4dbf81e71d08.zip
improvements targeted at improving async functions
* Reuse bytes of async function frames when non-async functions make `noasync` calls. This prevents explosive stack growth. * Zig now passes a stack size argument to the linker when linking ELF binaries. Linux ignores this value, but it is available as a program header called GNU_STACK. I prototyped some code that memory maps extra space to the stack using this program header, but there was still a problem when accessing stack memory very far down. Stack probing is needed or not working or something. I also prototyped using `@newStackCall` to call main and that does work around the issue but it also brings its own issues. That code is commented out for now in std/special/start.zig. I'm on a plane with no Internet, but I plan to consult with the musl community for advice when I get a chance. * Added `noasync` to a bunch of function calls in std.debug. It's very messy but it's a workaround that makes stack traces functional with evented I/O enabled. Eventually these will be cleaned up as the root bugs are found and fixed. Programs built in blocking mode are unaffected. * Lowered the default stack size of std.io.InStream (for the async version) to 1 MiB instead of 4. Until we figure out how to get choosing a stack size working (see 2nd bullet point above), 4 MiB tends to cause segfaults due to stack size running out, or usage of stack memory too far apart, or something like that. * Default thread stack size is bumped from 8 MiB to 16 to match the size we give for the main thread. It's planned to eventually remove this hard coded value and have Zig able to determine this value during semantic analysis, with call graph analysis and function pointer annotations and extern function annotations.
Diffstat (limited to 'src')
-rw-r--r--src/codegen.cpp14
-rw-r--r--src/link.cpp5
2 files changed, 17 insertions, 2 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index a9542f96d9..200589cd2a 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -7184,6 +7184,9 @@ static void do_code_gen(CodeGen *g) {
if (!is_async) {
// allocate async frames for noasync calls & awaits to async functions
+ ZigType *largest_call_frame_type = nullptr;
+ IrInstruction *all_calls_alloca = ir_create_alloca(g, &fn_table_entry->fndef_scope->base,
+ fn_table_entry->body_node, fn_table_entry, g->builtin_types.entry_void, "@async_call_frame");
for (size_t i = 0; i < fn_table_entry->call_list.length; i += 1) {
IrInstructionCallGen *call = fn_table_entry->call_list.at(i);
if (call->fn_entry == nullptr)
@@ -7195,8 +7198,15 @@ static void do_code_gen(CodeGen *g) {
if (call->frame_result_loc != nullptr)
continue;
ZigType *callee_frame_type = get_fn_frame_type(g, call->fn_entry);
- call->frame_result_loc = ir_create_alloca(g, call->base.scope, call->base.source_node,
- fn_table_entry, callee_frame_type, "");
+ if (largest_call_frame_type == nullptr ||
+ callee_frame_type->abi_size > largest_call_frame_type->abi_size)
+ {
+ largest_call_frame_type = callee_frame_type;
+ }
+ call->frame_result_loc = all_calls_alloca;
+ }
+ if (largest_call_frame_type != nullptr) {
+ all_calls_alloca->value.type = get_pointer_to_type(g, largest_call_frame_type, false);
}
// allocate temporary stack data
for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {
diff --git a/src/link.cpp b/src/link.cpp
index 1130481dce..b10220d5da 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -1615,6 +1615,11 @@ static void construct_linker_job_elf(LinkJob *lj) {
lj->args.append("-error-limit=0");
+ if (g->out_type == OutTypeExe) {
+ lj->args.append("-z");
+ lj->args.append("stack-size=16777216"); // default to 16 MiB
+ }
+
if (g->linker_script) {
lj->args.append("-T");
lj->args.append(g->linker_script);