Commit a99235e8 authored by Chris Toshok's avatar Chris Toshok

free generator stacks both in the destructor and when a generator exits.

also, don't register MAX_STACK_SIZE bytes with the GC, register INITIAL_STACK_SIZE.
parent 71840bc9
...@@ -60,6 +60,29 @@ public: ...@@ -60,6 +60,29 @@ public:
} }
}; };
static void freeGeneratorStack(BoxedGenerator* g) {
if (g->stack_begin == NULL)
return;
available_addrs.push_back((uint64_t)g->stack_begin);
// Limit the number of generator stacks we keep around:
if (available_addrs.size() > 5) {
uint64_t addr = available_addrs.front();
available_addrs.pop_front();
int r = munmap((void*)(addr - MAX_STACK_SIZE), MAX_STACK_SIZE);
assert(r == 0);
// also unmap the redzone
#if STACK_GROWS_DOWN
r = munmap((void*)addr, STACK_REDZONE_SIZE);
assert(r == 0);
#else
#error "implement me"
#endif
}
g->stack_begin = NULL;
}
Context* getReturnContextForGeneratorFrame(void* frame_addr) { Context* getReturnContextForGeneratorFrame(void* frame_addr) {
BoxedGenerator* generator = s_generator_map[frame_addr]; BoxedGenerator* generator = s_generator_map[frame_addr];
assert(generator); assert(generator);
...@@ -88,6 +111,7 @@ void generatorEntry(BoxedGenerator* g) { ...@@ -88,6 +111,7 @@ void generatorEntry(BoxedGenerator* g) {
// we returned from the body of the generator. next/send/throw will notify the caller // we returned from the body of the generator. next/send/throw will notify the caller
g->entryExited = true; g->entryExited = true;
threading::popGenerator(); threading::popGenerator();
freeGeneratorStack(g);
swapContext(&g->context, g->returnContext, 0); swapContext(&g->context, g->returnContext, 0);
} }
...@@ -220,7 +244,12 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1 ...@@ -220,7 +244,12 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1
#error "implement me" #error "implement me"
#endif #endif
gc::registerGCManagedBytes(MAX_STACK_SIZE); // we're registering memory that isn't in the gc heap here,
// which may sound wrong. Generators, however, can represent
// a larger tax on system resources than just their GC
// allocation, so we try to encode that here as additional gc
// heap pressure.
gc::registerGCManagedBytes(INITIAL_STACK_SIZE);
} else { } else {
generator_stack_reused.log(); generator_stack_reused.log();
...@@ -290,18 +319,7 @@ Box* generatorName(Box* _self, void* context) { ...@@ -290,18 +319,7 @@ Box* generatorName(Box* _self, void* context) {
void generatorDestructor(Box* b) { void generatorDestructor(Box* b) {
assert(isSubclass(b->cls, generator_cls)); assert(isSubclass(b->cls, generator_cls));
BoxedGenerator* self = static_cast<BoxedGenerator*>(b); BoxedGenerator* self = static_cast<BoxedGenerator*>(b);
freeGeneratorStack(self);
if (self->stack_begin) {
available_addrs.push_back((uint64_t)self->stack_begin);
// Limit the number of generator stacks we keep around:
if (available_addrs.size() > 5) {
uint64_t addr = available_addrs.front();
available_addrs.pop_front();
int r = munmap((void*)(addr - MAX_STACK_SIZE), MAX_STACK_SIZE);
assert(r == 0);
}
}
self->stack_begin = NULL;
} }
void setupGenerator() { void setupGenerator() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment