{
StgStack *new_stack, *old_stack;
StgUnderflowFrame *frame;
+ lnat chunk_size;
IF_DEBUG(sanity,checkTSO(tso));
return;
}
+ old_stack = tso->stackobj;
+
+ // If we used less than half of the previous stack chunk, then we
+ // must have failed a stack check for a large amount of stack. In
+ // this case we allocate a double-sized chunk to try to
+ // accommodate the large stack request. If that also fails, the
+ // next chunk will be 4x normal size, and so on.
+ //
+ // It would be better to have the mutator tell us how much stack
+ // was needed, as we do with heap allocations, but this works for
+ // now.
+ //
+ if (old_stack->sp > old_stack->stack + old_stack->stack_size / 2)
+ {
+ chunk_size = 2 * (old_stack->stack_size + sizeofW(StgStack));
+ }
+ else
+ {
+ chunk_size = RtsFlags.GcFlags.stkChunkSize;
+ }
+
debugTraceCap(DEBUG_sched, cap,
"allocating new stack chunk of size %d bytes",
- RtsFlags.GcFlags.stkChunkSize * sizeof(W_));
-
- old_stack = tso->stackobj;
+ chunk_size * sizeof(W_));
- new_stack = (StgStack*) allocate(cap, RtsFlags.GcFlags.stkChunkSize);
+ new_stack = (StgStack*) allocate(cap, chunk_size);
SET_HDR(new_stack, &stg_STACK_info, CCS_SYSTEM);
- TICK_ALLOC_STACK(RtsFlags.GcFlags.stkChunkSize);
+ TICK_ALLOC_STACK(chunk_size);
new_stack->dirty = 0; // begin clean, we'll mark it dirty below
- new_stack->stack_size = RtsFlags.GcFlags.stkChunkSize - sizeofW(StgStack);
+ new_stack->stack_size = chunk_size - sizeofW(StgStack);
new_stack->sp = new_stack->stack + new_stack->stack_size;
tso->tot_stack_size += new_stack->stack_size;
// will be discarded after the first overflow, being replaced by a
// non-moving 32k chunk.
if (old_stack->sp == old_stack->stack + old_stack->stack_size) {
- frame->next_chunk = new_stack;
+ frame->next_chunk = (StgStack*)END_TSO_QUEUE; // dummy
}
tso->stackobj = new_stack;
if (retvals != 0)
{
// we have some return values to copy to the old stack
- if ((new_stack->sp - new_stack->stack) < retvals)
+ if ((nat)(new_stack->sp - new_stack->stack) < retvals)
{
barf("threadStackUnderflow: not enough space for return values");
}