[pypy-svn] r77200 - in pypy/branch/fast-forward: . pypy/config pypy/doc/discussion pypy/interpreter pypy/jit/backend/x86 pypy/jit/metainterp/optimizeopt pypy/jit/metainterp/test pypy/jit/tl pypy/module/__builtin__ pypy/module/__builtin__/test pypy/module/_ssl/test pypy/module/array pypy/module/array/test pypy/module/gc pypy/module/gc/test pypy/module/pypyjit/test pypy/module/select pypy/module/select/test pypy/module/sys pypy/rlib pypy/rlib/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/memory pypy/rpython/memory/gc pypy/rpython/memory/gc/test pypy/rpython/memory/gctransform pypy/rpython/memory/test pypy/rpython/numpy pypy/translator pypy/translator/c pypy/translator/c/src pypy/translator/c/test
afa at codespeak.net
afa at codespeak.net
Mon Sep 20 13:19:54 CEST 2010
Author: afa
Date: Mon Sep 20 13:19:51 2010
New Revision: 77200
Added:
pypy/branch/fast-forward/pypy/module/gc/app_referents.py
- copied unchanged from r77197, pypy/trunk/pypy/module/gc/app_referents.py
pypy/branch/fast-forward/pypy/module/gc/referents.py
- copied unchanged from r77197, pypy/trunk/pypy/module/gc/referents.py
pypy/branch/fast-forward/pypy/module/gc/test/test_app_referents.py
- copied unchanged from r77197, pypy/trunk/pypy/module/gc/test/test_app_referents.py
pypy/branch/fast-forward/pypy/module/gc/test/test_referents.py
- copied unchanged from r77197, pypy/trunk/pypy/module/gc/test/test_referents.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/inspect.py
- copied unchanged from r77197, pypy/trunk/pypy/rpython/memory/gc/inspect.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/minimark.py
- copied unchanged from r77197, pypy/trunk/pypy/rpython/memory/gc/minimark.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/minimarkpage.py
- copied unchanged from r77197, pypy/trunk/pypy/rpython/memory/gc/minimarkpage.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_minimark.py
- copied unchanged from r77197, pypy/trunk/pypy/rpython/memory/gc/test/test_minimark.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_minimarkpage.py
- copied unchanged from r77197, pypy/trunk/pypy/rpython/memory/gc/test/test_minimarkpage.py
Removed:
pypy/branch/fast-forward/pypy/rpython/numpy/
Modified:
pypy/branch/fast-forward/ (props changed)
pypy/branch/fast-forward/pypy/config/translationoption.py
pypy/branch/fast-forward/pypy/doc/discussion/finalizer-order.txt
pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py
pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py
pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/__init__.py
pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/heap.py
pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/intbounds.py
pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/optimizer.py (contents, props changed)
pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/rewrite.py
pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/virtualize.py
pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py
pypy/branch/fast-forward/pypy/jit/tl/pypyjit_demo.py
pypy/branch/fast-forward/pypy/module/__builtin__/functional.py
pypy/branch/fast-forward/pypy/module/__builtin__/test/test_minmax.py
pypy/branch/fast-forward/pypy/module/_ssl/test/test_ssl.py
pypy/branch/fast-forward/pypy/module/array/interp_array.py
pypy/branch/fast-forward/pypy/module/array/test/test_array_old.py (props changed)
pypy/branch/fast-forward/pypy/module/gc/__init__.py
pypy/branch/fast-forward/pypy/module/gc/interp_gc.py
pypy/branch/fast-forward/pypy/module/gc/test/test_gc.py
pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py
pypy/branch/fast-forward/pypy/module/select/interp_select.py
pypy/branch/fast-forward/pypy/module/select/test/test_select.py
pypy/branch/fast-forward/pypy/module/sys/version.py
pypy/branch/fast-forward/pypy/rlib/_rsocket_rffi.py
pypy/branch/fast-forward/pypy/rlib/rarithmetic.py
pypy/branch/fast-forward/pypy/rlib/rgc.py
pypy/branch/fast-forward/pypy/rlib/rstring.py
pypy/branch/fast-forward/pypy/rlib/rwin32.py
pypy/branch/fast-forward/pypy/rlib/test/test_rgc.py
pypy/branch/fast-forward/pypy/rpython/llinterp.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/llheap.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/base.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/generation.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/markcompact.py
pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_direct.py
pypy/branch/fast-forward/pypy/rpython/memory/gctransform/framework.py
pypy/branch/fast-forward/pypy/rpython/memory/gctypelayout.py
pypy/branch/fast-forward/pypy/rpython/memory/gcwrapper.py
pypy/branch/fast-forward/pypy/rpython/memory/lltypelayout.py
pypy/branch/fast-forward/pypy/rpython/memory/support.py
pypy/branch/fast-forward/pypy/rpython/memory/test/test_gc.py
pypy/branch/fast-forward/pypy/rpython/memory/test/test_support.py
pypy/branch/fast-forward/pypy/rpython/memory/test/test_transformed_gc.py
pypy/branch/fast-forward/pypy/rpython/rptr.py
pypy/branch/fast-forward/pypy/translator/c/funcgen.py
pypy/branch/fast-forward/pypy/translator/c/src/mem.h
pypy/branch/fast-forward/pypy/translator/c/test/test_newgc.py
pypy/branch/fast-forward/pypy/translator/exceptiontransform.py
Log:
merge from trunk
Modified: pypy/branch/fast-forward/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/fast-forward/pypy/config/translationoption.py (original)
+++ pypy/branch/fast-forward/pypy/config/translationoption.py Mon Sep 20 13:19:51 2010
@@ -52,7 +52,7 @@
# gc
ChoiceOption("gc", "Garbage Collection Strategy",
["boehm", "ref", "marksweep", "semispace", "statistics",
- "generation", "hybrid", "markcompact", "none"],
+ "generation", "hybrid", "markcompact", "minimark", "none"],
"ref", requires={
"ref": [("translation.rweakref", False), # XXX
("translation.gctransformer", "ref")],
@@ -65,6 +65,7 @@
"hybrid": [("translation.gctransformer", "framework")],
"boehm": [("translation.gctransformer", "boehm")],
"markcompact": [("translation.gctransformer", "framework")],
+ "minimark": [("translation.gctransformer", "framework")],
},
cmdline="--gc"),
ChoiceOption("gctransformer", "GC transformer that is used - internal",
Modified: pypy/branch/fast-forward/pypy/doc/discussion/finalizer-order.txt
==============================================================================
--- pypy/branch/fast-forward/pypy/doc/discussion/finalizer-order.txt (original)
+++ pypy/branch/fast-forward/pypy/doc/discussion/finalizer-order.txt Mon Sep 20 13:19:51 2010
@@ -133,8 +133,8 @@
that doesn't change the state of an object, we don't follow its children
recursively.
-In practice we can encode the 4 states with a single extra bit in the
-header:
+In practice, in the SemiSpace, Generation and Hybrid GCs, we can encode
+the 4 states with a single extra bit in the header:
===== ============= ======== ====================
state is_forwarded? bit set? bit set in the copy?
@@ -150,3 +150,17 @@
bit in the copy at the end, to clean up before the next collection
(which means recursively bumping the state from 2 to 3 in the final
loop).
+
+In the MiniMark GC, the objects don't move (apart from when they are
+copied out of the nursery), but we use the flag GCFLAG_VISITED to mark
+objects that survive, so we can also have a single extra bit for
+finalizers:
+
+ ===== ============== ============================
+ state GCFLAG_VISITED GCFLAG_FINALIZATION_ORDERING
+ ===== ============== ============================
+ 0 no no
+ 1 no yes
+ 2 yes yes
+ 3 yes no
+ ===== ============== ============================
Modified: pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/baseobjspace.py Mon Sep 20 13:19:51 2010
@@ -71,7 +71,8 @@
space.wrap("__class__ assignment: only for heap types"))
def user_setup(self, space, w_subtype):
- assert False, "only for interp-level user subclasses from typedef.py"
+ raise NotImplementedError("only for interp-level user subclasses "
+ "from typedef.py")
def getname(self, space, default):
try:
Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py Mon Sep 20 13:19:51 2010
@@ -1,16 +1,17 @@
import sys, os
from pypy.jit.backend.llsupport import symbolic
from pypy.jit.metainterp.history import Const, Box, BoxInt, BoxPtr, BoxFloat
-from pypy.jit.metainterp.history import AbstractFailDescr, INT, REF, FLOAT,\
- LoopToken
+from pypy.jit.metainterp.history import (AbstractFailDescr, INT, REF, FLOAT,
+ LoopToken)
from pypy.rpython.lltypesystem import lltype, rffi, rstr, llmemory
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.annlowlevel import llhelper
from pypy.tool.uid import fixid
-from pypy.jit.backend.x86.regalloc import RegAlloc, \
- X86RegisterManager, X86XMMRegisterManager, get_ebp_ofs
+from pypy.jit.backend.x86.regalloc import (RegAlloc, X86RegisterManager,
+ X86XMMRegisterManager, get_ebp_ofs)
-from pypy.jit.backend.x86.arch import FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD, IS_X86_32, IS_X86_64
+from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD,
+ IS_X86_32, IS_X86_64)
from pypy.jit.backend.x86.regloc import (eax, ecx, edx, ebx,
esp, ebp, esi, edi,
@@ -474,6 +475,7 @@
# align, e.g. for Mac OS X
aligned_words = align_stack_words(words+2)-2 # 2 = EIP+EBP
mc.writeimm32(-WORD * aligned_words)
+ mc.valgrind_invalidated()
mc.done()
def _call_header(self):
@@ -596,6 +598,7 @@
target = newlooptoken._x86_direct_bootstrap_code
mc = codebuf.InMemoryCodeBuilder(oldadr, oldadr + 16)
mc.JMP(imm(target))
+ mc.valgrind_invalidated()
mc.done()
def _assemble_bootstrap_code(self, inputargs, arglocs):
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/__init__.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/__init__.py Mon Sep 20 13:19:51 2010
@@ -1,8 +1,8 @@
-from optimizer import Optimizer
-from rewrite import OptRewrite
-from intbounds import OptIntBounds
-from virtualize import OptVirtualize
-from heap import OptHeap
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimizer
+from pypy.jit.metainterp.optimizeopt.rewrite import OptRewrite
+from pypy.jit.metainterp.optimizeopt.intbounds import OptIntBounds
+from pypy.jit.metainterp.optimizeopt.virtualize import OptVirtualize
+from pypy.jit.metainterp.optimizeopt.heap import OptHeap
def optimize_loop_1(metainterp_sd, loop, virtuals=True):
"""Optimize loop.operations to make it match the input of loop.specnodes
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/heap.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/heap.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/heap.py Mon Sep 20 13:19:51 2010
@@ -2,7 +2,7 @@
from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.rlib.objectmodel import we_are_translated
-from optimizer import Optimization
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
class CachedArrayItems(object):
def __init__(self):
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/intbounds.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/intbounds.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/intbounds.py Mon Sep 20 13:19:51 2010
@@ -1,6 +1,7 @@
-from optimizer import Optimization, CONST_1, CONST_0
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization, CONST_1, CONST_0
from pypy.jit.metainterp.optimizeutil import _findall
-from pypy.jit.metainterp.optimizeopt.intutils import IntBound, IntUnbounded
+from pypy.jit.metainterp.optimizeopt.intutils import IntBound, IntUnbounded, \
+ IntLowerBound
from pypy.jit.metainterp.history import Const, ConstInt
from pypy.jit.metainterp.resoperation import rop, ResOperation
@@ -25,7 +26,7 @@
b = v.intbound
if b.has_lower and b.has_upper and b.lower == b.upper:
v.make_constant(ConstInt(b.lower))
-
+
try:
op = self.optimizer.producer[box]
except KeyError:
@@ -35,7 +36,7 @@
if opnum == value:
func(self, op)
break
-
+
def optimize_GUARD_TRUE(self, op):
self.emit_operation(op)
self.propagate_bounds_backward(op.args[0])
@@ -47,7 +48,7 @@
v1 = self.getvalue(op.args[0])
v2 = self.getvalue(op.args[1])
self.emit_operation(op)
-
+
r = self.getvalue(op.result)
if v2.is_constant():
val = v2.box.getint()
@@ -57,14 +58,14 @@
val = v1.box.getint()
if val >= 0:
r.intbound.intersect(IntBound(0,val))
-
+
def optimize_INT_SUB(self, op):
v1 = self.getvalue(op.args[0])
v2 = self.getvalue(op.args[1])
self.emit_operation(op)
r = self.getvalue(op.result)
r.intbound.intersect(v1.intbound.sub_bound(v2.intbound))
-
+
def optimize_INT_ADD(self, op):
v1 = self.getvalue(op.args[0])
v2 = self.getvalue(op.args[1])
@@ -93,7 +94,7 @@
self.emit_operation(op)
r = self.getvalue(op.result)
r.intbound.intersect(resbound)
-
+
def optimize_INT_SUB_OVF(self, op):
v1 = self.getvalue(op.args[0])
v2 = self.getvalue(op.args[1])
@@ -123,7 +124,7 @@
self.emit_operation(op)
r = self.getvalue(op.result)
r.intbound.intersect(resbound)
-
+
def optimize_INT_LT(self, op):
v1 = self.getvalue(op.args[0])
v2 = self.getvalue(op.args[1])
@@ -171,9 +172,9 @@
self.make_constant_int(op.result, 0)
elif v1.intbound.known_lt(v2.intbound):
self.make_constant_int(op.result, 0)
- else:
+ else:
self.emit_operation(op)
-
+
def optimize_INT_NE(self, op):
v1 = self.getvalue(op.args[0])
v2 = self.getvalue(op.args[1])
@@ -181,17 +182,24 @@
self.make_constant_int(op.result, 1)
elif v1.intbound.known_lt(v2.intbound):
self.make_constant_int(op.result, 1)
- else:
+ else:
self.emit_operation(op)
-
+
+ def optimize_ARRAYLEN_GC(self, op):
+ self.emit_operation(op)
+ v1 = self.getvalue(op.result)
+ v1.intbound.make_ge(IntLowerBound(0))
+
+ optimize_STRLEN = optimize_ARRAYLEN_GC
+
def make_int_lt(self, args):
v1 = self.getvalue(args[0])
v2 = self.getvalue(args[1])
if v1.intbound.make_lt(v2.intbound):
- self.propagate_bounds_backward(args[0])
+ self.propagate_bounds_backward(args[0])
if v2.intbound.make_gt(v1.intbound):
self.propagate_bounds_backward(args[1])
-
+
def make_int_le(self, args):
v1 = self.getvalue(args[0])
@@ -267,7 +275,7 @@
r = self.getvalue(op.result)
b = r.intbound.sub_bound(v2.intbound)
if v1.intbound.intersect(b):
- self.propagate_bounds_backward(op.args[0])
+ self.propagate_bounds_backward(op.args[0])
b = r.intbound.sub_bound(v1.intbound)
if v2.intbound.intersect(b):
self.propagate_bounds_backward(op.args[1])
@@ -278,10 +286,10 @@
r = self.getvalue(op.result)
b = r.intbound.add_bound(v2.intbound)
if v1.intbound.intersect(b):
- self.propagate_bounds_backward(op.args[0])
+ self.propagate_bounds_backward(op.args[0])
b = r.intbound.sub_bound(v1.intbound).mul(-1)
if v2.intbound.intersect(b):
- self.propagate_bounds_backward(op.args[1])
+ self.propagate_bounds_backward(op.args[1])
def propagate_bounds_INT_MUL(self, op):
v1 = self.getvalue(op.args[0])
@@ -289,7 +297,7 @@
r = self.getvalue(op.result)
b = r.intbound.div_bound(v2.intbound)
if v1.intbound.intersect(b):
- self.propagate_bounds_backward(op.args[0])
+ self.propagate_bounds_backward(op.args[0])
b = r.intbound.div_bound(v1.intbound)
if v2.intbound.intersect(b):
self.propagate_bounds_backward(op.args[1])
@@ -300,4 +308,3 @@
optimize_ops = _findall(OptIntBounds, 'optimize_')
propagate_bounds_ops = _findall(OptIntBounds, 'propagate_bounds_')
-
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/optimizer.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/optimizer.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/optimizer.py Mon Sep 20 13:19:51 2010
@@ -11,7 +11,7 @@
from pypy.jit.metainterp.typesystem import llhelper, oohelper
from pypy.rpython.lltypesystem import lltype
from pypy.jit.metainterp.history import AbstractDescr, make_hashable_int
-from intutils import IntBound, IntUnbounded
+from pypy.jit.metainterp.optimizeopt.intutils import IntBound, IntUnbounded
LEVEL_UNKNOWN = '\x00'
LEVEL_NONNULL = '\x01'
@@ -187,7 +187,7 @@
class Optimizer(Optimization):
- def __init__(self, metainterp_sd, loop, optimizations=[], virtuals=True):
+ def __init__(self, metainterp_sd, loop, optimizations=None, virtuals=True):
self.metainterp_sd = metainterp_sd
self.cpu = metainterp_sd.cpu
self.loop = loop
@@ -199,10 +199,8 @@
self.pure_operations = args_dict()
self.producer = {}
self.pendingfields = []
-
- if len(optimizations) == 0:
- self.first_optimization = self
- else:
+
+ if optimizations:
self.first_optimization = optimizations[0]
for i in range(1, len(optimizations)):
optimizations[i - 1].next_optimization = optimizations[i]
@@ -210,6 +208,8 @@
for o in optimizations:
o.optimizer = self
o.setup(virtuals)
+ else:
+ self.first_optimization = self
def forget_numberings(self, virtualbox):
self.metainterp_sd.profiler.count(jitprof.OPT_FORCINGS)
@@ -351,9 +351,9 @@
if op.opnum == rop.GUARD_VALUE:
if self.getvalue(op.args[0]) in self.bool_boxes:
# Hack: turn guard_value(bool) into guard_true/guard_false.
- # This is done after the operation is emitted, to let
- # store_final_boxes_in_guard set the guard_opnum field
- # of the descr to the original rop.GUARD_VALUE.
+ # This is done after the operation is emitted to let
+ # store_final_boxes_in_guard set the guard_opnum field of the
+ # descr to the original rop.GUARD_VALUE.
constvalue = op.args[1].getint()
if constvalue == 0:
opnum = rop.GUARD_FALSE
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/rewrite.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/rewrite.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/rewrite.py Mon Sep 20 13:19:51 2010
@@ -1,11 +1,11 @@
-from optimizer import *
+from pypy.jit.metainterp.optimizeopt.optimizer import *
from pypy.jit.metainterp.resoperation import opboolinvers, opboolreflex
from pypy.jit.metainterp.history import ConstInt
from pypy.jit.metainterp.optimizeutil import _findall
from pypy.jit.metainterp.resoperation import rop, ResOperation
class OptRewrite(Optimization):
- """Rewrite operations into equvivialent, cheeper operations.
+ """Rewrite operations into equivalent, cheaper operations.
This includes already executed operations and constants.
"""
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/virtualize.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/virtualize.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/virtualize.py Mon Sep 20 13:19:51 2010
@@ -6,7 +6,7 @@
from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.jit.metainterp.optimizeutil import _findall
from pypy.rlib.objectmodel import we_are_translated
-from optimizer import *
+from pypy.jit.metainterp.optimizeopt.optimizer import *
class AbstractVirtualValue(OptValue):
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_optimizeopt.py Mon Sep 20 13:19:51 2010
@@ -33,7 +33,7 @@
self.profiler = EmptyProfiler()
self.options = Fake()
self.globaldata = Fake()
-
+
def test_store_final_boxes_in_guard():
from pypy.jit.metainterp.compile import ResumeGuardDescr
from pypy.jit.metainterp.resume import tag, TAGBOX
@@ -75,7 +75,7 @@
assert lst3 == [LLtypeMixin.valuedescr]
lst4 = virt1._get_field_descr_list()
assert lst3 is lst4
-
+
virt2 = virtualize.AbstractVirtualStructValue(opt, None)
lst5 = virt2._get_field_descr_list()
assert lst5 is lst1
@@ -489,7 +489,7 @@
jump()
"""
self.optimize_loop(ops, 'Constant(myptr)', expected)
-
+
def test_ooisnull_oononnull_1(self):
ops = """
[p0]
@@ -842,7 +842,7 @@
jump(f, f1)
"""
self.optimize_loop(ops, 'Not, Virtual(node_vtable, floatdescr=Not)',
- expected, checkspecnodes=False)
+ expected, checkspecnodes=False)
def test_virtual_2(self):
ops = """
@@ -2171,7 +2171,7 @@
jump(i1, i0)
"""
self.optimize_loop(ops, 'Not, Not', expected)
-
+
def test_fold_partially_constant_ops(self):
ops = """
[i0]
@@ -2183,7 +2183,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
ops = """
[i0]
i1 = int_add(i0, 0)
@@ -2194,7 +2194,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
ops = """
[i0]
i1 = int_add(0, i0)
@@ -2205,7 +2205,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
# ----------
def make_fail_descr(self):
@@ -3119,7 +3119,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_lt_noguard(self):
ops = """
[i0]
@@ -3134,7 +3134,7 @@
jump(i2)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_lt_noopt(self):
ops = """
[i0]
@@ -3153,7 +3153,7 @@
jump(4)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_lt_rev(self):
ops = """
[i0]
@@ -3170,7 +3170,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_lt_tripple(self):
ops = """
[i0]
@@ -3189,7 +3189,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_lt_add(self):
ops = """
[i0]
@@ -3204,11 +3204,11 @@
[i0]
i1 = int_lt(i0, 4)
guard_true(i1) []
- i2 = int_add(i0, 10)
+ i2 = int_add(i0, 10)
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_lt_add_before(self):
ops = """
[i0]
@@ -3227,7 +3227,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_lt_add_ovf(self):
ops = """
[i0]
@@ -3243,11 +3243,11 @@
[i0]
i1 = int_lt(i0, 4)
guard_true(i1) []
- i2 = int_add(i0, 10)
+ i2 = int_add(i0, 10)
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_lt_add_ovf_before(self):
ops = """
[i0]
@@ -3268,7 +3268,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_lt_sub(self):
ops = """
[i0]
@@ -3283,11 +3283,11 @@
[i0]
i1 = int_lt(i0, 4)
guard_true(i1) []
- i2 = int_sub(i0, 10)
+ i2 = int_sub(i0, 10)
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_lt_sub_before(self):
ops = """
[i0]
@@ -3306,7 +3306,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_ltle(self):
ops = """
[i0]
@@ -3357,7 +3357,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_gtge(self):
ops = """
[i0]
@@ -3374,7 +3374,7 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
-
+
def test_bound_gegt(self):
ops = """
[i0]
@@ -3414,6 +3414,42 @@
"""
self.optimize_loop(ops, 'Not', expected)
+ def test_bound_arraylen(self):
+ ops = """
+ [i0, p0]
+ p1 = new_array(i0, descr=arraydescr)
+ i1 = arraylen_gc(p1)
+ i2 = int_gt(i1, -1)
+ guard_true(i2) []
+ setarrayitem_gc(p0, 0, p1)
+ jump(i0, p0)
+ """
+ # The dead arraylen_gc will be eliminated by the backend.
+ expected = """
+ [i0, p0]
+ p1 = new_array(i0, descr=arraydescr)
+ i1 = arraylen_gc(p1)
+ setarrayitem_gc(p0, 0, p1)
+ jump(i0, p0)
+ """
+ self.optimize_loop(ops, 'Not, Not', expected)
+
+ def test_bound_strlen(self):
+ ops = """
+ [p0]
+ i0 = strlen(p0)
+ i1 = int_ge(i0, 0)
+ guard_true(i1) []
+ jump(p0)
+ """
+ # The dead strlen will be eliminated be the backend.
+ expected = """
+ [p0]
+ i0 = strlen(p0)
+ jump(p0)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
def test_addsub_const(self):
ops = """
[i0]
@@ -3558,7 +3594,7 @@
i14 = int_gt(i1, 10)
guard_true(i14) []
i15 = int_ge(i1, 20)
- guard_true(i15) []
+ guard_true(i15) []
jump(i1)
"""
expected = """
@@ -3571,7 +3607,7 @@
i14 = int_gt(i1, 10)
guard_true(i14) []
i15 = int_ge(i1, 20)
- guard_true(i15) []
+ guard_true(i15) []
jump(i1)
"""
self.optimize_loop(ops, 'Not', expected)
@@ -3818,7 +3854,7 @@
"""
self.optimize_loop(ops, 'Not, Not', expected)
-
+
##class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin):
@@ -3835,7 +3871,7 @@
## jump(1)
## """
## self.optimize_loop(ops, 'Not', expected)
-
+
## def test_instanceof_guard_class(self):
## ops = """
## [i0, p0]
Modified: pypy/branch/fast-forward/pypy/jit/tl/pypyjit_demo.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/tl/pypyjit_demo.py (original)
+++ pypy/branch/fast-forward/pypy/jit/tl/pypyjit_demo.py Mon Sep 20 13:19:51 2010
@@ -39,16 +39,24 @@
try:
from array import array
+
+ def coords(w,h):
+ y = 0
+ while y < h:
+ x = 0
+ while x < w:
+ yield x,y
+ x += 1
+ y += 1
+
def f(img):
- i=0
sa=0
- while i < img.__len__():
- sa+=img[i]
- i+=1
+ for x, y in coords(4,4):
+ sa += x * y
return sa
- img=array('h',(1,2,3,4))
- print f(img)
+ #img=array('h',(1,2,3,4))
+ print f(3)
except Exception, e:
print "Exception: ", type(e)
print e
Modified: pypy/branch/fast-forward/pypy/module/__builtin__/functional.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/__builtin__/functional.py (original)
+++ pypy/branch/fast-forward/pypy/module/__builtin__/functional.py Mon Sep 20 13:19:51 2010
@@ -13,6 +13,7 @@
from pypy.rlib.objectmodel import specialize
from pypy.module.__builtin__.app_functional import range as app_range
from inspect import getsource, getfile
+from pypy.rlib.jit import unroll_safe
"""
Implementation of the common integer case of range. Instead of handling
@@ -96,12 +97,32 @@
return W_RangeListObject(start, step, howmany)
+ at unroll_safe
@specialize.arg(2)
def min_max(space, args, implementation_of):
if implementation_of == "max":
compare = space.gt
else:
compare = space.lt
+
+ args_w = args.arguments_w
+ if len(args_w) == 2 and not args.keywords:
+ # Unrollable case
+ w_max_item = None
+ for w_item in args_w:
+ if w_max_item is None or \
+ space.is_true(compare(w_item, w_max_item)):
+ w_max_item = w_item
+ return w_max_item
+ else:
+ return min_max_loop(space, args, implementation_of)
+
+ at specialize.arg(2)
+def min_max_loop(space, args, implementation_of):
+ if implementation_of == "max":
+ compare = space.gt
+ else:
+ compare = space.lt
args_w = args.arguments_w
if len(args_w) > 1:
w_sequence = space.newtuple(args_w)
Modified: pypy/branch/fast-forward/pypy/module/__builtin__/test/test_minmax.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/__builtin__/test/test_minmax.py (original)
+++ pypy/branch/fast-forward/pypy/module/__builtin__/test/test_minmax.py Mon Sep 20 13:19:51 2010
@@ -51,3 +51,37 @@
def test_max_empty(self):
raises(ValueError, max, [])
+
+class AppTestMaxTuple:
+
+ def test_max_usual(self):
+ assert max((1, 2, 3)) == 3
+
+ def test_max_floats(self):
+ assert max((0.1, 2.7, 14.7)) == 14.7
+
+ def test_max_chars(self):
+ assert max(('a', 'b', 'c')) == 'c'
+
+ def test_max_strings(self):
+ assert max(('aaa', 'bbb', 'c')) == 'c'
+
+ def test_max_mixed(self):
+ assert max(('1', 2, 3, 'aa')) == 'aa'
+
+class AppTestMinList:
+
+ def test_min_usual(self):
+ assert min([1, 2, 3]) == 1
+
+ def test_min_floats(self):
+ assert min([0.1, 2.7, 14.7]) == 0.1
+
+ def test_min_chars(self):
+ assert min(['a', 'b', 'c']) == 'a'
+
+ def test_min_strings(self):
+ assert min(['aaa', 'bbb', 'c']) == 'aaa'
+
+ def test_min_mixed(self):
+ assert min(['1', 2, 3, 'aa']) == 2
Modified: pypy/branch/fast-forward/pypy/module/_ssl/test/test_ssl.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_ssl/test/test_ssl.py (original)
+++ pypy/branch/fast-forward/pypy/module/_ssl/test/test_ssl.py Mon Sep 20 13:19:51 2010
@@ -60,8 +60,8 @@
cls.space = space
def setup_method(self, method):
- # https://connect.sigen-ca.si/index-en.html
- ADDR = "connect.sigen-ca.si", 443
+ # https://codespeak.net/
+ ADDR = "codespeak.net", 443
self.w_s = self.space.appexec([self.space.wrap(ADDR)], """(ADDR):
import socket
Modified: pypy/branch/fast-forward/pypy/module/array/interp_array.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/array/interp_array.py (original)
+++ pypy/branch/fast-forward/pypy/module/array/interp_array.py Mon Sep 20 13:19:51 2010
@@ -528,12 +528,15 @@
def array_tostring__Array(space, self):
cbuf = self.charbuf()
- s = ''
- i = 0
- while i < self.len * mytype.bytes:
- s += cbuf[i]
- i += 1
+ s = ''.join([cbuf[i] for i in xrange(self.len * mytype.bytes)])
return self.space.wrap(s)
+##
+## s = ''
+## i = 0
+## while i < self.len * mytype.bytes:
+## s += cbuf[i]
+## i += 1
+## return self.space.wrap(s)
def array_fromfile__Array_ANY_ANY(space, self, w_f, w_n):
if not isinstance(w_f, W_File):
Modified: pypy/branch/fast-forward/pypy/module/gc/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/gc/__init__.py (original)
+++ pypy/branch/fast-forward/pypy/module/gc/__init__.py Mon Sep 20 13:19:51 2010
@@ -10,13 +10,25 @@
'collect': 'interp_gc.collect',
'enable_finalizers': 'interp_gc.enable_finalizers',
'disable_finalizers': 'interp_gc.disable_finalizers',
- 'estimate_heap_size': 'interp_gc.estimate_heap_size',
'garbage' : 'space.newlist([])',
#'dump_heap_stats': 'interp_gc.dump_heap_stats',
}
def __init__(self, space, w_name):
- ts = space.config.translation.type_system
- if ts == 'ootype':
- del self.interpleveldefs['dump_heap_stats']
+ if (not space.config.translating or
+ space.config.translation.gctransformer == "framework"):
+ self.appleveldefs.update({
+ 'dump_rpy_heap': 'app_referents.dump_rpy_heap',
+ })
+ self.interpleveldefs.update({
+ 'get_rpy_roots': 'referents.get_rpy_roots',
+ 'get_rpy_referents': 'referents.get_rpy_referents',
+ 'get_rpy_memory_usage': 'referents.get_rpy_memory_usage',
+ 'get_rpy_type_index': 'referents.get_rpy_type_index',
+ 'get_objects': 'referents.get_objects',
+ 'get_referents': 'referents.get_referents',
+ 'get_referrers': 'referents.get_referrers',
+ '_dump_rpy_heap': 'referents._dump_rpy_heap',
+ 'GcRef': 'referents.W_GcRef',
+ })
MixedModule.__init__(self, space, w_name)
Modified: pypy/branch/fast-forward/pypy/module/gc/interp_gc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/gc/interp_gc.py (original)
+++ pypy/branch/fast-forward/pypy/module/gc/interp_gc.py Mon Sep 20 13:19:51 2010
@@ -24,36 +24,6 @@
# ____________________________________________________________
-import sys
-platform = sys.platform
-
-def estimate_heap_size(space):
- # XXX should be done with the help of the GCs
- if platform == "linux2":
- import os
- pid = os.getpid()
- try:
- fd = os.open("/proc/" + str(pid) + "/status", os.O_RDONLY, 0777)
- except OSError:
- pass
- else:
- try:
- content = os.read(fd, 1000000)
- finally:
- os.close(fd)
- lines = content.split("\n")
- for line in lines:
- if line.startswith("VmSize:"):
- start = line.find(" ") # try to ignore tabs
- assert start > 0
- stop = len(line) - 3
- assert stop > 0
- result = int(line[start:stop].strip(" ")) * 1024
- return space.wrap(result)
- raise OperationError(space.w_RuntimeError,
- space.wrap("can't estimate the heap size"))
-estimate_heap_size.unwrap_spec = [ObjSpace]
-
def dump_heap_stats(space, filename):
tb = rgc._heap_stats()
if not tb:
Modified: pypy/branch/fast-forward/pypy/module/gc/test/test_gc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/gc/test/test_gc.py (original)
+++ pypy/branch/fast-forward/pypy/module/gc/test/test_gc.py Mon Sep 20 13:19:51 2010
@@ -59,13 +59,6 @@
raises(ValueError, gc.enable_finalizers)
runtest(True)
- def test_estimate_heap_size(self):
- import sys, gc
- if sys.platform == "linux2":
- assert gc.estimate_heap_size() > 1024
- else:
- raises(RuntimeError, gc.estimate_heap_size)
-
def test_enable(self):
import gc
assert gc.isenabled()
Modified: pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py (original)
+++ pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py Mon Sep 20 13:19:51 2010
@@ -762,6 +762,8 @@
else:
n = 215
+ print
+ print 'Test:', e1, e2, n, res
self.run_source('''
class tst:
pass
@@ -779,6 +781,25 @@
return sa
'''%(e1, e2), n, ([], res))
+ def test_boolrewrite_ptr_single(self):
+ self.run_source('''
+ class tst:
+ pass
+ def main():
+ a = tst()
+ b = tst()
+ c = tst()
+ sa = 0
+ for i in range(1000):
+ if a == b: sa += 1
+ else: sa += 2
+ if a != b: sa += 10000
+ else: sa += 20000
+ if i > 750: a = b
+ return sa
+ ''', 215, ([], 12481752))
+ assert False
+
def test_array_sum(self):
for tc, maxops in zip('bhilBHILfd', (38,) * 6 + (40, 40, 41, 38)):
res = 19352859
@@ -1059,7 +1080,38 @@
''', 170, ([], 1239690.0))
-
+ def test_min_max(self):
+ self.run_source('''
+ def main():
+ i=0
+ sa=0
+ while i < 2000:
+ sa+=min(max(i, 3000), 4000)
+ i+=1
+ return sa
+ ''', 51, ([], 2000*3000))
+
+ def test_silly_max(self):
+ self.run_source('''
+ def main():
+ i=2
+ sa=0
+ while i < 2000:
+ sa+=max(*range(i))
+ i+=1
+ return sa
+ ''', 125, ([], 1997001))
+
+ def test_iter_max(self):
+ self.run_source('''
+ def main():
+ i=2
+ sa=0
+ while i < 2000:
+ sa+=max(range(i))
+ i+=1
+ return sa
+ ''', 88, ([], 1997001))
# test_circular
Modified: pypy/branch/fast-forward/pypy/module/select/interp_select.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/select/interp_select.py (original)
+++ pypy/branch/fast-forward/pypy/module/select/interp_select.py Mon Sep 20 13:19:51 2010
@@ -54,14 +54,11 @@
if space.is_w(w_timeout, space.w_None):
timeout = -1
else:
- # rationale for computing directly integer, instead
- # of float + math.cell is that
- # we have for free overflow check and noone really
- # cares (since CPython does not try too hard to have
- # a ceiling of value)
+ # we want to be compatible with cpython and also accept things
+ # that can be casted to integer (I think)
try:
# compute the integer
- timeout = space.int_w(w_timeout)
+ timeout = space.int_w(space.int(w_timeout))
except (OverflowError, ValueError):
raise OperationError(space.w_ValueError,
space.wrap("math range error"))
Modified: pypy/branch/fast-forward/pypy/module/select/test/test_select.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/select/test/test_select.py (original)
+++ pypy/branch/fast-forward/pypy/module/select/test/test_select.py Mon Sep 20 13:19:51 2010
@@ -210,6 +210,14 @@
assert len(res[2]) == 0
assert res[0][0] == res[1][0]
+ def test_poll(self):
+ import select
+ class A(object):
+ def __int__(self):
+ return 3
+
+ select.poll().poll(A()) # assert did not crash
+
class AppTestSelectWithPipes(_AppTestSelect):
"Use a pipe to get pairs of file descriptors"
def setup_class(cls):
@@ -275,4 +283,3 @@
s1, addr2 = cls.sock.accept()
return s1, s2
-
Modified: pypy/branch/fast-forward/pypy/module/sys/version.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/sys/version.py (original)
+++ pypy/branch/fast-forward/pypy/module/sys/version.py Mon Sep 20 13:19:51 2010
@@ -4,10 +4,11 @@
import os
-CPYTHON_VERSION = (2, 7, 0, "final", 42)
-CPYTHON_API_VERSION = 1012
+#XXX # the release serial 42 is not in range(16)
+CPYTHON_VERSION = (2, 7, 0, "final", 42) #XXX # sync patchlevel.h
+CPYTHON_API_VERSION = 1012 #XXX # sync with include/modsupport.h
-PYPY_VERSION = (1, 3, 0, "beta", '?')
+PYPY_VERSION = (1, 3, 0, "beta", '?') #XXX # sync patchlevel.h
# the last item is replaced by the svn revision ^^^
TRIM_URL_UP_TO = 'svn/pypy/'
Modified: pypy/branch/fast-forward/pypy/rlib/_rsocket_rffi.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/_rsocket_rffi.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/_rsocket_rffi.py Mon Sep 20 13:19:51 2010
@@ -32,11 +32,13 @@
'arpa/inet.h',
'stdint.h',
'errno.h',
- 'netpacket/packet.h',
- 'sys/ioctl.h',
- 'net/if.h',
)
- cond_includes = [('AF_NETLINK', 'linux/netlink.h')]
+
+ cond_includes = [('AF_NETLINK', 'linux/netlink.h'),
+ ('AF_PACKET', 'netpacket/packet.h'),
+ ('AF_PACKET', 'sys/ioctl.h'),
+ ('AF_PACKET', 'net/if.h')]
+
libraries = ()
calling_conv = 'c'
HEADER = ''.join(['#include <%s>\n' % filename for filename in includes])
Modified: pypy/branch/fast-forward/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rarithmetic.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/rarithmetic.py Mon Sep 20 13:19:51 2010
@@ -50,6 +50,11 @@
LONG_MASK = _Ltest*2-1
LONG_TEST = _Ltest
+LONG_BIT_SHIFT = 0
+while (1 << LONG_BIT_SHIFT) != LONG_BIT:
+ LONG_BIT_SHIFT += 1
+ assert LONG_BIT_SHIFT < 99, "LONG_BIT_SHIFT value not found?"
+
INFINITY = 1e200 * 1e200
NAN = INFINITY / INFINITY
Modified: pypy/branch/fast-forward/pypy/rlib/rgc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rgc.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/rgc.py Mon Sep 20 13:19:51 2010
@@ -1,6 +1,7 @@
-import gc
+import gc, types
from pypy.rpython.extregistry import ExtRegistryEntry
from pypy.rlib.objectmodel import we_are_translated
+from pypy.rpython.lltypesystem import lltype, llmemory
# ____________________________________________________________
# General GC features
@@ -93,7 +94,7 @@
def specialize_call(self, hop):
from pypy.rpython.error import TyperError
- from pypy.rpython.lltypesystem import lltype, llmemory, rtuple
+ from pypy.rpython.lltypesystem import rtuple
from pypy.annotation import model as annmodel
from pypy.rpython.memory.gc.marksweep import X_CLONE, X_CLONE_PTR
@@ -150,7 +151,6 @@
return annmodel.s_None
def specialize_call(self, hop):
- from pypy.rpython.lltypesystem import lltype
hop.exception_cannot_occur()
args_v = []
if len(hop.args_s) == 1:
@@ -165,7 +165,6 @@
return annmodel.s_None
def specialize_call(self, hop):
- from pypy.rpython.lltypesystem import lltype
[v_nbytes] = hop.inputargs(lltype.Signed)
hop.exception_cannot_occur()
return hop.genop('gc_set_max_heap_size', [v_nbytes],
@@ -182,7 +181,6 @@
return annmodel.SomeBool()
def specialize_call(self, hop):
- from pypy.rpython.lltypesystem import lltype
hop.exception_cannot_occur()
return hop.genop('gc_can_move', hop.args_v, resulttype=hop.r_result)
@@ -195,11 +193,9 @@
def compute_result_annotation(self):
from pypy.annotation import model as annmodel
from pypy.rpython.memory.gc.base import ARRAY_TYPEID_MAP
- from pypy.rpython.lltypesystem import lltype
return annmodel.SomePtr(lltype.Ptr(ARRAY_TYPEID_MAP))
def specialize_call(self, hop):
- from pypy.rpython.lltypesystem import lltype
from pypy.rpython.memory.gc.base import ARRAY_TYPEID_MAP
hop.exception_is_here()
return hop.genop('gc_heap_stats', [], resulttype=hop.r_result)
@@ -209,7 +205,6 @@
When running directly, will pretend that gc is always
moving (might be configurable in a future)
"""
- from pypy.rpython.lltypesystem import lltype
return lltype.nullptr(TP)
class MallocNonMovingEntry(ExtRegistryEntry):
@@ -221,7 +216,6 @@
return malloc(s_TP, s_n, s_zero=s_zero)
def specialize_call(self, hop, i_zero=None):
- from pypy.rpython.lltypesystem import lltype
# XXX assume flavor and zero to be None by now
assert hop.args_s[0].is_constant()
vlist = [hop.inputarg(lltype.Void, arg=0)]
@@ -243,7 +237,6 @@
def ll_arraycopy(source, dest, source_start, dest_start, length):
from pypy.rpython.lltypesystem.lloperation import llop
- from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rlib.objectmodel import keepalive_until_here
# supports non-overlapping copies only
@@ -279,7 +272,6 @@
def ll_shrink_array(p, smallerlength):
from pypy.rpython.lltypesystem.lloperation import llop
- from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rlib.objectmodel import keepalive_until_here
if llop.shrink_array(lltype.Bool, p, smallerlength):
@@ -313,3 +305,221 @@
func._dont_inline_ = True
func._gc_no_collect_ = True
return func
+
+# ____________________________________________________________
+
+def get_rpy_roots():
+ "NOT_RPYTHON"
+ # Return the 'roots' from the GC.
+ # This stub is not usable on top of CPython.
+ # The gc typically returns a list that ends with a few NULL_GCREFs.
+ raise NotImplementedError
+
+def get_rpy_referents(gcref):
+ "NOT_RPYTHON"
+ x = gcref._x
+ if isinstance(x, list):
+ d = x
+ elif isinstance(x, dict):
+ d = x.keys() + x.values()
+ else:
+ d = []
+ if hasattr(x, '__dict__'):
+ d = x.__dict__.values()
+ if hasattr(type(x), '__slots__'):
+ for slot in type(x).__slots__:
+ try:
+ d.append(getattr(x, slot))
+ except AttributeError:
+ pass
+ # discard objects that are too random or that are _freeze_=True
+ return [_GcRef(x) for x in d if _keep_object(x)]
+
+def _keep_object(x):
+ if isinstance(x, type) or type(x) is types.ClassType:
+ return False # don't keep any type
+ if isinstance(x, (list, dict, str)):
+ return True # keep lists and dicts and strings
+ try:
+ return not x._freeze_() # don't keep any frozen object
+ except AttributeError:
+ return type(x).__module__ != '__builtin__' # keep non-builtins
+ except Exception:
+ return False # don't keep objects whose _freeze_() method explodes
+
+def get_rpy_memory_usage(gcref):
+ "NOT_RPYTHON"
+ # approximate implementation using CPython's type info
+ Class = type(gcref._x)
+ size = Class.__basicsize__
+ if Class.__itemsize__ > 0:
+ size += Class.__itemsize__ * len(gcref._x)
+ return size
+
+def get_rpy_type_index(gcref):
+ "NOT_RPYTHON"
+ from pypy.rlib.rarithmetic import intmask
+ Class = gcref._x.__class__
+ return intmask(id(Class))
+
+def cast_gcref_to_int(gcref):
+ if we_are_translated():
+ return lltype.cast_ptr_to_int(gcref)
+ else:
+ return id(gcref._x)
+
+def dump_rpy_heap(fd):
+ "NOT_RPYTHON"
+ raise NotImplementedError
+
+NULL_GCREF = lltype.nullptr(llmemory.GCREF.TO)
+
+class _GcRef(object):
+ # implementation-specific: there should not be any after translation
+ __slots__ = ['_x']
+ def __init__(self, x):
+ self._x = x
+ def __hash__(self):
+ return object.__hash__(self._x)
+ def __eq__(self, other):
+ if isinstance(other, lltype._ptr):
+ assert other == NULL_GCREF, (
+ "comparing a _GcRef with a non-NULL lltype ptr")
+ return False
+ assert isinstance(other, _GcRef)
+ return self._x is other._x
+ def __ne__(self, other):
+ return not self.__eq__(other)
+ def __repr__(self):
+ return "_GcRef(%r)" % (self._x, )
+ def _freeze_(self):
+ raise Exception("instances of rlib.rgc._GcRef cannot be translated")
+
+def cast_instance_to_gcref(x):
+ # Before translation, casts an RPython instance into a _GcRef.
+ # After translation, it is a variant of cast_object_to_ptr(GCREF).
+ if we_are_translated():
+ from pypy.rpython import annlowlevel
+ x = annlowlevel.cast_instance_to_base_ptr(x)
+ return lltype.cast_opaque_ptr(llmemory.GCREF, x)
+ else:
+ return _GcRef(x)
+cast_instance_to_gcref._annspecialcase_ = 'specialize:argtype(0)'
+
+def try_cast_gcref_to_instance(Class, gcref):
+ # Before translation, unwraps the RPython instance contained in a _GcRef.
+ # After translation, it is a type-check performed by the GC.
+ if we_are_translated():
+ from pypy.rpython.annlowlevel import base_ptr_lltype
+ from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+ from pypy.rpython.lltypesystem import rclass
+ if _is_rpy_instance(gcref):
+ objptr = lltype.cast_opaque_ptr(base_ptr_lltype(), gcref)
+ if objptr.typeptr: # may be NULL, e.g. in rdict's dummykeyobj
+ clsptr = _get_llcls_from_cls(Class)
+ if rclass.ll_isinstance(objptr, clsptr):
+ return cast_base_ptr_to_instance(Class, objptr)
+ return None
+ else:
+ if isinstance(gcref._x, Class):
+ return gcref._x
+ return None
+try_cast_gcref_to_instance._annspecialcase_ = 'specialize:arg(0)'
+
+# ------------------- implementation -------------------
+
+_cache_s_list_of_gcrefs = None
+
+def s_list_of_gcrefs():
+ global _cache_s_list_of_gcrefs
+ if _cache_s_list_of_gcrefs is None:
+ from pypy.annotation import model as annmodel
+ from pypy.annotation.listdef import ListDef
+ s_gcref = annmodel.SomePtr(llmemory.GCREF)
+ _cache_s_list_of_gcrefs = annmodel.SomeList(
+ ListDef(None, s_gcref, mutated=True, resized=False))
+ return _cache_s_list_of_gcrefs
+
+class Entry(ExtRegistryEntry):
+ _about_ = get_rpy_roots
+ def compute_result_annotation(self):
+ return s_list_of_gcrefs()
+ def specialize_call(self, hop):
+ return hop.genop('gc_get_rpy_roots', [], resulttype = hop.r_result)
+
+class Entry(ExtRegistryEntry):
+ _about_ = get_rpy_referents
+ def compute_result_annotation(self, s_gcref):
+ from pypy.annotation import model as annmodel
+ assert annmodel.SomePtr(llmemory.GCREF).contains(s_gcref)
+ return s_list_of_gcrefs()
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(hop.args_r[0])
+ return hop.genop('gc_get_rpy_referents', vlist,
+ resulttype = hop.r_result)
+
+class Entry(ExtRegistryEntry):
+ _about_ = get_rpy_memory_usage
+ def compute_result_annotation(self, s_gcref):
+ from pypy.annotation import model as annmodel
+ return annmodel.SomeInteger()
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(hop.args_r[0])
+ return hop.genop('gc_get_rpy_memory_usage', vlist,
+ resulttype = hop.r_result)
+
+class Entry(ExtRegistryEntry):
+ _about_ = get_rpy_type_index
+ def compute_result_annotation(self, s_gcref):
+ from pypy.annotation import model as annmodel
+ return annmodel.SomeInteger()
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(hop.args_r[0])
+ return hop.genop('gc_get_rpy_type_index', vlist,
+ resulttype = hop.r_result)
+
+def _is_rpy_instance(gcref):
+ "NOT_RPYTHON"
+ raise NotImplementedError
+
+def _get_llcls_from_cls(Class):
+ "NOT_RPYTHON"
+ raise NotImplementedError
+
+class Entry(ExtRegistryEntry):
+ _about_ = _is_rpy_instance
+ def compute_result_annotation(self, s_gcref):
+ from pypy.annotation import model as annmodel
+ return annmodel.SomeBool()
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(hop.args_r[0])
+ return hop.genop('gc_is_rpy_instance', vlist,
+ resulttype = hop.r_result)
+
+class Entry(ExtRegistryEntry):
+ _about_ = _get_llcls_from_cls
+ def compute_result_annotation(self, s_Class):
+ from pypy.annotation import model as annmodel
+ from pypy.rpython.lltypesystem import rclass
+ assert s_Class.is_constant()
+ return annmodel.SomePtr(rclass.CLASSTYPE)
+ def specialize_call(self, hop):
+ from pypy.rpython.rclass import getclassrepr
+ from pypy.objspace.flow.model import Constant
+ from pypy.rpython.lltypesystem import rclass
+ Class = hop.args_s[0].const
+ classdef = hop.rtyper.annotator.bookkeeper.getuniqueclassdef(Class)
+ classrepr = getclassrepr(hop.rtyper, classdef)
+ vtable = classrepr.getvtable()
+ assert lltype.typeOf(vtable) == rclass.CLASSTYPE
+ return Constant(vtable, concretetype=rclass.CLASSTYPE)
+
+class Entry(ExtRegistryEntry):
+ _about_ = dump_rpy_heap
+ def compute_result_annotation(self, s_fd):
+ from pypy.annotation.model import s_Bool
+ return s_Bool
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(lltype.Signed)
+ hop.exception_is_here()
+ return hop.genop('gc_dump_rpy_heap', vlist, resulttype = hop.r_result)
Modified: pypy/branch/fast-forward/pypy/rlib/rstring.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rstring.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/rstring.py Mon Sep 20 13:19:51 2010
@@ -46,7 +46,9 @@
# -------------- public API ---------------------------------
-INIT_SIZE = 100 # XXX tweak
+# the following number is the maximum size of an RPython unicode
+# string that goes into the nursery of the minimark GC.
+INIT_SIZE = 56
class AbstractStringBuilder(object):
def __init__(self, init_size=INIT_SIZE):
Modified: pypy/branch/fast-forward/pypy/rlib/rwin32.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rwin32.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/rwin32.py Mon Sep 20 13:19:51 2010
@@ -82,6 +82,8 @@
if WIN32:
HANDLE = rffi.COpaquePtr(typedef='HANDLE')
+ assert rffi.cast(HANDLE, -1) == rffi.cast(HANDLE, -1)
+
LPHANDLE = rffi.CArrayPtr(HANDLE)
HMODULE = HANDLE
NULL_HANDLE = rffi.cast(HANDLE, 0)
Modified: pypy/branch/fast-forward/pypy/rlib/test/test_rgc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/test/test_rgc.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/test/test_rgc.py Mon Sep 20 13:19:51 2010
@@ -16,7 +16,7 @@
assert len(op.args) == 0
res = interpret(f, [])
-
+
assert res is None
def test_collect_0():
@@ -31,13 +31,13 @@
assert len(ops) == 1
op = ops[0][1]
assert op.opname == 'gc__collect'
- assert len(op.args) == 1
+ assert len(op.args) == 1
assert op.args[0].value == 0
res = interpret(f, [])
-
- assert res is None
-
+
+ assert res is None
+
def test_can_move():
T0 = lltype.GcStruct('T')
T1 = lltype.GcArray(lltype.Float)
@@ -53,9 +53,9 @@
assert len(res) == 2
res = interpret(f, [1])
-
+
assert res == True
-
+
def test_ll_arraycopy_1():
TYPE = lltype.GcArray(lltype.Signed)
a1 = lltype.malloc(TYPE, 10)
@@ -153,3 +153,21 @@
assert len(s2.vars) == 3
for i in range(3):
assert s2.vars[i] == 50 + i
+
+def test_get_referents():
+ class X(object):
+ __slots__ = ['stuff']
+ x1 = X()
+ x1.stuff = X()
+ x2 = X()
+ lst = rgc.get_rpy_referents(rgc.cast_instance_to_gcref(x1))
+ lst2 = [rgc.try_cast_gcref_to_instance(X, x) for x in lst]
+ assert x1.stuff in lst2
+ assert x2 not in lst2
+
+def test_get_memory_usage():
+ class X(object):
+ pass
+ x1 = X()
+ n = rgc.get_rpy_memory_usage(rgc.cast_instance_to_gcref(x1))
+ assert n >= 8 and n <= 64
Modified: pypy/branch/fast-forward/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/llinterp.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/llinterp.py Mon Sep 20 13:19:51 2010
@@ -650,7 +650,7 @@
offsets, fieldvalue = fieldnamesval[:-1], fieldnamesval[-1]
inneraddr, FIELD = self.getinneraddr(obj, *offsets)
if FIELD is not lltype.Void:
- self.heap.setinterior(obj, inneraddr, FIELD, fieldvalue)
+ self.heap.setinterior(obj, inneraddr, FIELD, fieldvalue, offsets)
def op_bare_setinteriorfield(self, obj, *fieldnamesval):
offsets, fieldvalue = fieldnamesval[:-1], fieldnamesval[-1]
@@ -916,6 +916,24 @@
def op_gc_get_type_info_group(self):
raise NotImplementedError("gc_get_type_info_group")
+ def op_gc_get_rpy_memory_usage(self):
+ raise NotImplementedError("gc_get_rpy_memory_usage")
+
+ def op_gc_get_rpy_roots(self):
+ raise NotImplementedError("gc_get_rpy_roots")
+
+ def op_gc_get_rpy_referents(self):
+ raise NotImplementedError("gc_get_rpy_referents")
+
+ def op_gc_is_rpy_instance(self):
+ raise NotImplementedError("gc_is_rpy_instance")
+
+ def op_gc_get_rpy_type_index(self):
+ raise NotImplementedError("gc_get_rpy_type_index")
+
+ def op_gc_dump_rpy_heap(self):
+ raise NotImplementedError("gc_dump_rpy_heap")
+
def op_do_malloc_fixedsize_clear(self):
raise NotImplementedError("do_malloc_fixedsize_clear")
@@ -925,6 +943,9 @@
def op_get_write_barrier_failing_case(self):
raise NotImplementedError("get_write_barrier_failing_case")
+ def op_get_write_barrier_from_array_failing_case(self):
+ raise NotImplementedError("get_write_barrier_from_array_failing_case")
+
def op_yield_current_frame_to_caller(self):
raise NotImplementedError("yield_current_frame_to_caller")
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py Mon Sep 20 13:19:51 2010
@@ -26,9 +26,6 @@
from pypy.translator.platform import platform
from array import array
-def uaddressof(obj):
- return fixid(ctypes.addressof(obj))
-
_ctypes_cache = {}
_eci_cache = {}
@@ -251,7 +248,7 @@
else:
n = None
cstruct = cls._malloc(n)
- add_storage(container, _struct_mixin, cstruct)
+ add_storage(container, _struct_mixin, ctypes.pointer(cstruct))
for field_name in STRUCT._names:
FIELDTYPE = getattr(STRUCT, field_name)
field_value = getattr(container, field_name)
@@ -264,8 +261,6 @@
if isinstance(FIELDTYPE, lltype.Struct):
csubstruct = getattr(cstruct, field_name)
convert_struct(field_value, csubstruct)
- subcontainer = getattr(container, field_name)
- substorage = subcontainer._storage
elif field_name == STRUCT._arrayfld: # inlined var-sized part
csubarray = getattr(cstruct, field_name)
convert_array(field_value, csubarray)
@@ -292,7 +287,7 @@
# regular case: allocate a new ctypes array of the proper type
cls = get_ctypes_type(ARRAY)
carray = cls._malloc(container.getlength())
- add_storage(container, _array_mixin, carray)
+ add_storage(container, _array_mixin, ctypes.pointer(carray))
if not isinstance(ARRAY.OF, lltype.ContainerType):
# fish that we have enough space
ctypes_array = ctypes.cast(carray.items,
@@ -321,13 +316,15 @@
if isinstance(FIELDTYPE, lltype.ContainerType):
if isinstance(FIELDTYPE, lltype.Struct):
struct_container = getattr(container, field_name)
- struct_storage = getattr(ctypes_storage, field_name)
+ struct_storage = ctypes.pointer(
+ getattr(ctypes_storage.contents, field_name))
struct_use_ctypes_storage(struct_container, struct_storage)
struct_container._setparentstructure(container, field_name)
elif isinstance(FIELDTYPE, lltype.Array):
assert FIELDTYPE._hints.get('nolength', False) == False
arraycontainer = _array_of_known_length(FIELDTYPE)
- arraycontainer._storage = getattr(ctypes_storage, field_name)
+ arraycontainer._storage = ctypes.pointer(
+ getattr(ctypes_storage.contents, field_name))
arraycontainer._setparentstructure(container, field_name)
object.__setattr__(container, field_name, arraycontainer)
else:
@@ -352,6 +349,8 @@
def add_storage(instance, mixin_cls, ctypes_storage):
"""Put ctypes_storage on the instance, changing its __class__ so that it
sees the methods of the given mixin class."""
+ # _storage is a ctypes pointer to a structure
+ # except for Opaque objects which use a c_void_p.
assert not isinstance(instance, _parentable_mixin) # not yet
subcls = get_common_subclass(mixin_cls, instance.__class__)
instance.__class__ = subcls
@@ -365,17 +364,23 @@
__slots__ = ()
def _ctypes_storage_was_allocated(self):
- addr = ctypes.addressof(self._storage)
+ addr = ctypes.cast(self._storage, ctypes.c_void_p).value
if addr in ALLOCATED:
raise Exception("internal ll2ctypes error - "
"double conversion from lltype to ctypes?")
# XXX don't store here immortal structures
ALLOCATED[addr] = self
+ def _addressof_storage(self):
+ "Returns the storage address as an int"
+ if self._storage is None or self._storage is True:
+ raise ValueError("Not a ctypes allocated structure")
+ return ctypes.cast(self._storage, ctypes.c_void_p).value
+
def _free(self):
self._check() # no double-frees
# allow the ctypes object to go away now
- addr = ctypes.addressof(self._storage)
+ addr = ctypes.cast(self._storage, ctypes.c_void_p).value
try:
del ALLOCATED[addr]
except KeyError:
@@ -393,16 +398,16 @@
raise RuntimeError("pointer comparison with a freed structure")
if other._storage is True:
return False # the other container is not ctypes-based
- addressof_other = ctypes.addressof(other._storage)
- # both containers are ctypes-based, compare by address
- return (ctypes.addressof(self._storage) == addressof_other)
+ addressof_other = other._addressof_storage()
+ # both containers are ctypes-based, compare the addresses
+ return self._addressof_storage() == addressof_other
def __ne__(self, other):
return not (self == other)
def __hash__(self):
if self._storage is not None:
- return ctypes.addressof(self._storage)
+ return self._addressof_storage()
else:
return object.__hash__(self)
@@ -411,7 +416,7 @@
return '<freed C object %s>' % (self._TYPE,)
else:
return '<C object %s at 0x%x>' % (self._TYPE,
- uaddressof(self._storage),)
+ fixid(self._addressof_storage()))
def __str__(self):
return repr(self)
@@ -422,7 +427,7 @@
def __getattr__(self, field_name):
T = getattr(self._TYPE, field_name)
- cobj = getattr(self._storage, field_name)
+ cobj = getattr(self._storage.contents, field_name)
return ctypes2lltype(T, cobj)
def __setattr__(self, field_name, value):
@@ -430,17 +435,17 @@
object.__setattr__(self, field_name, value) # '_xxx' attributes
else:
cobj = lltype2ctypes(value)
- setattr(self._storage, field_name, cobj)
+ setattr(self._storage.contents, field_name, cobj)
class _array_mixin(_parentable_mixin):
"""Mixin added to _array containers when they become ctypes-based."""
__slots__ = ()
def getitem(self, index, uninitialized_ok=False):
- return self._storage._getitem(index)
+ return self._storage.contents._getitem(index)
def setitem(self, index, value):
- self._storage._setitem(index, value)
+ self._storage.contents._setitem(index, value)
class _array_of_unknown_length(_parentable_mixin, lltype._parentable):
_kind = "array"
@@ -451,10 +456,10 @@
return 0, sys.maxint
def getitem(self, index, uninitialized_ok=False):
- return self._storage._getitem(index, boundscheck=False)
+ return self._storage.contents._getitem(index, boundscheck=False)
def setitem(self, index, value):
- self._storage._setitem(index, value, boundscheck=False)
+ self._storage.contents._setitem(index, value, boundscheck=False)
def getitems(self):
if self._TYPE.OF != lltype.Char:
@@ -476,7 +481,7 @@
__slots__ = ()
def getlength(self):
- return self._storage.length
+ return self._storage.contents.length
def getbounds(self):
return 0, self.getlength()
@@ -653,17 +658,18 @@
container._ctypes_storage_was_allocated()
if isinstance(T.TO, lltype.OpaqueType):
- return container._storage
+ return container._storage.value
storage = container._storage
- p = ctypes.pointer(storage)
+ p = storage
if index:
p = ctypes.cast(p, ctypes.c_void_p)
p = ctypes.c_void_p(p.value + index)
c_tp = get_ctypes_type(T.TO)
- storage._normalized_ctype = c_tp
- if normalize and hasattr(storage, '_normalized_ctype'):
- p = ctypes.cast(p, ctypes.POINTER(storage._normalized_ctype))
+ storage.contents._normalized_ctype = c_tp
+ if normalize and hasattr(storage.contents, '_normalized_ctype'):
+ normalized_ctype = storage.contents._normalized_ctype
+ p = ctypes.cast(p, ctypes.POINTER(normalized_ctype))
if lltype.typeOf(llobj) == llmemory.GCREF:
p = ctypes.cast(p, ctypes.c_void_p)
return p
@@ -707,13 +713,13 @@
cobjheader = ctypes.cast(cobj,
get_ctypes_type(lltype.Ptr(OBJECT)))
struct_use_ctypes_storage(containerheader,
- cobjheader.contents)
+ cobjheader)
REAL_TYPE = get_rtyper().get_type_for_typeptr(
containerheader.typeptr)
REAL_T = lltype.Ptr(REAL_TYPE)
cobj = ctypes.cast(cobj, get_ctypes_type(REAL_T))
container = lltype._struct(REAL_TYPE)
- struct_use_ctypes_storage(container, cobj.contents)
+ struct_use_ctypes_storage(container, cobj)
if REAL_TYPE != T.TO:
p = container._as_ptr()
container = lltype.cast_pointer(T, p)._as_obj()
@@ -728,10 +734,10 @@
elif isinstance(T.TO, lltype.Array):
if T.TO._hints.get('nolength', False):
container = _array_of_unknown_length(T.TO)
- container._storage = cobj.contents
+ container._storage = cobj
else:
container = _array_of_known_length(T.TO)
- container._storage = cobj.contents
+ container._storage = cobj
elif isinstance(T.TO, lltype.FuncType):
cobjkey = intmask(ctypes.cast(cobj, ctypes.c_void_p).value)
if cobjkey in _int2obj:
@@ -745,7 +751,8 @@
container = _llgcopaque(cobj)
else:
container = lltype._opaque(T.TO)
- container._storage = ctypes.cast(cobj, ctypes.c_void_p)
+ cbuf = ctypes.cast(cobj, ctypes.c_void_p)
+ add_storage(container, _parentable_mixin, cbuf)
else:
raise NotImplementedError(T)
llobj = lltype._ptr(T, container, solid=True)
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/llarena.py Mon Sep 20 13:19:51 2010
@@ -16,8 +16,11 @@
class Arena(object):
object_arena_location = {} # {container: (arena, offset)}
old_object_arena_location = weakref.WeakKeyDictionary()
+ _count_arenas = 0
def __init__(self, nbytes, zero):
+ Arena._count_arenas += 1
+ self._arena_index = Arena._count_arenas
self.nbytes = nbytes
self.usagemap = array.array('c')
self.objectptrs = {} # {offset: ptr-to-container}
@@ -25,6 +28,9 @@
self.freed = False
self.reset(zero)
+ def __repr__(self):
+ return '<Arena #%d [%d bytes]>' % (self._arena_index, self.nbytes)
+
def reset(self, zero, start=0, size=None):
self.check()
if size is None:
@@ -40,7 +46,7 @@
assert offset >= stop, "object overlaps cleared area"
else:
obj = ptr._obj
- del Arena.object_arena_location[obj]
+ _dictdel(Arena.object_arena_location, obj)
del self.objectptrs[offset]
del self.objectsizes[offset]
obj._free()
@@ -63,7 +69,7 @@
raise ArenaError("Address offset is outside the arena")
return fakearenaaddress(self, offset)
- def allocate_object(self, offset, size):
+ def allocate_object(self, offset, size, letter='x'):
self.check()
bytes = llmemory.raw_malloc_usage(size)
if offset + bytes > self.nbytes:
@@ -78,7 +84,7 @@
raise ArenaError("new object overlaps a previous object")
assert offset not in self.objectptrs
addr2 = size._raw_malloc([], zero=zero)
- pattern = 'X' + 'x'*(bytes-1)
+ pattern = letter.upper() + letter*(bytes-1)
self.usagemap[offset:offset+bytes] = array.array('c', pattern)
self.setobject(addr2, offset, bytes)
# common case: 'size' starts with a GCHeaderOffset. In this case
@@ -252,6 +258,16 @@
raise RuntimeError(msg % (obj,))
return arena.getaddr(offset)
+def _dictdel(d, key):
+ # hack
+ try:
+ del d[key]
+ except KeyError:
+ items = d.items()
+ d.clear()
+ d.update(items)
+ del d[key]
+
class RoundedUpForAllocation(llmemory.AddressOffset):
"""A size that is rounded up in order to preserve alignment of objects
following it. For arenas containing heterogenous objects.
@@ -297,6 +313,7 @@
assert isinstance(arena_addr, fakearenaaddress)
assert arena_addr.offset == 0
arena_addr.arena.reset(False)
+ assert not arena_addr.arena.objectptrs
arena_addr.arena.freed = True
def arena_reset(arena_addr, size, zero):
@@ -317,10 +334,13 @@
this is used to know what type of lltype object to allocate."""
from pypy.rpython.memory.lltypelayout import memory_alignment
addr = getfakearenaaddress(addr)
- if check_alignment and (addr.offset & (memory_alignment-1)) != 0:
+ letter = 'x'
+ if llmemory.raw_malloc_usage(size) == 1:
+ letter = 'b' # for Byte-aligned allocations
+ elif check_alignment and (addr.offset & (memory_alignment-1)) != 0:
raise ArenaError("object at offset %d would not be correctly aligned"
% (addr.offset,))
- addr.arena.allocate_object(addr.offset, size)
+ addr.arena.allocate_object(addr.offset, size, letter)
def arena_shrink_obj(addr, newsize):
""" Mark object as shorter than it was
@@ -357,6 +377,11 @@
# This only works with linux's madvise(), which is really not a memory
# usage hint but a real command. It guarantees that after MADV_DONTNEED
# the pages are cleared again.
+
+ # Note that the trick of the general 'posix' section below, i.e.
+ # reading /dev/zero, does not seem to have the correct effect of
+ # lazily-allocating pages on all Linux systems.
+
from pypy.rpython.tool import rffi_platform
from pypy.translator.tool.cbuild import ExternalCompilationInfo
_eci = ExternalCompilationInfo(includes=['sys/mman.h'])
@@ -459,6 +484,7 @@
sandboxsafe=True)
def llimpl_arena_free(arena_addr):
+ # NB. minimark.py assumes that arena_free() is actually just a raw_free().
llmemory.raw_free(arena_addr)
register_external(arena_free, [llmemory.Address], None, 'll_arena.arena_free',
llimpl=llimpl_arena_free,
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/llheap.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/llheap.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/llheap.py Mon Sep 20 13:19:51 2010
@@ -8,7 +8,8 @@
from pypy.rlib.rgc import collect
from pypy.rlib.rgc import can_move
-def setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue):
+def setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue,
+ offsets=None):
assert typeOf(newvalue) == INNERTYPE
# xxx access the address object's ref() directly for performance
inneraddr.ref()[0] = newvalue
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py Mon Sep 20 13:19:51 2010
@@ -409,6 +409,9 @@
if self.ptr is None:
s = 'NULL'
else:
+ #try:
+ # s = hex(self.ptr._cast_to_int())
+ #except:
s = str(self.ptr)
return '<fakeaddr %s>' % (s,)
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py Mon Sep 20 13:19:51 2010
@@ -438,6 +438,7 @@
'do_malloc_fixedsize_clear':LLOp(canraise=(MemoryError,),canunwindgc=True),
'do_malloc_varsize_clear': LLOp(canraise=(MemoryError,),canunwindgc=True),
'get_write_barrier_failing_case': LLOp(sideeffects=False),
+ 'get_write_barrier_from_array_failing_case': LLOp(sideeffects=False),
'gc_get_type_info_group': LLOp(sideeffects=False),
# __________ GC operations __________
@@ -469,6 +470,13 @@
'gc_writebarrier_before_copy': LLOp(canrun=True),
'gc_heap_stats' : LLOp(canunwindgc=True),
+ 'gc_get_rpy_roots' : LLOp(),
+ 'gc_get_rpy_referents': LLOp(),
+ 'gc_get_rpy_memory_usage': LLOp(),
+ 'gc_get_rpy_type_index': LLOp(),
+ 'gc_is_rpy_instance' : LLOp(),
+ 'gc_dump_rpy_heap' : LLOp(),
+
# ------- JIT & GC interaction, only for some GCs ----------
'gc_adr_of_nursery_free' : LLOp(),
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Mon Sep 20 13:19:51 2010
@@ -353,6 +353,8 @@
assert tmppath.check(file=1)
assert not ALLOCATED # detects memory leaks in the test
+ assert rffi.cast(FILEP, -1) == rffi.cast(FILEP, -1)
+
def test_simple_cast(self):
assert rffi.cast(rffi.SIGNEDCHAR, 0x123456) == 0x56
assert rffi.cast(rffi.SIGNEDCHAR, 0x123481) == -127
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gc/base.py Mon Sep 20 13:19:51 2010
@@ -5,6 +5,7 @@
from pypy.rpython.memory.support import get_address_stack, get_address_deque
from pypy.rpython.memory.support import AddressDict
from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
+from pypy.rlib.rarithmetic import r_uint
TYPEID_MAP = lltype.GcStruct('TYPEID_MAP', ('count', lltype.Signed),
('size', lltype.Signed),
@@ -53,7 +54,8 @@
varsize_offset_to_length,
varsize_offsets_to_gcpointers_in_var_part,
weakpointer_offset,
- member_index):
+ member_index,
+ is_rpython_class):
self.getfinalizer = getfinalizer
self.is_varsize = is_varsize
self.has_gcptr_in_varsize = has_gcptr_in_varsize
@@ -66,6 +68,7 @@
self.varsize_offsets_to_gcpointers_in_var_part = varsize_offsets_to_gcpointers_in_var_part
self.weakpointer_offset = weakpointer_offset
self.member_index = member_index
+ self.is_rpython_class = is_rpython_class
def get_member_index(self, type_id):
return self.member_index(type_id)
@@ -101,6 +104,9 @@
def get_size(self, obj):
return self._get_size_for_typeid(obj, self.get_type_id(obj))
+ def get_size_incl_hash(self, obj):
+ return self.get_size(obj)
+
def malloc(self, typeid, length=0, zero=False):
"""For testing. The interface used by the gctransformer is
the four malloc_[fixed,var]size[_clear]() functions.
@@ -146,7 +152,7 @@
return False
def set_max_heap_size(self, size):
- pass
+ raise NotImplementedError
def x_swap_pool(self, newpool):
return newpool
@@ -194,6 +200,39 @@
length -= 1
trace._annspecialcase_ = 'specialize:arg(2)'
+ def trace_partial(self, obj, start, stop, callback, arg):
+ """Like trace(), but only walk the array part, for indices in
+ range(start, stop). Must only be called if has_gcptr_in_varsize().
+ """
+ length = stop - start
+ typeid = self.get_type_id(obj)
+ if self.is_gcarrayofgcptr(typeid):
+ # a performance shortcut for GcArray(gcptr)
+ item = obj + llmemory.gcarrayofptr_itemsoffset
+ item += llmemory.gcarrayofptr_singleitemoffset * start
+ while length > 0:
+ if self.points_to_valid_gc_object(item):
+ callback(item, arg)
+ item += llmemory.gcarrayofptr_singleitemoffset
+ length -= 1
+ return
+ ll_assert(self.has_gcptr_in_varsize(typeid),
+ "trace_partial() on object without has_gcptr_in_varsize()")
+ item = obj + self.varsize_offset_to_variable_part(typeid)
+ offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
+ itemlength = self.varsize_item_sizes(typeid)
+ item += itemlength * start
+ while length > 0:
+ j = 0
+ while j < len(offsets):
+ itemobj = item + offsets[j]
+ if self.points_to_valid_gc_object(itemobj):
+ callback(itemobj, arg)
+ j += 1
+ item += itemlength
+ length -= 1
+ trace_partial._annspecialcase_ = 'specialize:arg(4)'
+
def points_to_valid_gc_object(self, addr):
return self.is_valid_gc_object(addr.address[0])
@@ -340,6 +379,7 @@
"generation": "generation.GenerationGC",
"hybrid": "hybrid.HybridGC",
"markcompact" : "markcompact.MarkCompactGC",
+ "minimark" : "minimark.MiniMarkGC",
}
try:
modulename, classname = classes[config.translation.gc].split('.')
@@ -351,10 +391,12 @@
GCClass = getattr(module, classname)
return GCClass, GCClass.TRANSLATION_PARAMS
-def read_from_env(varname):
+def _read_float_and_factor_from_env(varname):
import os
value = os.environ.get(varname)
if value:
+ if len(value) > 1 and value[-1] in 'bB':
+ value = value[:-1]
realvalue = value[:-1]
if value[-1] in 'kK':
factor = 1024
@@ -366,7 +408,21 @@
factor = 1
realvalue = value
try:
- return int(float(realvalue) * factor)
+ return (float(realvalue), factor)
except ValueError:
pass
- return -1
+ return (0.0, 0)
+
+def read_from_env(varname):
+ value, factor = _read_float_and_factor_from_env(varname)
+ return int(value * factor)
+
+def read_uint_from_env(varname):
+ value, factor = _read_float_and_factor_from_env(varname)
+ return r_uint(value * factor)
+
+def read_float_from_env(varname):
+ value, factor = _read_float_and_factor_from_env(varname)
+ if factor != 1:
+ return 0.0
+ return value
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gc/generation.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gc/generation.py Mon Sep 20 13:19:51 2010
@@ -449,7 +449,7 @@
# for the JIT: a minimal description of the write_barrier() method
# (the JIT assumes it is of the shape
- # "if newvalue.int0 & JIT_WB_IF_FLAG: remember_young_pointer()")
+ # "if addr_struct.int0 & JIT_WB_IF_FLAG: remember_young_pointer()")
JIT_WB_IF_FLAG = GCFLAG_NO_YOUNG_PTRS
def write_barrier(self, newvalue, addr_struct):
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gc/markcompact.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gc/markcompact.py Mon Sep 20 13:19:51 2010
@@ -674,6 +674,13 @@
return llmemory.cast_adr_to_int(obj) # not in an arena...
return adr - self.space
+ def get_size_incl_hash(self, obj):
+ size = self.get_size(obj)
+ hdr = self.header(obj)
+ if hdr.tid & GCFLAG_HASHFIELD:
+ size += llmemory.sizeof(lltype.Signed)
+ return size
+
# ____________________________________________________________
class CannotAllocateGCArena(Exception):
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_direct.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_direct.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_direct.py Mon Sep 20 13:19:51 2010
@@ -95,7 +95,10 @@
if self.gc.needs_write_barrier:
newaddr = llmemory.cast_ptr_to_adr(newvalue)
addr_struct = llmemory.cast_ptr_to_adr(p)
- self.gc.write_barrier(newaddr, addr_struct)
+ if hasattr(self.gc, 'write_barrier_from_array'):
+ self.gc.write_barrier_from_array(newaddr, addr_struct, index)
+ else:
+ self.gc.write_barrier(newaddr, addr_struct)
p[index] = newvalue
def malloc(self, TYPE, n=None):
@@ -326,6 +329,27 @@
self.gc.collect()
assert hash == self.gc.identityhash(self.stackroots[-1])
self.stackroots.pop()
+ # (6) ask for the hash of varsized objects, larger and larger
+ for i in range(10):
+ self.gc.collect()
+ p = self.malloc(VAR, i)
+ self.stackroots.append(p)
+ hash = self.gc.identityhash(p)
+ self.gc.collect()
+ assert hash == self.gc.identityhash(self.stackroots[-1])
+ self.stackroots.pop()
+
+ def test_memory_alignment(self):
+ A1 = lltype.GcArray(lltype.Char)
+ for i in range(50):
+ p1 = self.malloc(A1, i)
+ if i:
+ p1[i-1] = chr(i)
+ self.stackroots.append(p1)
+ self.gc.collect()
+ for i in range(1, 50):
+ p = self.stackroots[-50+i]
+ assert p[i-1] == chr(i)
class TestSemiSpaceGC(DirectGCTest):
from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass
@@ -456,3 +480,35 @@
def test_varsized_from_prebuilt_gc(self):
DirectGCTest.test_varsized_from_prebuilt_gc(self)
test_varsized_from_prebuilt_gc.GC_PARAMS = {'space_size': 3 * 1024 * WORD}
+
+
+class TestMiniMarkGCSimple(DirectGCTest):
+ from pypy.rpython.memory.gc.minimark import MiniMarkGC as GCClass
+ from pypy.rpython.memory.gc.minimark import SimpleArenaCollection
+ # test the GC itself, providing a simple class for ArenaCollection
+ GC_PARAMS = {'ArenaCollectionClass': SimpleArenaCollection}
+
+ def test_card_marker(self):
+ for arraylength in (range(4, 17)
+ + [69] # 3 bytes
+ + [300]): # 10 bytes
+ print 'array length:', arraylength
+ nums = {}
+ a = self.malloc(VAR, arraylength)
+ self.stackroots.append(a)
+ for i in range(50):
+ p = self.malloc(S)
+ p.x = -i
+ a = self.stackroots[-1]
+ index = (i*i) % arraylength
+ self.writearray(a, index, p)
+ nums[index] = p.x
+ #
+ for index, expected_x in nums.items():
+ assert a[index].x == expected_x
+ self.stackroots.pop()
+ test_card_marker.GC_PARAMS = {"card_page_indices": 4,
+ "card_page_indices_min": 7}
+
+class TestMiniMarkGCFull(DirectGCTest):
+ from pypy.rpython.memory.gc.minimark import MiniMarkGC as GCClass
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gctransform/framework.py Mon Sep 20 13:19:51 2010
@@ -7,7 +7,7 @@
from pypy.rpython.memory.gc import marksweep
from pypy.rpython.memory.gcheader import GCHeaderBuilder
from pypy.rlib.rarithmetic import ovfcheck
-from pypy.rlib import rstack
+from pypy.rlib import rstack, rgc
from pypy.rlib.debug import ll_assert
from pypy.translator.backendopt import graphanalyze
from pypy.translator.backendopt.support import var_needsgc
@@ -139,6 +139,8 @@
def __init__(self, translator):
from pypy.rpython.memory.gc.base import choose_gc_from_config
from pypy.rpython.memory.gc.base import ARRAY_TYPEID_MAP
+ from pypy.rpython.memory.gc import inspect
+
super(FrameworkGCTransformer, self).__init__(translator, inline=True)
if hasattr(self, 'GC_PARAMS'):
# for tests: the GC choice can be specified as class attributes
@@ -180,6 +182,7 @@
gcdata.gc.set_root_walker(root_walker)
self.num_pushs = 0
self.write_barrier_calls = 0
+ self.write_barrier_from_array_calls = 0
def frameworkgc_setup():
# run-time initialization code
@@ -388,11 +391,38 @@
else:
self.id_ptr = None
+ self.get_rpy_roots_ptr = getfn(inspect.get_rpy_roots,
+ [s_gc],
+ rgc.s_list_of_gcrefs(),
+ minimal_transform=False)
+ self.get_rpy_referents_ptr = getfn(inspect.get_rpy_referents,
+ [s_gc, s_gcref],
+ rgc.s_list_of_gcrefs(),
+ minimal_transform=False)
+ self.get_rpy_memory_usage_ptr = getfn(inspect.get_rpy_memory_usage,
+ [s_gc, s_gcref],
+ annmodel.SomeInteger(),
+ minimal_transform=False)
+ self.get_rpy_type_index_ptr = getfn(inspect.get_rpy_type_index,
+ [s_gc, s_gcref],
+ annmodel.SomeInteger(),
+ minimal_transform=False)
+ self.is_rpy_instance_ptr = getfn(inspect.is_rpy_instance,
+ [s_gc, s_gcref],
+ annmodel.SomeBool(),
+ minimal_transform=False)
+ self.dump_rpy_heap_ptr = getfn(inspect.dump_rpy_heap,
+ [s_gc, annmodel.SomeInteger()],
+ annmodel.s_Bool,
+ minimal_transform=False)
+
self.set_max_heap_size_ptr = getfn(GCClass.set_max_heap_size.im_func,
[s_gc,
annmodel.SomeInteger(nonneg=True)],
annmodel.s_None)
+ self.write_barrier_ptr = None
+ self.write_barrier_from_array_ptr = None
if GCClass.needs_write_barrier:
self.write_barrier_ptr = getfn(GCClass.write_barrier.im_func,
[s_gc,
@@ -408,8 +438,26 @@
[annmodel.SomeAddress(),
annmodel.SomeAddress()],
annmodel.s_None)
- else:
- self.write_barrier_ptr = None
+ func = getattr(GCClass, 'write_barrier_from_array', None)
+ if func is not None:
+ self.write_barrier_from_array_ptr = getfn(func.im_func,
+ [s_gc,
+ annmodel.SomeAddress(),
+ annmodel.SomeAddress(),
+ annmodel.SomeInteger()],
+ annmodel.s_None,
+ inline=True)
+ func = getattr(gcdata.gc, 'remember_young_pointer_from_array',
+ None)
+ if func is not None:
+ # func should not be a bound method, but a real function
+ assert isinstance(func, types.FunctionType)
+ self.write_barrier_from_array_failing_case_ptr = \
+ getfn(func,
+ [annmodel.SomeAddress(),
+ annmodel.SomeInteger(),
+ annmodel.SomeAddress()],
+ annmodel.s_None)
self.statistics_ptr = getfn(GCClass.statistics.im_func,
[s_gc, annmodel.SomeInteger()],
annmodel.SomeInteger())
@@ -496,6 +544,9 @@
if self.write_barrier_ptr:
log.info("inserted %s write barrier calls" % (
self.write_barrier_calls, ))
+ if self.write_barrier_from_array_ptr:
+ log.info("inserted %s write_barrier_from_array calls" % (
+ self.write_barrier_from_array_calls, ))
# XXX because we call inputconst already in replace_malloc, we can't
# modify the instance, we have to modify the 'rtyped instance'
@@ -766,6 +817,12 @@
[self.write_barrier_failing_case_ptr],
resultvar=op.result)
+ def gct_get_write_barrier_from_array_failing_case(self, hop):
+ op = hop.spaceop
+ hop.genop("same_as",
+ [self.write_barrier_from_array_failing_case_ptr],
+ resultvar=op.result)
+
def gct_zero_gc_pointers_inside(self, hop):
if not self.malloc_zero_filled:
v_ob = hop.spaceop.args[0]
@@ -883,6 +940,53 @@
def gct_gc_get_type_info_group(self, hop):
return hop.cast_result(self.c_type_info_group)
+ def gct_gc_get_rpy_roots(self, hop):
+ livevars = self.push_roots(hop)
+ hop.genop("direct_call",
+ [self.get_rpy_roots_ptr, self.c_const_gc],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
+ def gct_gc_get_rpy_referents(self, hop):
+ livevars = self.push_roots(hop)
+ [v_ptr] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.get_rpy_referents_ptr, self.c_const_gc, v_ptr],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
+ def gct_gc_get_rpy_memory_usage(self, hop):
+ livevars = self.push_roots(hop)
+ [v_ptr] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.get_rpy_memory_usage_ptr, self.c_const_gc, v_ptr],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
+ def gct_gc_get_rpy_type_index(self, hop):
+ livevars = self.push_roots(hop)
+ [v_ptr] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.get_rpy_type_index_ptr, self.c_const_gc, v_ptr],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
+ def gct_gc_is_rpy_instance(self, hop):
+ livevars = self.push_roots(hop)
+ [v_ptr] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.is_rpy_instance_ptr, self.c_const_gc, v_ptr],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
+ def gct_gc_dump_rpy_heap(self, hop):
+ livevars = self.push_roots(hop)
+ [v_fd] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.dump_rpy_heap_ptr, self.c_const_gc, v_fd],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
def gct_malloc_nonmovable_varsize(self, hop):
TYPE = hop.spaceop.result.concretetype
if self.gcdata.gc.can_malloc_nonmovable():
@@ -897,6 +1001,15 @@
c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO))
return hop.cast_result(c)
+ def _set_into_gc_array_part(self, op):
+ if op.opname == 'setarrayitem':
+ return op.args[1]
+ if op.opname == 'setinteriorfield':
+ for v in op.args[1:-1]:
+ if v.concretetype is not lltype.Void:
+ return v
+ return None
+
def transform_generic_set(self, hop):
from pypy.objspace.flow.model import Constant
opname = hop.spaceop.opname
@@ -910,15 +1023,26 @@
and not isinstance(v_newvalue, Constant)
and v_struct.concretetype.TO._gckind == "gc"
and hop.spaceop not in self.clean_sets):
- self.write_barrier_calls += 1
v_newvalue = hop.genop("cast_ptr_to_adr", [v_newvalue],
resulttype = llmemory.Address)
v_structaddr = hop.genop("cast_ptr_to_adr", [v_struct],
resulttype = llmemory.Address)
- hop.genop("direct_call", [self.write_barrier_ptr,
- self.c_const_gc,
- v_newvalue,
- v_structaddr])
+ if (self.write_barrier_from_array_ptr is not None and
+ self._set_into_gc_array_part(hop.spaceop) is not None):
+ self.write_barrier_from_array_calls += 1
+ v_index = self._set_into_gc_array_part(hop.spaceop)
+ assert v_index.concretetype == lltype.Signed
+ hop.genop("direct_call", [self.write_barrier_from_array_ptr,
+ self.c_const_gc,
+ v_newvalue,
+ v_structaddr,
+ v_index])
+ else:
+ self.write_barrier_calls += 1
+ hop.genop("direct_call", [self.write_barrier_ptr,
+ self.c_const_gc,
+ v_newvalue,
+ v_structaddr])
hop.rename('bare_' + opname)
def transform_getfield_typeptr(self, hop):
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gctypelayout.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gctypelayout.py Mon Sep 20 13:19:51 2010
@@ -101,6 +101,10 @@
infobits = self.get(typeid).infobits
return infobits & T_MEMBER_INDEX
+ def q_is_rpython_class(self, typeid):
+ infobits = self.get(typeid).infobits
+ return infobits & T_IS_RPYTHON_INSTANCE != 0
+
def set_query_functions(self, gc):
gc.set_query_functions(
self.q_is_varsize,
@@ -114,7 +118,8 @@
self.q_varsize_offset_to_length,
self.q_varsize_offsets_to_gcpointers_in_var_part,
self.q_weakpointer_offset,
- self.q_member_index)
+ self.q_member_index,
+ self.q_is_rpython_class)
# the lowest 16bits are used to store group member index
@@ -123,6 +128,7 @@
T_HAS_GCPTR_IN_VARSIZE = 0x20000
T_IS_GCARRAY_OF_GCPTR = 0x40000
T_IS_WEAKREF = 0x80000
+T_IS_RPYTHON_INSTANCE = 0x100000 # the type is a subclass of OBJECT
T_KEY_MASK = intmask(0xFF000000)
T_KEY_VALUE = intmask(0x7A000000) # bug detection only
@@ -181,6 +187,8 @@
varinfo.varitemsize = llmemory.sizeof(ARRAY.OF)
if builder.is_weakref_type(TYPE):
infobits |= T_IS_WEAKREF
+ if is_subclass_of_object(TYPE):
+ infobits |= T_IS_RPYTHON_INSTANCE
info.infobits = infobits | T_KEY_VALUE
# ____________________________________________________________
@@ -259,9 +267,7 @@
else:
# no vtable from lltype2vtable -- double-check to be sure
# that it's not a subclass of OBJECT.
- while isinstance(TYPE, lltype.GcStruct):
- assert TYPE is not rclass.OBJECT
- _, TYPE = TYPE._first_struct()
+ assert not is_subclass_of_object(TYPE)
def get_info(self, type_id):
res = llop.get_group_member(GCData.TYPE_INFO_PTR,
@@ -437,6 +443,13 @@
for i in range(p._obj.getlength()):
zero_gc_pointers_inside(p[i], ITEM)
+def is_subclass_of_object(TYPE):
+ while isinstance(TYPE, lltype.GcStruct):
+ if TYPE is rclass.OBJECT:
+ return True
+ _, TYPE = TYPE._first_struct()
+ return False
+
########## weakrefs ##########
# framework: weakref objects are small structures containing only an address
Modified: pypy/branch/fast-forward/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gcwrapper.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gcwrapper.py Mon Sep 20 13:19:51 2010
@@ -15,6 +15,8 @@
self.llinterp = llinterp
self.prepare_graphs(flowgraphs)
self.gc.setup()
+ self.has_write_barrier_from_array = hasattr(self.gc,
+ 'write_barrier_from_array')
def prepare_graphs(self, flowgraphs):
lltype2vtable = self.llinterp.typer.lltype2vtable
@@ -78,13 +80,30 @@
ARRAY = lltype.typeOf(array).TO
addr = llmemory.cast_ptr_to_adr(array)
addr += llmemory.itemoffsetof(ARRAY, index)
- self.setinterior(array, addr, ARRAY.OF, newitem)
+ self.setinterior(array, addr, ARRAY.OF, newitem, (index,))
- def setinterior(self, toplevelcontainer, inneraddr, INNERTYPE, newvalue):
+ def setinterior(self, toplevelcontainer, inneraddr, INNERTYPE, newvalue,
+ offsets=()):
if (lltype.typeOf(toplevelcontainer).TO._gckind == 'gc' and
isinstance(INNERTYPE, lltype.Ptr) and INNERTYPE.TO._gckind == 'gc'):
- self.gc.write_barrier(llmemory.cast_ptr_to_adr(newvalue),
- llmemory.cast_ptr_to_adr(toplevelcontainer))
+ #
+ wb = True
+ if self.has_write_barrier_from_array:
+ for index in offsets:
+ if type(index) is not str:
+ assert (type(index) is int # <- fast path
+ or lltype.typeOf(index) == lltype.Signed)
+ self.gc.write_barrier_from_array(
+ llmemory.cast_ptr_to_adr(newvalue),
+ llmemory.cast_ptr_to_adr(toplevelcontainer),
+ index)
+ wb = False
+ break
+ #
+ if wb:
+ self.gc.write_barrier(
+ llmemory.cast_ptr_to_adr(newvalue),
+ llmemory.cast_ptr_to_adr(toplevelcontainer))
llheap.setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue)
def collect(self, *gen):
Modified: pypy/branch/fast-forward/pypy/rpython/memory/lltypelayout.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/lltypelayout.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/lltypelayout.py Mon Sep 20 13:19:51 2010
@@ -7,7 +7,7 @@
primitive_to_fmt = {lltype.Signed: "l",
lltype.Unsigned: "L",
lltype.Char: "c",
- lltype.UniChar: "H", # maybe
+ lltype.UniChar: "i", # 4 bytes
lltype.Bool: "B",
lltype.Float: "d",
llmemory.Address: "P",
Modified: pypy/branch/fast-forward/pypy/rpython/memory/support.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/support.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/support.py Mon Sep 20 13:19:51 2010
@@ -216,6 +216,24 @@
self.index_in_oldest = index + 1
return result
+ def foreach(self, callback, arg):
+ """Invoke 'callback(address, arg)' for all addresses in the deque.
+ Typically, 'callback' is a bound method and 'arg' can be None.
+ """
+ chunk = self.oldest_chunk
+ index = self.index_in_oldest
+ while chunk is not self.newest_chunk:
+ while index < chunk_size:
+ callback(chunk.items[index], arg)
+ index += 1
+ chunk = chunk.next
+ index = 0
+ limit = self.index_in_newest
+ while index < limit:
+ callback(chunk.items[index], arg)
+ index += 1
+ foreach._annspecialcase_ = 'specialize:arg(1)'
+
def delete(self):
cur = self.oldest_chunk
while cur:
Modified: pypy/branch/fast-forward/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/test/test_gc.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/test/test_gc.py Mon Sep 20 13:19:51 2010
@@ -26,8 +26,9 @@
class GCTest(object):
GC_PARAMS = {}
GC_CAN_MOVE = False
- GC_CANNOT_MALLOC_NONMOVABLE = False
+ GC_CAN_MALLOC_NONMOVABLE = True
GC_CAN_SHRINK_ARRAY = False
+ GC_CAN_SHRINK_BIG_ARRAY = False
def setup_class(cls):
cls._saved_logstate = py.log._getstate()
@@ -451,10 +452,10 @@
a = rgc.malloc_nonmovable(TP, 3)
if a:
assert not rgc.can_move(a)
- return 0
- return 1
+ return 1
+ return 0
- assert self.interpret(func, []) == int(self.GC_CANNOT_MALLOC_NONMOVABLE)
+ assert self.interpret(func, []) == int(self.GC_CAN_MALLOC_NONMOVABLE)
def test_malloc_nonmovable_fixsize(self):
S = lltype.GcStruct('S', ('x', lltype.Float))
@@ -465,37 +466,36 @@
rgc.collect()
if a:
assert not rgc.can_move(a)
- return 0
- return 1
+ return 1
+ return 0
except Exception, e:
return 2
- assert self.interpret(func, []) == int(self.GC_CANNOT_MALLOC_NONMOVABLE)
+ assert self.interpret(func, []) == int(self.GC_CAN_MALLOC_NONMOVABLE)
def test_shrink_array(self):
from pypy.rpython.lltypesystem.rstr import STR
- GC_CAN_SHRINK_ARRAY = self.GC_CAN_SHRINK_ARRAY
- def f(n, m):
+ def f(n, m, gc_can_shrink_array):
ptr = lltype.malloc(STR, n)
ptr.hash = 0x62
ptr.chars[0] = 'A'
ptr.chars[1] = 'B'
ptr.chars[2] = 'C'
ptr2 = rgc.ll_shrink_array(ptr, 2)
- assert (ptr == ptr2) == GC_CAN_SHRINK_ARRAY
+ assert (ptr == ptr2) == gc_can_shrink_array
rgc.collect()
return ( ord(ptr2.chars[0]) +
(ord(ptr2.chars[1]) << 8) +
(len(ptr2.chars) << 16) +
(ptr2.hash << 24))
- assert self.interpret(f, [3, 0]) == 0x62024241
- # don't test with larger numbers of top of the Hybrid GC, because
- # the default settings make it a too-large varsized object that
- # gets allocated outside the semispace
- if not isinstance(self, TestHybridGC):
- assert self.interpret(f, [12, 0]) == 0x62024241
+ flag = self.GC_CAN_SHRINK_ARRAY
+ assert self.interpret(f, [3, 0, flag]) == 0x62024241
+ # with larger numbers, it gets allocated outside the semispace
+ # with some GCs.
+ flag = self.GC_CAN_SHRINK_BIG_ARRAY
+ assert self.interpret(f, [12, 0, flag]) == 0x62024241
def test_tagged_simple(self):
from pypy.rlib.objectmodel import UnboxedValue
@@ -568,7 +568,7 @@
assert res == 111
def test_writebarrier_before_copy(self):
- S = lltype.GcStruct('S')
+ S = lltype.GcStruct('S', ('x', lltype.Char))
TP = lltype.GcArray(lltype.Ptr(S))
def fn():
l = lltype.malloc(TP, 100)
@@ -628,8 +628,9 @@
class TestSemiSpaceGC(GCTest, snippet.SemiSpaceGCTests):
from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass
GC_CAN_MOVE = True
- GC_CANNOT_MALLOC_NONMOVABLE = True
+ GC_CAN_MALLOC_NONMOVABLE = False
GC_CAN_SHRINK_ARRAY = True
+ GC_CAN_SHRINK_BIG_ARRAY = True
class TestGrowingSemiSpaceGC(TestSemiSpaceGC):
GC_PARAMS = {'space_size': 16*WORD}
@@ -641,16 +642,15 @@
from pypy.rpython.memory.gc.markcompact import MarkCompactGC as GCClass
GC_PARAMS = {'space_size': 65536+16384}
GC_CAN_SHRINK_ARRAY = False
+ GC_CAN_SHRINK_BIG_ARRAY = False
def test_finalizer_order(self):
py.test.skip("Not implemented yet")
- def test_writebarrier_before_copy(self):
- py.test.skip("Not relevant, and crashes because llarena does not "
- "support empty GcStructs")
class TestHybridGC(TestGenerationalGC):
from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass
- GC_CANNOT_MALLOC_NONMOVABLE = False
+ GC_CAN_MALLOC_NONMOVABLE = True
+ GC_CAN_SHRINK_BIG_ARRAY = False
def test_ref_from_rawmalloced_to_regular(self):
import gc
@@ -720,7 +720,7 @@
from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass
GC_CAN_MOVE = False # with this size of heap, stuff gets allocated
# in 3rd gen.
- GC_CANNOT_MALLOC_NONMOVABLE = False
+ GC_CAN_MALLOC_NONMOVABLE = True
GC_PARAMS = {'space_size': 48*WORD,
'min_nursery_size': 12*WORD,
'nursery_size': 12*WORD,
@@ -764,3 +764,13 @@
def test_malloc_nonmovable_fixsize(self):
py.test.skip("Not supported")
+
+
+class TestMiniMarkGC(TestSemiSpaceGC):
+ from pypy.rpython.memory.gc.minimark import MiniMarkGC as GCClass
+ GC_CAN_SHRINK_BIG_ARRAY = False
+ GC_CAN_MALLOC_NONMOVABLE = True
+
+class TestMiniMarkGCCardMarking(TestMiniMarkGC):
+ GC_PARAMS = {'card_page_indices': 4,
+ 'card_page_indices_min': 10}
Modified: pypy/branch/fast-forward/pypy/rpython/memory/test/test_support.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/test/test_support.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/test/test_support.py Mon Sep 20 13:19:51 2010
@@ -113,6 +113,27 @@
deque.append(x)
expected.append(x)
+ def test_foreach(self):
+ AddressDeque = get_address_deque(10)
+ ll = AddressDeque()
+ for num_entries in range(30, -1, -1):
+ addrs = [raw_malloc(llmemory.sizeof(lltype.Signed))
+ for i in range(num_entries)]
+ for a in addrs:
+ ll.append(a)
+
+ seen = []
+ def callback(addr, fortytwo):
+ assert fortytwo == 42
+ seen.append(addr)
+
+ ll.foreach(callback, 42)
+ assert seen == addrs
+ for a in addrs:
+ b = ll.popleft()
+ assert a == b
+ assert not ll.non_empty()
+
def test_stack_annotate():
AddressStack = get_address_stack(60)
Modified: pypy/branch/fast-forward/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/test/test_transformed_gc.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/test/test_transformed_gc.py Mon Sep 20 13:19:51 2010
@@ -47,7 +47,7 @@
gcpolicy = None
stacklessgc = False
GC_CAN_MOVE = False
- GC_CANNOT_MALLOC_NONMOVABLE = False
+ GC_CAN_MALLOC_NONMOVABLE = True
taggedpointers = False
def setup_class(cls):
@@ -242,6 +242,26 @@
heap_size = self.heap_usage(statistics)
assert heap_size < 16000 * WORD / 4 # xxx
+ def define_llinterp_dict(self):
+ class A(object):
+ pass
+ def malloc_a_lot():
+ i = 0
+ while i < 10:
+ i += 1
+ a = (1, 2, i)
+ b = {a: A()}
+ j = 0
+ while j < 20:
+ j += 1
+ b[1, j, i] = A()
+ return 0
+ return malloc_a_lot
+
+ def test_llinterp_dict(self):
+ run = self.runner("llinterp_dict")
+ run([])
+
def skipdefine_global_list(cls):
gl = []
class Box:
@@ -602,8 +622,8 @@
rgc.collect()
if a:
assert not rgc.can_move(a)
- return 0
- return 1
+ return 1
+ return 0
#except Exception, e:
# return 2
@@ -611,7 +631,7 @@
def test_malloc_nonmovable(self):
run = self.runner("malloc_nonmovable")
- assert int(self.GC_CANNOT_MALLOC_NONMOVABLE) == run([])
+ assert int(self.GC_CAN_MALLOC_NONMOVABLE) == run([])
def define_malloc_nonmovable_fixsize(cls):
S = lltype.GcStruct('S', ('x', lltype.Float))
@@ -622,8 +642,8 @@
rgc.collect()
if a:
assert not rgc.can_move(a)
- return 0
- return 1
+ return 1
+ return 0
except Exception, e:
return 2
@@ -631,7 +651,7 @@
def test_malloc_nonmovable_fixsize(self):
run = self.runner("malloc_nonmovable_fixsize")
- assert run([]) == int(self.GC_CANNOT_MALLOC_NONMOVABLE)
+ assert run([]) == int(self.GC_CAN_MALLOC_NONMOVABLE)
def define_shrink_array(cls):
from pypy.rpython.lltypesystem.rstr import STR
@@ -680,7 +700,8 @@
class GenericMovingGCTests(GenericGCTests):
GC_CAN_MOVE = True
- GC_CANNOT_MALLOC_NONMOVABLE = True
+ GC_CAN_MALLOC_NONMOVABLE = False
+ GC_CAN_TEST_ID = False
def define_many_ids(cls):
class A(object):
@@ -710,7 +731,8 @@
return f
def test_many_ids(self):
- py.test.skip("fails for bad reasons in lltype.py :-(")
+ if not self.GC_CAN_TEST_ID:
+ py.test.skip("fails for bad reasons in lltype.py :-(")
run = self.runner("many_ids")
run([])
@@ -856,7 +878,7 @@
# (and give fixedsize)
def define_writebarrier_before_copy(cls):
- S = lltype.GcStruct('S')
+ S = lltype.GcStruct('S', ('x', lltype.Char))
TP = lltype.GcArray(lltype.Ptr(S))
def fn():
l = lltype.malloc(TP, 100)
@@ -1144,10 +1166,6 @@
GC_PARAMS = {'space_size': 4096*WORD}
root_stack_depth = 200
- def test_writebarrier_before_copy(self):
- py.test.skip("Not relevant, and crashes because llarena does not "
- "support empty GcStructs")
-
class TestGenerationGC(GenericMovingGCTests):
gcname = "generation"
GC_CAN_SHRINK_ARRAY = True
@@ -1379,7 +1397,7 @@
class TestHybridGC(TestGenerationGC):
gcname = "hybrid"
- GC_CANNOT_MALLOC_NONMOVABLE = False
+ GC_CAN_MALLOC_NONMOVABLE = True
class gcpolicy(gc.FrameworkGcPolicy):
class transformerclass(framework.FrameworkGCTransformer):
@@ -1444,6 +1462,23 @@
def test_malloc_nonmovable_fixsize(self):
py.test.skip("not supported")
+
+class TestMiniMarkGC(TestHybridGC):
+ gcname = "minimark"
+ GC_CAN_TEST_ID = True
+
+ class gcpolicy(gc.FrameworkGcPolicy):
+ class transformerclass(framework.FrameworkGCTransformer):
+ from pypy.rpython.memory.gc.minimark import MiniMarkGC as GCClass
+ GC_PARAMS = {'nursery_size': 32*WORD,
+ 'page_size': 16*WORD,
+ 'arena_size': 64*WORD,
+ 'small_request_threshold': 5*WORD,
+ 'card_page_indices': 4,
+ 'card_page_indices_min': 10,
+ }
+ root_stack_depth = 200
+
# ________________________________________________________________
# tagged pointers
Modified: pypy/branch/fast-forward/pypy/rpython/rptr.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/rptr.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/rptr.py Mon Sep 20 13:19:51 2010
@@ -35,6 +35,9 @@
id = lltype.cast_ptr_to_int(p)
return ll_str.ll_int2hex(r_uint(id), True)
+ def get_ll_eq_function(self):
+ return None
+
def rtype_getattr(self, hop):
attr = hop.args_s[1].const
if isinstance(hop.s_result, annmodel.SomeLLADTMeth):
Modified: pypy/branch/fast-forward/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/funcgen.py (original)
+++ pypy/branch/fast-forward/pypy/translator/c/funcgen.py Mon Sep 20 13:19:51 2010
@@ -733,6 +733,8 @@
continue
elif T == Signed:
format.append('%ld')
+ elif T == Unsigned:
+ format.append('%lu')
elif T == Float:
format.append('%f')
elif isinstance(T, Ptr) or T == Address:
Modified: pypy/branch/fast-forward/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/src/mem.h (original)
+++ pypy/branch/fast-forward/pypy/translator/c/src/mem.h Mon Sep 20 13:19:51 2010
@@ -224,3 +224,13 @@
#define OP_CAST_PTR_TO_WEAKREFPTR(x, r) r = x
#define OP_CAST_WEAKREFPTR_TO_PTR(x, r) r = x
+
+/************************************************************/
+/* dummy version of these operations, e.g. with Boehm */
+
+#define OP_GC_GET_RPY_ROOTS(r) r = 0
+#define OP_GC_GET_RPY_REFERENTS(x, r) r = 0
+#define OP_GC_GET_RPY_MEMORY_USAGE(x, r) r = -1
+#define OP_GC_GET_RPY_TYPE_INDEX(x, r) r = -1
+#define OP_GC_IS_RPY_INSTANCE(x, r) r = 0
+#define OP_GC_DUMP_RPY_HEAP(r) r = 0
Modified: pypy/branch/fast-forward/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/branch/fast-forward/pypy/translator/c/test/test_newgc.py Mon Sep 20 13:19:51 2010
@@ -2,7 +2,7 @@
import sys, os, inspect
from pypy.objspace.flow.model import summary
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.memory.test import snippet
from pypy.rlib import rgc
@@ -19,10 +19,11 @@
removetypeptr = False
taggedpointers = False
GC_CAN_MOVE = False
- GC_CANNOT_MALLOC_NONMOVABLE = False
+ GC_CAN_MALLOC_NONMOVABLE = True
GC_CAN_SHRINK_ARRAY = False
_isolated_func = None
+ c_allfuncs = None
@classmethod
def _makefunc_str_int(cls, f):
@@ -111,6 +112,7 @@
def teardown_class(cls):
if hasattr(cls.c_allfuncs, 'close_isolate'):
cls.c_allfuncs.close_isolate()
+ cls.c_allfuncs = None
def run(self, name, *args):
if not args:
@@ -690,8 +692,8 @@
rgc.collect()
if a:
assert not rgc.can_move(a)
- return 0
- return 1
+ return 1
+ return 0
except Exception, e:
return 2
@@ -699,7 +701,7 @@
def test_malloc_nonmovable(self):
res = self.run('malloc_nonmovable')
- assert res == self.GC_CANNOT_MALLOC_NONMOVABLE
+ assert res == self.GC_CAN_MALLOC_NONMOVABLE
def define_resizable_buffer(cls):
from pypy.rpython.lltypesystem.rstr import STR
@@ -891,12 +893,208 @@
def test_arraycopy_writebarrier_ptr(self):
self.run("arraycopy_writebarrier_ptr")
+ def define_get_rpy_roots(self):
+ U = lltype.GcStruct('U', ('x', lltype.Signed))
+ S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
+
+ def g(s):
+ lst = rgc.get_rpy_roots()
+ found = False
+ for x in lst:
+ if x == lltype.cast_opaque_ptr(llmemory.GCREF, s):
+ found = True
+ if x == lltype.cast_opaque_ptr(llmemory.GCREF, s.u):
+ os.write(2, "s.u should not be found!\n")
+ assert False
+ return found == 1
+
+ def fn():
+ s = lltype.malloc(S)
+ s.u = lltype.malloc(U)
+ found = g(s)
+ if not found:
+ os.write(2, "not found!\n")
+ assert False
+ s.u.x = 42
+ return 0
+
+ return fn
+
+ def test_get_rpy_roots(self):
+ self.run("get_rpy_roots")
+
+ def define_get_rpy_referents(self):
+ U = lltype.GcStruct('U', ('x', lltype.Signed))
+ S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
+
+ def fn():
+ s = lltype.malloc(S)
+ s.u = lltype.malloc(U)
+ gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u)
+ lst = rgc.get_rpy_referents(gcref1)
+ assert gcref2 in lst
+ assert gcref1 not in lst
+ s.u.x = 42
+ return 0
+
+ return fn
+
+ def test_get_rpy_referents(self):
+ self.run("get_rpy_referents")
+
+ def define_is_rpy_instance(self):
+ class Foo:
+ pass
+ S = lltype.GcStruct('S', ('x', lltype.Signed))
+
+ def check(gcref, expected):
+ result = rgc._is_rpy_instance(gcref)
+ assert result == expected
+
+ def fn():
+ s = lltype.malloc(S)
+ gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ check(gcref1, False)
+
+ f = Foo()
+ gcref3 = rgc.cast_instance_to_gcref(f)
+ check(gcref3, True)
+
+ return 0
+
+ return fn
+
+ def test_is_rpy_instance(self):
+ self.run("is_rpy_instance")
+
+ def define_try_cast_gcref_to_instance(self):
+ class Foo:
+ pass
+ class FooBar(Foo):
+ pass
+ class Biz(object):
+ pass
+ S = lltype.GcStruct('S', ('x', lltype.Signed))
+
+ def fn():
+ foo = Foo()
+ gcref1 = rgc.cast_instance_to_gcref(foo)
+ assert rgc.try_cast_gcref_to_instance(Foo, gcref1) is foo
+ assert rgc.try_cast_gcref_to_instance(FooBar, gcref1) is None
+ assert rgc.try_cast_gcref_to_instance(Biz, gcref1) is None
+
+ foobar = FooBar()
+ gcref2 = rgc.cast_instance_to_gcref(foobar)
+ assert rgc.try_cast_gcref_to_instance(Foo, gcref2) is foobar
+ assert rgc.try_cast_gcref_to_instance(FooBar, gcref2) is foobar
+ assert rgc.try_cast_gcref_to_instance(Biz, gcref2) is None
+
+ s = lltype.malloc(S)
+ gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ assert rgc.try_cast_gcref_to_instance(Foo, gcref3) is None
+ assert rgc.try_cast_gcref_to_instance(FooBar, gcref3) is None
+ assert rgc.try_cast_gcref_to_instance(Biz, gcref3) is None
+
+ return 0
+
+ return fn
+
+ def test_try_cast_gcref_to_instance(self):
+ self.run("try_cast_gcref_to_instance")
+
+ def define_get_rpy_memory_usage(self):
+ U = lltype.GcStruct('U', ('x1', lltype.Signed),
+ ('x2', lltype.Signed),
+ ('x3', lltype.Signed),
+ ('x4', lltype.Signed),
+ ('x5', lltype.Signed),
+ ('x6', lltype.Signed),
+ ('x7', lltype.Signed),
+ ('x8', lltype.Signed))
+ S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
+ A = lltype.GcArray(lltype.Ptr(S))
+
+ def fn():
+ s = lltype.malloc(S)
+ s.u = lltype.malloc(U)
+ a = lltype.malloc(A, 1000)
+ gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ int1 = rgc.get_rpy_memory_usage(gcref1)
+ assert 8 <= int1 <= 32
+ gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u)
+ int2 = rgc.get_rpy_memory_usage(gcref2)
+ assert 4*9 <= int2 <= 8*12
+ gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, a)
+ int3 = rgc.get_rpy_memory_usage(gcref3)
+ assert 4*1001 <= int3 <= 8*1010
+ return 0
+
+ return fn
+
+ def test_get_rpy_memory_usage(self):
+ self.run("get_rpy_memory_usage")
+
+ def define_get_rpy_type_index(self):
+ U = lltype.GcStruct('U', ('x', lltype.Signed))
+ S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
+ A = lltype.GcArray(lltype.Ptr(S))
+
+ def fn():
+ s = lltype.malloc(S)
+ s.u = lltype.malloc(U)
+ a = lltype.malloc(A, 1000)
+ s2 = lltype.malloc(S)
+ gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ int1 = rgc.get_rpy_type_index(gcref1)
+ gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u)
+ int2 = rgc.get_rpy_type_index(gcref2)
+ gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, a)
+ int3 = rgc.get_rpy_type_index(gcref3)
+ gcref4 = lltype.cast_opaque_ptr(llmemory.GCREF, s2)
+ int4 = rgc.get_rpy_type_index(gcref4)
+ assert int1 != int2
+ assert int1 != int3
+ assert int2 != int3
+ assert int1 == int4
+ return 0
+
+ return fn
+
+ def test_get_rpy_type_index(self):
+ self.run("get_rpy_type_index")
+
+ filename_dump = str(udir.join('test_dump_rpy_heap'))
+ def define_dump_rpy_heap(self):
+ U = lltype.GcStruct('U', ('x', lltype.Signed))
+ S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
+ A = lltype.GcArray(lltype.Ptr(S))
+ filename = self.filename_dump
+
+ def fn():
+ s = lltype.malloc(S)
+ s.u = lltype.malloc(U)
+ a = lltype.malloc(A, 1000)
+ s2 = lltype.malloc(S)
+ #
+ fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0666)
+ rgc.dump_rpy_heap(fd)
+ os.close(fd)
+ return 0
+
+ return fn
+
+ def test_dump_rpy_heap(self):
+ self.run("dump_rpy_heap")
+ assert os.path.exists(self.filename_dump)
+ assert os.path.getsize(self.filename_dump) > 0 # minimal test
+
class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTestDefines):
gcpolicy = "semispace"
should_be_moving = True
GC_CAN_MOVE = True
- GC_CANNOT_MALLOC_NONMOVABLE = True
+ GC_CAN_MALLOC_NONMOVABLE = False
GC_CAN_SHRINK_ARRAY = True
# for snippets
@@ -1055,7 +1253,7 @@
class TestHybridGC(TestGenerationalGC):
gcpolicy = "hybrid"
should_be_moving = True
- GC_CANNOT_MALLOC_NONMOVABLE = False
+ GC_CAN_MALLOC_NONMOVABLE = True
def test_gc_set_max_heap_size(self):
py.test.skip("not implemented")
@@ -1126,6 +1324,15 @@
res = self.run("adding_a_hash")
assert res == 0
+class TestMiniMarkGC(TestSemiSpaceGC):
+ gcpolicy = "minimark"
+ should_be_moving = True
+ GC_CAN_MALLOC_NONMOVABLE = True
+ GC_CAN_SHRINK_ARRAY = True
+
+ def test_gc_heap_stats(self):
+ py.test.skip("not implemented")
+
# ____________________________________________________________________
class TaggedPointersTest(object):
@@ -1180,3 +1387,6 @@
class TestMarkCompactGCMostCompact(TaggedPointersTest, TestMarkCompactGC):
removetypeptr = True
+
+class TestMiniMarkGCMostCompact(TaggedPointersTest, TestMiniMarkGC):
+ removetypeptr = True
Modified: pypy/branch/fast-forward/pypy/translator/exceptiontransform.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/exceptiontransform.py (original)
+++ pypy/branch/fast-forward/pypy/translator/exceptiontransform.py Mon Sep 20 13:19:51 2010
@@ -277,7 +277,9 @@
block.exits[0].target is graph.returnblock and
len(block.operations) and
(block.exits[0].args[0].concretetype is lltype.Void or
- block.exits[0].args[0] is block.operations[-1].result)):
+ block.exits[0].args[0] is block.operations[-1].result) and
+ block.operations[-1].opname not in ('malloc', # special cases
+ 'malloc_nonmovable')):
last_operation -= 1
lastblock = block
for i in range(last_operation, -1, -1):
@@ -466,6 +468,9 @@
c_flags = spaceop.args[1]
c_flags.value = c_flags.value.copy()
spaceop.args[1].value['zero'] = True
+ # NB. when inserting more special-cases here, keep in mind that
+ # you also need to list the opnames in transform_block()
+ # (see "special cases")
if insert_zeroing_op:
if normalafterblock is None:
More information about the Pypy-commit
mailing list