Commit 1a58c87d authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'generator-simple-destructor' of https://github.com/toshok/pyston

Conflicts:
	src/runtime/generator.cpp

Closes #307
parents 76057292 330b378c
#!/usr/bin/env python
"""Wrapper script for testing the performance of simple AI systems.
bm_ai.py runs the following little solvers:
- N-Queens
This used to contain an alphametics solver, but that was found to be bound
primarily by eval() performance.
"""
# Wanted by the alphametics solver.
from __future__ import division
__author__ = "collinwinter@google.com (Collin Winter)"
# Python imports
import optparse
import re
import string
import time
# Pure-Python implementation of itertools.permutations().
def permutations(iterable, r=None):
"""permutations(range(3), 2) --> (0,1) (0,2) (1,0) (1,2) (2,0) (2,1)"""
pool = tuple(iterable)
n = len(pool)
if r is None:
r = n
indices = range(n)
cycles = range(n-r+1, n+1)[::-1]
yield tuple(pool[i] for i in indices[:r])
while n:
for i in reversed(range(r)):
cycles[i] -= 1
if cycles[i] == 0:
indices[i:] = indices[i+1:] + indices[i:i+1]
cycles[i] = n - i
else:
j = cycles[i]
indices[i], indices[-j] = indices[-j], indices[i]
yield tuple(pool[i] for i in indices[:r])
break
else:
return
# From http://code.activestate.com/recipes/576647/
def n_queens(queen_count):
"""N-Queens solver.
Args:
queen_count: the number of queens to solve for. This is also the
board size.
Yields:
Solutions to the problem. Each yielded value is looks like
(3, 8, 2, 1, 4, ..., 6) where each number is the column position for the
queen, and the index into the tuple indicates the row.
"""
cols = range(queen_count)
for vec in permutations(cols):
if (queen_count == len(set(vec[i]+i for i in cols))
== len(set(vec[i]-i for i in cols))):
yield vec
def test_n_queens(iterations):
# Warm-up runs.
list(n_queens(8))
list(n_queens(8))
times = []
for _ in xrange(iterations):
t0 = time.time()
list(n_queens(8))
t1 = time.time()
times.append(t1 - t0)
return times
test_n_queens(1)
......@@ -184,35 +184,47 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1
memcpy(&this->args->elts[0], args, numArgs * sizeof(Box*));
}
uint64_t stack_low = next_stack_addr;
uint64_t stack_high = stack_low + MAX_STACK_SIZE;
next_stack_addr = stack_high;
void* initial_stack_limit;
if (available_addrs.size() == 0) {
uint64_t stack_low = next_stack_addr;
uint64_t stack_high = stack_low + MAX_STACK_SIZE;
next_stack_addr = stack_high;
#if STACK_GROWS_DOWN
this->stack_begin = (void*)stack_high;
void* initial_stack_limit = (void*)(stack_high - INITIAL_STACK_SIZE);
void* p = mmap(initial_stack_limit, INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
ASSERT(p == initial_stack_limit, "%p %s", p, strerror(errno));
// Create an inaccessible redzone so that the generator stack won't grow indefinitely.
// Looks like it throws a SIGBUS if we reach the redzone; it's unclear if that's better
// or worse than being able to consume all available memory.
void* p2 = mmap((void*)stack_low, STACK_REDZONE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
assert(p2 == (void*)stack_low);
// Interestingly, it seems like MAP_GROWSDOWN will leave a page-size gap between the redzone and the growable
// region.
if (VERBOSITY() >= 1) {
printf("Created new generator stack, starts at %p, currently extends to %p\n", (void*)stack_high,
initial_stack_limit);
printf("Created a redzone from %p-%p\n", (void*)stack_low, (void*)(stack_low + STACK_REDZONE_SIZE));
}
this->stack_begin = (void*)stack_high;
initial_stack_limit = (void*)(stack_high - INITIAL_STACK_SIZE);
void* p = mmap(initial_stack_limit, INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
ASSERT(p == initial_stack_limit, "%p %s", p, strerror(errno));
// Create an inaccessible redzone so that the generator stack won't grow indefinitely.
// Looks like it throws a SIGBUS if we reach the redzone; it's unclear if that's better
// or worse than being able to consume all available memory.
void* p2
= mmap((void*)stack_low, STACK_REDZONE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
assert(p2 == (void*)stack_low);
// Interestingly, it seems like MAP_GROWSDOWN will leave a page-size gap between the redzone and the growable
// region.
if (VERBOSITY() >= 1) {
printf("Created new generator stack, starts at %p, currently extends to %p\n", (void*)stack_high,
initial_stack_limit);
printf("Created a redzone from %p-%p\n", (void*)stack_low, (void*)(stack_low + STACK_REDZONE_SIZE));
}
#else
#error "implement me"
#endif
} else {
#if STACK_GROWS_DOWN
uint64_t stack_high = available_addrs.back();
this->stack_begin = (void*)stack_high;
initial_stack_limit = (void*)(stack_high - INITIAL_STACK_SIZE);
available_addrs.pop_back();
#else
#error "implement me"
#endif
}
assert(((intptr_t)stack_begin & (~(intptr_t)(0xF))) == (intptr_t)stack_begin && "stack must be aligned");
......@@ -254,10 +266,19 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
}
}
void generatorDestructor(Box* b) {
assert(isSubclass(b->cls, generator_cls));
BoxedGenerator* self = static_cast<BoxedGenerator*>(b);
if (self->stack_begin)
available_addrs.push_back((uint64_t)self->stack_begin);
self->stack_begin = NULL;
}
void setupGenerator() {
generator_cls = new BoxedHeapClass(object_cls, &generatorGCHandler, offsetof(BoxedGenerator, attrs),
sizeof(BoxedGenerator), false, "generator");
generator_cls->simple_destructor = generatorDestructor;
generator_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)generatorIter, typeFromClass(generator_cls), 1)));
......
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