[pypy-commit] pypy stmgc-c7: Light finalizers: still a problem if they call some function like close(),
Author: Armin Rigo Branch: stmgc-c7 Changeset: r74011:6355617bf9a2 Date: 2014-10-18 09:14 +0200 http://bitbucket.org/pypy/pypy/changeset/6355617bf9a2/ Log:Light finalizers: still a problem if they call some function like close(), because that triggers stm_become_inevitable(), which can pause and run gc collections --- not supported in light finalizers. diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py --- a/rpython/memory/gc/stmgc.py +++ b/rpython/memory/gc/stmgc.py @@ -78,7 +78,8 @@ if contains_weakptr:# check constant-folded return llop.stm_allocate_weakref(llmemory.GCREF, size, typeid16) if needs_finalizer: -#is_finalizer_light XXX ignored now +#if is_finalizer_light: XXX implement me +# return llop.stm_allocate_f_light(llmemory.GCREF, size, typeid16) return llop.stm_allocate_finalizer(llmemory.GCREF, size, typeid16) return llop.stm_allocate_tid(llmemory.GCREF, size, typeid16) diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py --- a/rpython/rtyper/lltypesystem/lloperation.py +++ b/rpython/rtyper/lltypesystem/lloperation.py @@ -418,6 +418,7 @@ 'stm_allocate_tid': LLOp(sideeffects=False, canmallocgc=True), 'stm_allocate_weakref': LLOp(sideeffects=False, canmallocgc=True), 'stm_allocate_finalizer': LLOp(sideeffects=False, canmallocgc=True), +'stm_allocate_f_light': LLOp(sideeffects=False, canmallocgc=True), 'stm_get_from_obj': LLOp(sideeffects=False), 'stm_get_from_obj_const': LLOp(canfold=True), 'stm_set_into_obj': LLOp(), diff --git a/rpython/translator/stm/funcgen.py b/rpython/translator/stm/funcgen.py --- a/rpython/translator/stm/funcgen.py +++ b/rpython/translator/stm/funcgen.py @@ -98,6 +98,16 @@ result, arg_size) + '((rpyobj_t *)%s)->tid = %s;' % (result, arg_type_id)) +def stm_allocate_f_light(funcgen, op): +arg_size= funcgen.expr(op.args[0]) +arg_type_id = funcgen.expr(op.args[1]) +result = funcgen.expr(op.result) +# XXX NULL returns? +return ('%s = (rpygcchar_t *)stm_allocate(%s); ' % ( +result, arg_size) + +'((rpyobj_t *)%s)->tid = %s;\n' % (result, arg_type_id) + +'stm_enable_light_finalizer(%s);' % (result,)) + def stm_get_from_obj(funcgen, op): assert op.args[0].concretetype == llmemory.GCREF arg_obj = funcgen.expr(op.args[0]) diff --git a/rpython/translator/stm/test/test_ztranslated.py b/rpython/translator/stm/test/test_ztranslated.py --- a/rpython/translator/stm/test/test_ztranslated.py +++ b/rpython/translator/stm/test/test_ztranslated.py @@ -535,6 +535,7 @@ assert 'destructors called: 1\n' in data def test_light_finalizer(self): +py.test.skip("XXX implement me") class X: @rgc.must_be_light_finalizer def __del__(self): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] extradoc extradoc: (fijal, arigo) start working on slides
Author: Maciej Fijalkowski Branch: extradoc Changeset: r5441:e25d84db6be0 Date: 2014-10-18 15:47 +0200 http://bitbucket.org/pypy/extradoc/changeset/e25d84db6be0/ Log:(fijal, arigo) start working on slides diff --git a/talk/pyconpl-2014/benchmarks/abstract.rst b/talk/pyconpl-2014/benchmarks/abstract.rst new file mode 100644 --- /dev/null +++ b/talk/pyconpl-2014/benchmarks/abstract.rst @@ -0,0 +1,7 @@ +How to benchmark code +- + +In this talk, we would like to present basics of how the Python virtual machines +like CPython or PyPy work and how to use that knowledge to write meaningful +benchmarks for your programs. We'll show what's wrong with microbenchmarks +and how to improve the situation. diff --git a/talk/pyconpl-2014/benchmarks/f1.py b/talk/pyconpl-2014/benchmarks/f1.py new file mode 100644 --- /dev/null +++ b/talk/pyconpl-2014/benchmarks/f1.py @@ -0,0 +1,8 @@ + +def f(): +i = 0 +while i < 1: +i += 1 +return i + +f() diff --git a/talk/pyconpl-2014/benchmarks/f2.py b/talk/pyconpl-2014/benchmarks/f2.py new file mode 100644 --- /dev/null +++ b/talk/pyconpl-2014/benchmarks/f2.py @@ -0,0 +1,10 @@ + +def f(): +i = 0 +s = 0 +while i < 1: +s += len(str(i)) +i += 1 +return s + +print f() diff --git a/talk/pyconpl-2014/benchmarks/fib.py b/talk/pyconpl-2014/benchmarks/fib.py new file mode 100644 --- /dev/null +++ b/talk/pyconpl-2014/benchmarks/fib.py @@ -0,0 +1,27 @@ + +import time +import numpy +from matplotlib import pylab + +def fib(n): +if n == 0 or n == 1: +return 1 +return fib(n - 1) + fib(n - 2) + +def f(): +for i in range(1): +"".join(list(str(i))) + +times = [] +for i in xrange(1000): +t0 = time.time() +#f() +fib(17) +times.append(time.time() - t0) + +hist, bins = numpy.histogram(times, 20) +#pylab.plot(bins[:-1], hist) +pylab.ylim(ymin=0, ymax=max(times) * 1.2) +pylab.plot(times) +#pylab.hist(hist, bins, histtype='bar') +pylab.show() diff --git a/talk/pyconpl-2014/benchmarks/talk.rst b/talk/pyconpl-2014/benchmarks/talk.rst new file mode 100644 --- /dev/null +++ b/talk/pyconpl-2014/benchmarks/talk.rst @@ -0,0 +1,78 @@ +- +How to benchmark code +- + +Who are we? + + +xxx + +What is this talk is about? +--- + +* basics how CPython and PyPy run programs + +* a bit of theory about measuring performance + +* microbenchmarks + +* complicated picture of "real world" + +CPython +--- + +* a "simple" virtual machine + +* compiles python code to bytecode + +* runs the bytecode + +* usually invokes tons of runtime functions written in C + +CPython (demo) +-- + +PyPy + + +* not so simple virtual machine + +* all of the above + +* ... and then if the loop/function gets called often enough + it's compiled down to an optimized assembler by the JIT + +PyPy (demo) +--- + +Measurments 101 +--- + +* run your benchmark multiple times + +* the distribution should be gaussian + +* take the average and the variation + +* if the variation is too large, increase the number of iterations + +Let's do it (demo) +-- + +Problems + + +* the whole previous slide is a bunch of nonsense + +* ... + +"Solution" +-- + +* you try your best and do the average anyway + +* presumably cutting off the warmup time + +|pause| + +* not ideal at all ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] extradoc extradoc: merge
Author: Maciej Fijalkowski Branch: extradoc Changeset: r5442:bb1fcacdc6cb Date: 2014-10-18 15:48 +0200 http://bitbucket.org/pypy/extradoc/changeset/bb1fcacdc6cb/ Log:merge diff --git a/talk/pyconpl-2014/talk.pdf b/talk/pyconpl-2014/talk.pdf new file mode 100644 index ..96cfd649da81c326dec0dbe7d92087b9864229d7 GIT binary patch [cut] ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc hashtable: A branch to add "hashtable" support in stmgc
Author: Armin Rigo Branch: hashtable Changeset: r1478:27943c928c3c Date: 2014-10-18 16:54 +0200 http://bitbucket.org/pypy/stmgc/changeset/27943c928c3c/ Log:A branch to add "hashtable" support in stmgc ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc hashtable: Import initial untested logic
Author: Armin Rigo Branch: hashtable Changeset: r1479:04bcef9511f9 Date: 2014-10-18 17:09 +0200 http://bitbucket.org/pypy/stmgc/changeset/04bcef9511f9/ Log:Import initial untested logic diff --git a/c7/stm/hashtable.c b/c7/stm/hashtable.c new file mode 100644 --- /dev/null +++ b/c7/stm/hashtable.c @@ -0,0 +1,276 @@ +#include "stmgc.h" + +/* +Design of stmgc's "hashtable" objects += + +A "hashtable" is theoretically a lazily-filled array of objects of +length 2**64. Initially it is full of NULLs. It's obviously +implemented as a dictionary in which NULL objects are not needed. + +The only operations on a hashtable are reading or writing an object at +a given index. + +There are two markers for every index (a read and a write marker). +This is unlike regular arrays, which have only two markers in total. + + +Implementation +-- + +First idea: have the hashtable in raw memory, pointing to "entry" +objects. The entry objects themselves point to the user-specified +objects, and they have the read/write markers. Every entry object +itself, once created, stays around. It is only removed by the next +major GC if it points to NULL and its read/write markers are not set +in any currently-running transaction. +*/ + + +typedef TLPREFIX struct stm_hashtable_entry_s { +struct object_s header; +uintptr_t index; +object_t *object; +} stm_hashtable_entry_t; + + +#define INITIAL_HASHTABLE_SIZE 8 +#define PERTURB_SHIFT5 +#define RESIZING_LOCK0 + +typedef struct { +uintptr_t mask; + +/* 'resize_counter' start at an odd value, and is decremented (by + 6) for every new item put in 'items'. When it crosses 0, we + instead allocate a bigger table and change 'resize_counter' to + be a regular pointer to it (which is then even). The whole + structure is immutable then. + + The field 'resize_counter' also works as a write lock: changes + go via the intermediate value RESIZING_LOCK (0). +*/ +uintptr_t resize_counter; + +stm_hashtable_entry_t *items[INITIAL_HASHTABLE_SIZE]; +} stm_hashtable_table_t; + +#define IS_EVEN(p) (((p) & 1) == 0) + +struct stm_hashtable_s { +stm_hashtable_table_t *table; +stm_hashtable_table_t initial_table; +}; + + +static inline void init_table(stm_hashtable_table_t *table, uintptr_t itemcount) +{ +table->mask = itemcount - 1; +table->resize_counter = itemcount * 4 + 1; +memset(table->items, 0, itemcount * sizeof(stm_hashtable_entry_t *)); +} + +stm_hashtable_t *stm_hashtable_create(void) +{ +stm_hashtable_t *hashtable = malloc(sizeof(stm_hashtable_t)); +assert(hashtable); +hashtable->table = &hashtable->initial_table; +init_table(&hashtable->initial_table, INITIAL_HASHTABLE_SIZE); +return hashtable; +} + +void stm_hashtable_free(stm_hashtable_t *hashtable) +{ +uintptr_t rc = hashtable->initial_table.resize_counter; +free(hashtable); +while (IS_EVEN(rc)) { +assert(rc != RESIZING_LOCK); + +stm_hashtable_table_t *table = (stm_hashtable_table_t *)rc; +rc = table->resize_counter; +free(table); +} +} + +#if 0 +static void stm_compact_hashtable(stm_hashtable_t *hashtable) +{ +stm_hashtable_table_t *table = hashtable->table; +assert(!IS_EVEN(table->resize_counter)); + +if (table != &hashtable->initial_table) { +uintptr_t rc = hashtable->initial_table.resize_counter; +while (1) { +assert(IS_EVEN(rc)); +assert(rc != RESIZING_LOCK); + +stm_hashtable_table_t *old_table = (stm_hashtable_table_t *)rc; +if (old_table == table) +break; +rc = old_table->resize_counter; +free(old_table); +} +hashtable->initial_table.resize_counter = (uintptr_t)table; +} +if (table->resize_counter < table->mask * 3) { +uintptr_t j, mask = table->mask; +uintptr_t rc = table->resize_counter; +for (j = 0; j <= mask; j++) { +stm_hashtable_entry_t *e = table->items[j]; +if (e != NULL && e->object == NULL) { +if (!_stm_was_read_by_anybody(e)) { +table->items[j] = NULL; +rc += 6; +} +} +} +table->resize_counter = rc; +} +} +#endif + +#define VOLATILE_HASHTABLE(p)((volatile stm_hashtable_t *)(p)) +#define VOLATILE_TABLE(p) ((volatile stm_hashtable_table_t *)(p)) + +static void _insert_clean(stm_hashtable_table_t *table, + stm_hashtable_entry_t *entry) +{ +uintptr_t mask = table->mask; +uintptr_t i = entry->index & mask; +if (table->items[i] == NULL) { +table->items[i] = entry; +return; +} + +uintptr_t perturb = entry->index; +while (1) { +i = (i << 2) + i + perturb + 1; +i &= mask; +if (table->items[i] == NULL) { +table-
[pypy-commit] stmgc hashtable: Next test
Author: Armin Rigo Branch: hashtable Changeset: r1480:e2b457616c30 Date: 2014-10-18 17:27 +0200 http://bitbucket.org/pypy/stmgc/changeset/e2b457616c30/ Log:Next test diff --git a/c7/stm/hashtable.c b/c7/stm/hashtable.c --- a/c7/stm/hashtable.c +++ b/c7/stm/hashtable.c @@ -29,10 +29,13 @@ typedef TLPREFIX struct stm_hashtable_entry_s { struct object_s header; +uint32_t userdata; uintptr_t index; object_t *object; } stm_hashtable_entry_t; +uint32_t stm_hashtable_entry_userdata; + #define INITIAL_HASHTABLE_SIZE 8 #define PERTURB_SHIFT5 @@ -219,7 +222,9 @@ if (rc > 6) { entry = (stm_hashtable_entry_t *) _stm_allocate_old(sizeof(stm_hashtable_entry_t)); +entry->userdata = stm_hashtable_entry_userdata; entry->index = index; +entry->object = NULL; write_fence(); /* make sure 'entry' is fully initialized here */ table->items[i] = entry; write_fence(); /* make sure 'table->items' is written here */ diff --git a/c7/stmgc.h b/c7/stmgc.h --- a/c7/stmgc.h +++ b/c7/stmgc.h @@ -508,7 +508,7 @@ /* Support for light finalizers. This is a simple version of finalizers that guarantees not to do anything fancy, like not resurrecting objects. */ -void (*stmcb_light_finalizer)(object_t *); +extern void (*stmcb_light_finalizer)(object_t *); void stm_enable_light_finalizer(object_t *); /* Support for regular finalizers. Unreachable objects with @@ -525,7 +525,7 @@ transaction. For older objects, the finalizer is called from a random thread between regular transactions, in a new custom transaction. */ -void (*stmcb_finalizer)(object_t *); +extern void (*stmcb_finalizer)(object_t *); object_t *stm_allocate_with_finalizer(ssize_t size_rounded_up); /* Hashtables. Keys are 64-bit unsigned integers, values are @@ -538,6 +538,7 @@ void stm_hashtable_free(stm_hashtable_t *); object_t *stm_hashtable_read(stm_hashtable_t *, uintptr_t key); void stm_hashtable_write(stm_hashtable_t *, uintptr_t key, object_t *nvalue); +extern uint32_t stm_hashtable_entry_userdata; /* END */ diff --git a/c7/test/support.py b/c7/test/support.py --- a/c7/test/support.py +++ b/c7/test/support.py @@ -171,6 +171,7 @@ void stm_hashtable_free(stm_hashtable_t *); object_t *stm_hashtable_read(stm_hashtable_t *, uintptr_t key); void stm_hashtable_write(stm_hashtable_t *, uintptr_t key, object_t *nvalue); +uint32_t stm_hashtable_entry_userdata; """) @@ -410,6 +411,7 @@ CARD_SIZE = lib._STM_CARD_SIZE # 16b at least NB_SEGMENTS = lib.STM_NB_SEGMENTS FAST_ALLOC = lib._STM_FAST_ALLOC +lib.stm_hashtable_entry_userdata = 42 + HDR + 2 * 8 class Conflict(Exception): pass diff --git a/c7/test/test_hashtable.py b/c7/test/test_hashtable.py --- a/c7/test/test_hashtable.py +++ b/c7/test/test_hashtable.py @@ -12,3 +12,15 @@ got = lib.stm_hashtable_read(h, index) assert got == ffi.NULL lib.stm_hashtable_free(h) + +def test_set_value(self): +self.start_transaction() +h = lib.stm_hashtable_create() +lp1 = stm_allocate(16) +lib.stm_hashtable_write(h, 12345678901, lp1) +assert lib.stm_hashtable_read(h, 12345678901) == lp1 +for i in range(64): +index = 12345678901 ^ (1 << i) +assert lib.stm_hashtable_read(h, index) == ffi.NULL +assert lib.stm_hashtable_read(h, 12345678901) == lp1 +lib.stm_hashtable_free(h) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc hashtable: test and fix
Author: Armin Rigo Branch: hashtable Changeset: r1481:34dc63f8a1d1 Date: 2014-10-18 17:47 +0200 http://bitbucket.org/pypy/stmgc/changeset/34dc63f8a1d1/ Log:test and fix diff --git a/c7/stm/hashtable.c b/c7/stm/hashtable.c --- a/c7/stm/hashtable.c +++ b/c7/stm/hashtable.c @@ -220,11 +220,19 @@ item in the current table. */ if (rc > 6) { -entry = (stm_hashtable_entry_t *) -_stm_allocate_old(sizeof(stm_hashtable_entry_t)); -entry->userdata = stm_hashtable_entry_userdata; -entry->index = index; -entry->object = NULL; +char *p = allocate_outside_nursery_large(sizeof(stm_hashtable_entry_t)); +entry = (stm_hashtable_entry_t *)(p - stm_object_pages); + +long j; +for (j = 0; j <= NB_SEGMENTS; j++) { +struct stm_hashtable_entry_s *e = (struct stm_hashtable_entry_s *) +REAL_ADDRESS(get_segment_base(j), entry); +e->header.stm_flags = GCFLAG_WRITE_BARRIER; +e->userdata = stm_hashtable_entry_userdata; +e->index = index; +e->object = NULL; +} + write_fence(); /* make sure 'entry' is fully initialized here */ table->items[i] = entry; write_fence(); /* make sure 'table->items' is written here */ diff --git a/c7/test/test_hashtable.py b/c7/test/test_hashtable.py --- a/c7/test/test_hashtable.py +++ b/c7/test/test_hashtable.py @@ -24,3 +24,31 @@ assert lib.stm_hashtable_read(h, index) == ffi.NULL assert lib.stm_hashtable_read(h, 12345678901) == lp1 lib.stm_hashtable_free(h) + +def test_no_conflict(self): +h = lib.stm_hashtable_create() +lp1 = stm_allocate_old(16) +lp2 = stm_allocate_old(16) +# +self.start_transaction() +stm_set_char(lp1, 'A') +lib.stm_hashtable_write(h, 1234, lp1) +self.commit_transaction() +# +self.start_transaction() +stm_set_char(lp2, 'B') +lib.stm_hashtable_write(h, 9991234, lp2) +# +self.switch(1) +self.start_transaction() +lp1b = lib.stm_hashtable_read(h, 1234) +assert stm_get_char(lp1b) == 'A' +assert lp1b == lp1 +self.commit_transaction() +# +self.switch(0) +assert lib.stm_hashtable_read(h, 9991234) == lp2 +assert stm_get_char(lp2) == 'B' +assert lib.stm_hashtable_read(h, 1234) == lp1 +lib.stm_hashtable_write(h, 1234, ffi.NULL) +self.commit_transaction() ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] stmgc hashtable: Add a test about hashtable conflicts
Author: Armin Rigo Branch: hashtable Changeset: r1482:40201225092d Date: 2014-10-18 17:57 +0200 http://bitbucket.org/pypy/stmgc/changeset/40201225092d/ Log:Add a test about hashtable conflicts diff --git a/c7/test/support.py b/c7/test/support.py --- a/c7/test/support.py +++ b/c7/test/support.py @@ -170,7 +170,9 @@ stm_hashtable_t *stm_hashtable_create(void); void stm_hashtable_free(stm_hashtable_t *); object_t *stm_hashtable_read(stm_hashtable_t *, uintptr_t key); -void stm_hashtable_write(stm_hashtable_t *, uintptr_t key, object_t *nvalue); +bool _check_hashtable_read(stm_hashtable_t *, uintptr_t key); +object_t *hashtable_read_result; +bool _check_hashtable_write(stm_hashtable_t *, uintptr_t key, object_t *nvalue); uint32_t stm_hashtable_entry_userdata; """) @@ -247,6 +249,18 @@ CHECKED(stm_become_globally_unique_transaction(tl, "TESTGUT")); } +object_t *hashtable_read_result; + +bool _check_hashtable_read(stm_hashtable_t *h, uintptr_t key) +{ +CHECKED(hashtable_read_result = stm_hashtable_read(h, key)); +} + +bool _check_hashtable_write(stm_hashtable_t *h, uintptr_t key, object_t *nvalue) +{ +CHECKED(stm_hashtable_write(h, key, nvalue)); +} + #undef CHECKED @@ -566,7 +580,6 @@ - SHADOWSTACK_LENGTH = 1000 _keepalive = weakref.WeakKeyDictionary() diff --git a/c7/test/test_hashtable.py b/c7/test/test_hashtable.py --- a/c7/test/test_hashtable.py +++ b/c7/test/test_hashtable.py @@ -2,53 +2,86 @@ import random import py + +class StmHashTable(object): +def __init__(self): +self.h = lib.stm_hashtable_create() + +def free(self): +lib.stm_hashtable_free(self.h) + +def __getitem__(self, key): +res = lib._check_hashtable_read(self.h, key) +if res: +raise Conflict +return lib.hashtable_read_result + +def __setitem__(self, key, nvalue): +res = lib._check_hashtable_write(self.h, key, nvalue) +if res: +raise Conflict + + class TestHashtable(BaseTest): def test_empty(self): self.start_transaction() -h = lib.stm_hashtable_create() +h = StmHashTable() for i in range(100): index = random.randrange(0, 1<<64) -got = lib.stm_hashtable_read(h, index) +got = h[index] assert got == ffi.NULL -lib.stm_hashtable_free(h) +h.free() def test_set_value(self): self.start_transaction() -h = lib.stm_hashtable_create() +h = StmHashTable() lp1 = stm_allocate(16) -lib.stm_hashtable_write(h, 12345678901, lp1) -assert lib.stm_hashtable_read(h, 12345678901) == lp1 +h[12345678901] = lp1 +assert h[12345678901] == lp1 for i in range(64): index = 12345678901 ^ (1 << i) -assert lib.stm_hashtable_read(h, index) == ffi.NULL -assert lib.stm_hashtable_read(h, 12345678901) == lp1 -lib.stm_hashtable_free(h) +assert h[index] == ffi.NULL +assert h[12345678901] == lp1 +h.free() def test_no_conflict(self): -h = lib.stm_hashtable_create() +h = StmHashTable() lp1 = stm_allocate_old(16) lp2 = stm_allocate_old(16) # self.start_transaction() stm_set_char(lp1, 'A') -lib.stm_hashtable_write(h, 1234, lp1) +h[1234] = lp1 self.commit_transaction() # self.start_transaction() stm_set_char(lp2, 'B') -lib.stm_hashtable_write(h, 9991234, lp2) +h[9991234] = lp2 # self.switch(1) self.start_transaction() -lp1b = lib.stm_hashtable_read(h, 1234) +lp1b = h[1234] assert stm_get_char(lp1b) == 'A' assert lp1b == lp1 self.commit_transaction() # self.switch(0) -assert lib.stm_hashtable_read(h, 9991234) == lp2 +assert h[9991234] == lp2 assert stm_get_char(lp2) == 'B' -assert lib.stm_hashtable_read(h, 1234) == lp1 -lib.stm_hashtable_write(h, 1234, ffi.NULL) +assert h[1234] == lp1 +h[1234] = ffi.NULL self.commit_transaction() +h.free() + +def test_conflict(self): +h = StmHashTable() +lp1 = stm_allocate_old(16) +lp2 = stm_allocate_old(16) +# +self.start_transaction() +h[1234] = lp1 +# +self.switch(1) +self.start_transaction() +py.test.raises(Conflict, "h[1234] = lp2") ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy gc-incminimark-pinning: Merge default into gc-incminimark-pinning.
Author: Gregor Wegberg Branch: gc-incminimark-pinning Changeset: r74012:a541092c6e2f Date: 2014-10-18 19:24 +0200 http://bitbucket.org/pypy/pypy/changeset/a541092c6e2f/ Log:Merge default into gc-incminimark-pinning. This is a first step merging the current incminimark (without zero filling nursery). Still a lot of tests to pass. However, its a start. diff too long, truncating to 2000 out of 16865 lines diff --git a/LICENSE b/LICENSE --- a/LICENSE +++ b/LICENSE @@ -3,8 +3,8 @@ Except when otherwise stated (look for LICENSE files in directories or information at the beginning of each file) all software and documentation in -the 'rpython', 'pypy', 'ctype_configure', 'dotviewer', 'demo', and 'lib_pypy' -directories is licensed as follows: +the 'rpython', 'pypy', 'ctype_configure', 'dotviewer', 'demo', 'lib_pypy', +'py', and '_pytest' directories is licensed as follows: The MIT License @@ -367,3 +367,43 @@ Detailed license information is contained in the NOTICE file in the directory. + +Licenses and Acknowledgements for Incorporated Software +=== + +This section is an incomplete, but growing list of licenses and +acknowledgements for third-party software incorporated in the PyPy +distribution. + +License for 'Tcl/Tk' + + +This copy of PyPy contains library code that may, when used, result in +the Tcl/Tk library to be loaded. PyPy also includes code that may be +regarded as being a copy of some parts of the Tcl/Tk header files. +You may see a copy of the License for Tcl/Tk in the file +`lib_pypy/_tkinter/license.terms` included here. + +License for 'bzip2' +--- + +This copy of PyPy may be linked (dynamically or statically) with the +bzip2 library. You may see a copy of the License for bzip2/libbzip2 at + +http://www.bzip.org/1.0.5/bzip2-manual-1.0.5.html + +License for 'openssl' +- + +This copy of PyPy may be linked (dynamically or statically) with the +openssl library. You may see a copy of the License for OpenSSL at + +https://www.openssl.org/source/license.html + +License for 'gdbm' +-- + +The gdbm module includes code from gdbm.h, which is distributed under +the terms of the GPL license version 2 or any later version. Thus the +gdbm module, provided in the file lib_pypy/gdbm.py, is redistributed +under the terms of the GPL license as well. diff --git a/lib-python/2.7/test/test_select.py b/lib-python/2.7/test/test_select.py --- a/lib-python/2.7/test/test_select.py +++ b/lib-python/2.7/test/test_select.py @@ -57,7 +57,17 @@ del a[-1] return sys.__stdout__.fileno() a[:] = [F()] * 10 -self.assertEqual(select.select([], a, []), ([], a[:5], [])) +result = select.select([], a, []) +# CPython: 'a' ends up with 5 items, because each fileno() +# removes an item and at the middle the iteration stops. +# PyPy: 'a' ends up empty, because the iteration is done on +# a copy of the original list: fileno() is called 10 times. +if test_support.check_impl_detail(cpython=True): +self.assertEqual(len(result[1]), 5) +self.assertEqual(len(a), 5) +if test_support.check_impl_detail(pypy=True): +self.assertEqual(len(result[1]), 10) +self.assertEqual(len(a), 0) def test_main(): test_support.run_unittest(SelectTestCase) diff --git a/lib_pypy/datetime.py b/lib_pypy/datetime.py --- a/lib_pypy/datetime.py +++ b/lib_pypy/datetime.py @@ -1242,7 +1242,7 @@ (other._hour, other._minute, other._second, other._microsecond)) if myoff is None or otoff is None: -raise TypeError("cannot compare naive and aware times") +raise TypeError("can't compare offset-naive and offset-aware times") myhhmm = self._hour * 60 + self._minute - myoff othhmm = other._hour * 60 + other._minute - otoff return _cmp((myhhmm, self._second, self._microsecond), @@ -1838,7 +1838,7 @@ other._hour, other._minute, other._second, other._microsecond)) if myoff is None or otoff is None: -raise TypeError("cannot compare naive and aware datetimes") +raise TypeError("can't compare offset-naive and offset-aware datetimes") # XXX What follows could be done more efficiently... diff = self - other # this will take offsets into account if diff.days < 0: @@ -1885,7 +1885,7 @@ if myoff == otoff: return base if myoff is None or otoff is None: -raise TypeError("cannot mix naive and timezone-aware time") +raise TypeError("can't subtract offset-naive and offset-aware datetimes") return base + timedelta(minutes = otoff-myoff) def __hash__(self): diff --gi
[pypy-commit] pypy gc-incminimark-pinning: passing gc/test/test_object_pinning tests, except skipped ones
Author: Gregor Wegberg Branch: gc-incminimark-pinning Changeset: r74013:fc3eef4065bc Date: 2014-10-18 19:34 +0200 http://bitbucket.org/pypy/pypy/changeset/fc3eef4065bc/ Log:passing gc/test/test_object_pinning tests, except skipped ones diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py --- a/rpython/memory/gc/incminimark.py +++ b/rpython/memory/gc/incminimark.py @@ -723,9 +723,10 @@ "Too many pinned objects?") # result = self.nursery_free -if self.nursery_free + totalsize <= self.nursery + self.nursery_size: +if self.nursery_free + totalsize <= self.nursery_top: self.nursery_free = result + totalsize -ll_assert(self.nursery_free <= self.nursery + self.nursery_size, "nursery overflow") +ll_assert(self.nursery_free <= self.nursery_top, "nursery overflow") +break # # if self.debug_tiny_nursery >= 0: # for debugging ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy gc-incminimark-pinning: passing all object pinning specific GC tests again
Author: Gregor Wegberg Branch: gc-incminimark-pinning Changeset: r74014:26934ad677e7 Date: 2014-10-18 19:46 +0200 http://bitbucket.org/pypy/pypy/changeset/26934ad677e7/ Log:passing all object pinning specific GC tests again diff --git a/rpython/memory/gc/test/test_object_pinning.py b/rpython/memory/gc/test/test_object_pinning.py --- a/rpython/memory/gc/test/test_object_pinning.py +++ b/rpython/memory/gc/test/test_object_pinning.py @@ -636,7 +636,6 @@ def test_pin_nursery_top_scenario1(self): -py.test.skip("nursery no longer zeros, test needs to be rewritten") ptr1 = self.malloc(T) adr1 = llmemory.cast_ptr_to_adr(ptr1) ptr1.someInt = 101 @@ -658,9 +657,9 @@ # scenario: no minor collection happened, only three mallocs # and pins # -# +- nursery nursery_real_top -+ -# | | -# v v +# +- nursery +# | +# v # ++++-...---+ # | pinned | pinned | pinned | empty | # ++++-...---+ @@ -671,11 +670,9 @@ # assert adr3 < self.gc.nursery_free assert self.gc.nursery_free < self.gc.nursery_top -assert self.gc.nursery_top == self.gc.nursery_real_top def test_pin_nursery_top_scenario2(self): -py.test.skip("nursery no longer zeros, test needs to be rewritten") ptr1 = self.malloc(T) adr1 = llmemory.cast_ptr_to_adr(ptr1) ptr1.someInt = 101 @@ -696,9 +693,9 @@ # scenario: after first GC minor collection # -# +- nursery nursery_real_top -+ -# | | -# v v +# +- nursery +# | +# v # ++++-...---+ # | pinned | pinned | pinned | empty | # ++++-...---+ @@ -712,11 +709,9 @@ assert self.gc.nursery_free == self.gc.nursery_top assert self.gc.nursery_top == self.gc.nursery assert self.gc.nursery_top < adr3 -assert adr3 < self.gc.nursery_real_top def test_pin_nursery_top_scenario3(self): -py.test.skip("nursery no longer zeros, test needs to be rewritten") ptr1 = self.malloc(T) adr1 = llmemory.cast_ptr_to_adr(ptr1) ptr1.someInt = 101 @@ -738,9 +733,9 @@ # scenario: after unpinning first object and a minor # collection # -# +- nursery nursery_real_top -+ -# | | -# v v +# +- nursery +# | +# v # ++++-...---+ # | empty | pinned | pinned | empty | # ++++-...---+ @@ -755,11 +750,9 @@ assert self.gc.nursery_free == self.gc.nursery assert self.gc.nursery_top > self.gc.nursery_free assert self.gc.nursery_top < adr2 -assert adr3 < self.gc.nursery_real_top def test_pin_nursery_top_scenario4(self): -py.test.skip("nursery no longer zeros, test needs to be rewritten") ptr1 = self.malloc(T) adr1 = llmemory.cast_ptr_to_adr(ptr1) ptr1.someInt = 101 @@ -781,9 +774,9 @@ # scenario: after unpinning first & second object and a minor # collection # -# +- nursery nursery_real_top -+ -# | | -# v v +# +- nursery +# | +# v # +-++-...---+ # | empty | pinned | empty | # +-++-...---+ @@ -799,11 +792,9 @@ assert self.gc.nursery_free == self.gc.nursery assert self.gc.nursery_free < self.gc.nursery_top assert self.gc.nursery_top < adr3 -assert adr3 < self.gc.nursery_real_top def test_pin_nursery_top_scenario5(self): -py.test.skip("nursery no longer zeros, test needs to be rewritten") ptr1 = self.malloc(T) adr1 = llmemory.cast_ptr_to_adr(ptr1) ptr1.someInt = 101 @@ -825,9 +816,9 @@ # scenario: no minor collection happened, only three mallocs # and pins # -# +- nursery nursery_real_top -+ -# |
[pypy-commit] pypy online-transforms: refactor handling of method objects in bk.immutablevalue()
Author: Ronan Lamy Branch: online-transforms Changeset: r74015:ca0bb5571fc7 Date: 2014-10-19 04:59 +0100 http://bitbucket.org/pypy/pypy/changeset/ca0bb5571fc7/ Log:refactor handling of method objects in bk.immutablevalue() diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py --- a/rpython/annotator/bookkeeper.py +++ b/rpython/annotator/bookkeeper.py @@ -35,6 +35,14 @@ CONTAINERS_S = [SomeList, SomeDict, SomeOrderedDict, SomeTuple] _cls2Some = {cls.knowntype: cls for cls in CONTAINERS_S} + +if '__pypy__' in sys.modules: +def is_user_function(func): +return (isinstance(func, types.FunctionType) and +isinstance(func.func_code, types.CodeType)) +else: +is_user_function = inspect.isfunction + class Bookkeeper(object): """The log of choices that have been made while analysing the operations. It ensures that the same 'choice objects' will be returned if we ask @@ -215,10 +223,6 @@ def immutablevalue(self, x): """The most precise SomeValue instance that contains the immutable value x.""" -# convert unbound methods to the underlying function -if hasattr(x, 'im_self') and x.im_self is None: -x = x.im_func -assert not hasattr(x, 'im_self') tp = type(x) if issubclass(tp, Symbolic): # symbolic constants support result = x.annotation() @@ -310,19 +314,15 @@ elif tp is type: result = SomeConstantType(x, self) elif callable(x): -if hasattr(x, 'im_self') and hasattr(x, 'im_func'): -# on top of PyPy, for cases like 'l.append' where 'l' is a -# global constant list, the find_method() returns non-None -s_self = self.immutablevalue(x.im_self) -result = s_self.find_method(x.im_func.__name__) -elif hasattr(x, '__self__') and x.__self__ is not None: -# for cases like 'l.append' where 'l' is a global constant list -s_self = self.immutablevalue(x.__self__) -result = s_self.find_method(x.__name__) -assert result is not None -elif hasattr(x, '__objclass__'): -cls_s = self.annotationclass(x.__objclass__) -result = cls_s.find_unboundmethod(x.__name__) +if hasattr(x, '__self__'): +if x.__self__ is not None: +# bound instance method +s_self = self.immutablevalue(x.__self__) +result = s_self.find_method(x.__name__) +else: +# unbound method +cls_s = self.annotationclass(x.im_class) +result = cls_s.find_unboundmethod(x.__name__) else: result = None if result is None: @@ -358,7 +358,7 @@ try: return self.descs[pyobj] except KeyError: -if isinstance(pyobj, types.FunctionType): +if is_user_function(pyobj): result = description.FunctionDesc(self, pyobj) elif isinstance(pyobj, (type, types.ClassType)): if pyobj is object: ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit