diff --git a/src/heap.cpp b/src/heap.cpp index 28d742d2b1..48ef9af9cf 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -187,7 +187,9 @@ class Segment { assert(segment->context, capacity >= segment->capacity()); uintptr_t* p = newData + offset(capacity); - memcpy(p, data(), size(segment->position()) * BytesPerWord); + if (segment->position()) { + memcpy(p, data(), size(segment->position()) * BytesPerWord); + } if (child) { child->update(newData, capacity); @@ -485,9 +487,18 @@ class Segment { void ensure(unsigned minimum) { if (remaining() < minimum) { - assert(context, rear->position); assert(context, rear->next == 0); + if (rear->position == 0) { + Chain* c = rear; + if (front == rear) { + front = rear = 0; + } else { + rear = rear->previous; + } + Chain::dispose(c); + } + unsigned desired = capacity() + minimum; Chain* c = Chain::make(this, minimum, desired); @@ -501,8 +512,12 @@ class Segment { map->update(c->data() + c->capacity, c->offset + c->capacity); } - rear->next = c; - rear = c; + if (rear) { + rear->next = c; + rear = c; + } else { + front = rear = c; + } } } diff --git a/src/machine.cpp b/src/machine.cpp index 363371db7c..c9e816b9ae 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -27,6 +27,7 @@ join(Thread* t, Thread* o) { if (t != o) { o->systemThread->join(); + o->state = Thread::JoinedState; } } @@ -97,9 +98,15 @@ killZombies(Thread* t, Thread* o) killZombies(t, child); } - if (o->state == Thread::ZombieState) { + switch (o->state) { + case Thread::ZombieState: join(t, o); + // fall through + + case Thread::JoinedState: dispose(t, o, true); + + default: break; } } @@ -1386,12 +1393,16 @@ enter(Thread* t, Thread::State s) if (s == t->state) return; + if (t->state == Thread::ExitState) { + // once in exit state, we stay that way + return; + } + ACQUIRE_RAW(t, t->vm->stateLock); switch (s) { case Thread::ExclusiveState: { - assert(t, t->state == Thread::ActiveState - or t->state == Thread::ExitState); + assert(t, t->state == Thread::ActiveState); while (t->vm->exclusive) { // another thread got here first. @@ -1419,8 +1430,11 @@ enter(Thread* t, Thread::State s) default: abort(t); } + assert(t, t->vm->activeCount > 0); -- t->vm->activeCount; + if (s == Thread::ZombieState) { + assert(t, t->vm->liveCount > 0); -- t->vm->liveCount; } t->state = s; @@ -1467,8 +1481,10 @@ enter(Thread* t, Thread::State s) default: abort(t); } - + + assert(t, t->vm->activeCount > 0); -- t->vm->activeCount; + t->state = s; while (t->vm->liveCount > 1) { diff --git a/src/machine.h b/src/machine.h index 1718a5416c..e1819f9099 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1131,6 +1131,7 @@ class Thread { ActiveState, IdleState, ZombieState, + JoinedState, ExclusiveState, ExitState };