Author: Maciej Fijalkowski <[email protected]>
Branch: jitframe-on-heap
Changeset: r62000:2bf49cfc5d1e
Date: 2013-03-04 12:08 +0200
http://bitbucket.org/pypy/pypy/changeset/2bf49cfc5d1e/
Log: merge
diff --git a/pypy/module/_continuation/interp_continuation.py
b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -19,11 +19,6 @@
# - normal: self.sthread != None, not is_empty_handle(self.h)
# - finished: self.sthread != None, is_empty_handle(self.h)
- def __del__(self):
- sthread = self.sthread
- if sthread is not None and not sthread.is_empty_handle(self.h):
- sthread.destroy(self.h)
-
def check_sthread(self):
ec = self.space.getexecutioncontext()
if ec.stacklet_thread is not self.sthread:
diff --git a/rpython/memory/gc/base.py b/rpython/memory/gc/base.py
--- a/rpython/memory/gc/base.py
+++ b/rpython/memory/gc/base.py
@@ -341,7 +341,7 @@
break
obj = self.run_finalizers.popleft()
finalizer = self.getfinalizer(self.get_type_id(obj))
- finalizer(obj, llmemory.NULL)
+ finalizer(obj)
finally:
self.finalizer_lock_count -= 1
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -1890,7 +1890,7 @@
if not self.is_forwarded(obj):
finalizer = self.getlightfinalizer(self.get_type_id(obj))
ll_assert(bool(finalizer), "no light finalizer found")
- finalizer(obj, llmemory.NULL)
+ finalizer(obj)
else:
obj = self.get_forwarding_address(obj)
self.old_objects_with_light_finalizers.append(obj)
@@ -1911,7 +1911,7 @@
# dying
finalizer = self.getlightfinalizer(self.get_type_id(obj))
ll_assert(bool(finalizer), "no light finalizer found")
- finalizer(obj, llmemory.NULL)
+ finalizer(obj)
self.old_objects_with_light_finalizers.delete()
self.old_objects_with_light_finalizers = new_objects
diff --git a/rpython/memory/gc/semispace.py b/rpython/memory/gc/semispace.py
--- a/rpython/memory/gc/semispace.py
+++ b/rpython/memory/gc/semispace.py
@@ -494,7 +494,7 @@
new_objects.append(self.get_forwarding_address(obj))
else:
finalizer = self.getfinalizer(self.get_type_id(obj))
- finalizer(obj, llmemory.NULL)
+ finalizer(obj)
self.objects_with_light_finalizers.delete()
self.objects_with_light_finalizers = new_objects
diff --git a/rpython/memory/gctransform/asmgcroot.py
b/rpython/memory/gctransform/asmgcroot.py
--- a/rpython/memory/gctransform/asmgcroot.py
+++ b/rpython/memory/gctransform/asmgcroot.py
@@ -139,11 +139,13 @@
if self._with_jit:
jit2gc = gctransformer.translator._jit2gc
self.frame_tid = jit2gc['frame_tid']
+ self.gctransformer = gctransformer
def need_stacklet_support(self, gctransformer, getfn):
# stacklet support: BIG HACK for rlib.rstacklet
from rpython.rlib import _stacklet_asmgcc
_stacklet_asmgcc._asmstackrootwalker = self # as a global! argh
+ _stacklet_asmgcc.complete_destrptr(gctransformer)
def need_thread_support(self, gctransformer, getfn):
# Threads supported "out of the box" by the rest of the code.
diff --git a/rpython/memory/gctransform/framework.py
b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -645,11 +645,9 @@
c_type_id = rmodel.inputconst(TYPE_ID, type_id)
info = self.layoutbuilder.get_info(type_id)
c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
- kind_and_fptr = self.special_funcptr_for_type(TYPE)
- has_finalizer = (kind_and_fptr is not None and
- kind_and_fptr[0] == "finalizer")
- has_light_finalizer = (kind_and_fptr is not None and
- kind_and_fptr[0] == "light_finalizer")
+ fptrs = self.special_funcptr_for_type(TYPE)
+ has_finalizer = "finalizer" in fptrs
+ has_light_finalizer = "light_finalizer" in fptrs
if has_light_finalizer:
has_finalizer = True
c_has_finalizer = rmodel.inputconst(lltype.Bool, has_finalizer)
@@ -798,11 +796,6 @@
[self.root_walker.gc_shadowstackref_context_ptr, op.args[0]],
resultvar=op.result)
- def gct_gc_shadowstackref_destroy(self, hop):
- op = hop.spaceop
- hop.genop("direct_call",
- [self.root_walker.gc_shadowstackref_destroy_ptr, op.args[0]])
-
def gct_gc_save_current_state_away(self, hop):
op = hop.spaceop
hop.genop("direct_call",
@@ -1213,8 +1206,8 @@
None)
def has_light_finalizer(self, TYPE):
- special = self.special_funcptr_for_type(TYPE)
- return special is not None and special[0] == 'light_finalizer'
+ fptrs = self.special_funcptr_for_type(TYPE)
+ return "light_finalizer" in fptrs
def has_custom_trace(self, TYPE):
rtti = get_rtti(TYPE)
@@ -1228,14 +1221,16 @@
destrptr = rtti._obj.destructor_funcptr
DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0]
typename = TYPE.__name__
- def ll_finalizer(addr, ignored):
+ def ll_finalizer(addr):
v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
ll_call_destructor(destrptr, v, typename)
- return llmemory.NULL
fptr = self.transformer.annotate_finalizer(ll_finalizer,
- [llmemory.Address, llmemory.Address], llmemory.Address)
- g = destrptr._obj.graph
- light = not
FinalizerAnalyzer(self.translator).analyze_light_finalizer(g)
+ [llmemory.Address], lltype.Void)
+ try:
+ g = destrptr._obj.graph
+ light = not
FinalizerAnalyzer(self.translator).analyze_light_finalizer(g)
+ except lltype.DelayedPointer:
+ light = False # XXX bah, too bad
return fptr, light
def make_custom_trace_funcptr_for_type(self, TYPE):
diff --git a/rpython/memory/gctransform/shadowstack.py
b/rpython/memory/gctransform/shadowstack.py
--- a/rpython/memory/gctransform/shadowstack.py
+++ b/rpython/memory/gctransform/shadowstack.py
@@ -1,6 +1,7 @@
from rpython.annotator import model as annmodel
from rpython.rlib.debug import ll_assert
from rpython.rlib.nonconst import NonConstant
+from rpython.rlib import rgc
from rpython.rtyper import rmodel
from rpython.rtyper.annlowlevel import llhelper
from rpython.rtyper.lltypesystem import lltype, llmemory
@@ -226,10 +227,6 @@
ssref = lltype.cast_opaque_ptr(lltype.Ptr(SHADOWSTACKREF), gcref)
return ssref.context
- def gc_shadowstackref_destroy(gcref):
- ssref = lltype.cast_opaque_ptr(lltype.Ptr(SHADOWSTACKREF), gcref)
- shadow_stack_pool.destroy(ssref)
-
def gc_save_current_state_away(gcref, ncontext):
ssref = lltype.cast_opaque_ptr(lltype.Ptr(SHADOWSTACKREF), gcref)
shadow_stack_pool.save_current_state_away(ssref, ncontext)
@@ -252,9 +249,6 @@
self.gc_shadowstackref_context_ptr = getfn(gc_shadowstackref_context,
[s_gcref], s_addr,
inline=True)
- self.gc_shadowstackref_destroy_ptr = getfn(gc_shadowstackref_destroy,
- [s_gcref], annmodel.s_None,
- inline=True)
self.gc_save_current_state_away_ptr = getfn(gc_save_current_state_away,
[s_gcref, s_addr],
annmodel.s_None,
@@ -340,10 +334,6 @@
self.gcdata.root_stack_top = self.unused_full_stack
self.unused_full_stack = llmemory.NULL
- def destroy(self, shadowstackref):
- llmemory.raw_free(shadowstackref.base)
- self._cleanup(shadowstackref)
-
def _cleanup(self, shadowstackref):
shadowstackref.base = llmemory.NULL
shadowstackref.top = llmemory.NULL
@@ -402,7 +392,20 @@
CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
llmemory.Address)
customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace)
- lltype.attachRuntimeTypeInfo(SHADOWSTACKREF, customtraceptr=customtraceptr)
+
+ def shadowstack_destructor(shadowstackref):
+ from rpython.rlib import _rffi_stacklet as _c
+ h = shadowstackref.context
+ h = llmemory.cast_adr_to_ptr(h, _c.handle)
+ llmemory.raw_free(shadowstackref.base)
+ if h:
+ _c.destroy(h)
+
+ destrptr = gctransformer.annotate_helper(shadowstack_destructor,
+ [SHADOWSTACKREFPTR], lltype.Void)
+
+ lltype.attachRuntimeTypeInfo(SHADOWSTACKREF, customtraceptr=customtraceptr,
+ destrptr=destrptr)
gctransformer._SHADOWSTACKREF = SHADOWSTACKREF
return SHADOWSTACKREF
diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py
--- a/rpython/memory/gctypelayout.py
+++ b/rpython/memory/gctypelayout.py
@@ -17,20 +17,22 @@
OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed)
- # When used as a finalizer, the following functions only take one
- # address and ignore the second, and return NULL. When used as a
- # custom tracer (CT), it enumerates the addresses that contain GCREFs.
+ # A custom tracer (CT), enumerates the addresses that contain GCREFs.
# It is called with the object as first argument, and the previous
# returned address (or NULL the first time) as the second argument.
- FINALIZER_OR_CT_FUNC = lltype.FuncType([llmemory.Address,
- llmemory.Address],
- llmemory.Address)
- FINALIZER_OR_CT = lltype.Ptr(FINALIZER_OR_CT_FUNC)
+ FINALIZER_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
+ CUSTOMTRACER_FUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
+ llmemory.Address)
+ FINALIZER = lltype.Ptr(FINALIZER_FUNC)
+ CUSTOMTRACER = lltype.Ptr(CUSTOMTRACER_FUNC)
+ EXTRA = lltype.Struct("type_info_extra",
+ ('finalizer', FINALIZER),
+ ('customtracer', CUSTOMTRACER))
# structure describing the layout of a typeid
TYPE_INFO = lltype.Struct("type_info",
("infobits", lltype.Signed), # combination of the T_xxx consts
- ("finalizer_or_customtrace", FINALIZER_OR_CT),
+ ("extra", lltype.Ptr(EXTRA)),
("fixedsize", lltype.Signed),
("ofstoptrs", lltype.Ptr(OFFSETS_TO_GC_PTR)),
hints={'immutable': True},
@@ -80,16 +82,16 @@
def q_finalizer(self, typeid):
typeinfo = self.get(typeid)
if typeinfo.infobits & T_HAS_FINALIZER:
- return typeinfo.finalizer_or_customtrace
+ return typeinfo.extra.finalizer
else:
- return lltype.nullptr(GCData.FINALIZER_OR_CT_FUNC)
+ return lltype.nullptr(GCData.FINALIZER_FUNC)
def q_light_finalizer(self, typeid):
typeinfo = self.get(typeid)
if typeinfo.infobits & T_HAS_LIGHTWEIGHT_FINALIZER:
- return typeinfo.finalizer_or_customtrace
+ return typeinfo.extra.finalizer
else:
- return lltype.nullptr(GCData.FINALIZER_OR_CT_FUNC)
+ return lltype.nullptr(GCData.FINALIZER_FUNC)
def q_offsets_to_gc_pointers(self, typeid):
return self.get(typeid).ofstoptrs
@@ -131,7 +133,7 @@
ll_assert(self.q_has_custom_trace(typeid),
"T_HAS_CUSTOM_TRACE missing")
typeinfo = self.get(typeid)
- return typeinfo.finalizer_or_customtrace
+ return typeinfo.extra.customtracer
def q_fast_path_tracing(self, typeid):
# return True if none of the flags T_HAS_GCPTR_IN_VARSIZE,
@@ -196,18 +198,20 @@
infobits = index
info.ofstoptrs = builder.offsets2table(offsets, TYPE)
#
- kind_and_fptr = builder.special_funcptr_for_type(TYPE)
- if kind_and_fptr is not None:
- kind, fptr = kind_and_fptr
- info.finalizer_or_customtrace = fptr
- if kind == "finalizer":
+ fptrs = builder.special_funcptr_for_type(TYPE)
+ if fptrs:
+ extra = lltype.malloc(GCData.EXTRA, zero=True, immortal=True,
+ flavor='raw')
+ if "finalizer" in fptrs:
+ extra.finalizer = fptrs["finalizer"]
infobits |= T_HAS_FINALIZER
- elif kind == 'light_finalizer':
+ if "light_finalizer" in fptrs:
+ extra.finalizer = fptrs["light_finalizer"]
infobits |= T_HAS_FINALIZER | T_HAS_LIGHTWEIGHT_FINALIZER
- elif kind == "custom_trace":
+ if "custom_trace" in fptrs:
+ extra.customtracer = fptrs["custom_trace"]
infobits |= T_HAS_CUSTOM_TRACE
- else:
- assert 0, kind
+ info.extra = extra
#
if not TYPE._is_varsize():
info.fixedsize = llarena.round_up_for_allocation(
@@ -379,19 +383,16 @@
return self._special_funcptrs[TYPE]
fptr1, is_lightweight = self.make_finalizer_funcptr_for_type(TYPE)
fptr2 = self.make_custom_trace_funcptr_for_type(TYPE)
- assert not (fptr1 and fptr2), (
- "type %r needs both a finalizer and a custom tracer" % (TYPE,))
+ result = {}
if fptr1:
if is_lightweight:
- kind_and_fptr = "light_finalizer", fptr1
+ result["light_finalizer"] = fptr1
else:
- kind_and_fptr = "finalizer", fptr1
- elif fptr2:
- kind_and_fptr = "custom_trace", fptr2
- else:
- kind_and_fptr = None
- self._special_funcptrs[TYPE] = kind_and_fptr
- return kind_and_fptr
+ result["finalizer"] = fptr1
+ if fptr2:
+ result["custom_trace"] = fptr2
+ self._special_funcptrs[TYPE] = result
+ return result
def make_finalizer_funcptr_for_type(self, TYPE):
# must be overridden for proper finalizer support
diff --git a/rpython/memory/gcwrapper.py b/rpython/memory/gcwrapper.py
--- a/rpython/memory/gcwrapper.py
+++ b/rpython/memory/gcwrapper.py
@@ -216,16 +216,14 @@
t = self.llinterp.typer.annotator.translator
light = not FinalizerAnalyzer(t).analyze_light_finalizer(destrgraph)
- def ll_finalizer(addr, dummy):
- assert dummy == llmemory.NULL
+ def ll_finalizer(addr):
try:
v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
self.llinterp.eval_graph(destrgraph, [v], recursive=True)
except llinterp.LLException:
raise RuntimeError(
"a finalizer raised an exception, shouldn't happen")
- return llmemory.NULL
- return llhelper(gctypelayout.GCData.FINALIZER_OR_CT, ll_finalizer),
light
+ return llhelper(gctypelayout.GCData.FINALIZER, ll_finalizer), light
def make_custom_trace_funcptr_for_type(self, TYPE):
from rpython.memory.gctransform.support import get_rtti
diff --git a/rpython/rlib/_rffi_stacklet.py b/rpython/rlib/_rffi_stacklet.py
--- a/rpython/rlib/_rffi_stacklet.py
+++ b/rpython/rlib/_rffi_stacklet.py
@@ -56,9 +56,9 @@
new = llexternal('stacklet_new', [thread_handle, run_fn, llmemory.Address],
handle, random_effects_on_gcobjs=True)
-switch = llexternal('stacklet_switch', [thread_handle, handle], handle,
+switch = llexternal('stacklet_switch', [handle], handle,
random_effects_on_gcobjs=True)
-destroy = llexternal('stacklet_destroy', [thread_handle, handle], lltype.Void)
+destroy = llexternal('stacklet_destroy', [handle], lltype.Void)
_translate_pointer = llexternal("_stacklet_translate_pointer",
[llmemory.Address, llmemory.Address],
diff --git a/rpython/rlib/_stacklet_asmgcc.py b/rpython/rlib/_stacklet_asmgcc.py
--- a/rpython/rlib/_stacklet_asmgcc.py
+++ b/rpython/rlib/_stacklet_asmgcc.py
@@ -1,8 +1,9 @@
-from rpython.rlib import _rffi_stacklet as _c
from rpython.rlib.debug import ll_assert
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.rtyper.annlowlevel import llhelper
+from rpython.rtyper.annlowlevel import llhelper, MixLevelHelperAnnotator
+from rpython.annotator import model as annmodel
+from rpython.rlib import _rffi_stacklet as _c
_asmstackrootwalker = None # BIG HACK: monkey-patched by asmgcroot.py
@@ -129,11 +130,26 @@
return _stackletrootwalker
get_stackletrootwalker._annspecialcase_ = 'specialize:memo'
+def complete_destrptr(gctransformer):
+ translator = gctransformer.translator
+ mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
+ args_s = [annmodel.lltype_to_annotation(lltype.Ptr(SUSPSTACK))]
+ s_result = annmodel.s_None
+ destrptr = mixlevelannotator.delayedfunction(suspstack_destructor,
+ args_s, s_result)
+ mixlevelannotator.finish()
+ lltype.attachRuntimeTypeInfo(SUSPSTACK, destrptr=destrptr)
+
def customtrace(obj, prev):
stackletrootwalker = get_stackletrootwalker()
return stackletrootwalker.next(obj, prev)
+def suspstack_destructor(suspstack):
+ h = suspstack.handle
+ if h:
+ _c.destroy(h)
+
SUSPSTACK = lltype.GcStruct('SuspStack',
('handle', _c.handle),
@@ -169,7 +185,7 @@
# stacklet with stacklet_new(). If this call fails, then we
# are just returning NULL.
_stack_just_closed()
- return _c.new(gcrootfinder.thrd, llhelper(_c.run_fn, _new_runfn),
+ return _c.new(gcrootfinder.newthrd, llhelper(_c.run_fn, _new_runfn),
llmemory.NULL)
def _stack_just_closed():
@@ -216,7 +232,7 @@
#
# gcrootfinder.suspstack.anchor is left with the anchor of the
# previous place (i.e. before the call to switch()).
- h2 = _c.switch(gcrootfinder.thrd, h)
+ h2 = _c.switch(h)
#
if not h2: # MemoryError: restore
gcrootfinder.suspstack.anchor = oldanchor
@@ -228,7 +244,7 @@
suspstack = NULL_SUSPSTACK
def new(self, thrd, callback, arg):
- self.thrd = thrd._thrd
+ self.newthrd = thrd._thrd
self.runfn = callback
self.arg = arg
# make a fresh new clean SUSPSTACK
@@ -240,8 +256,7 @@
alternateanchor)
return self.get_result_suspstack(h)
- def switch(self, thrd, suspstack):
- self.thrd = thrd._thrd
+ def switch(self, suspstack):
self.suspstack = suspstack
h = pypy_asm_stackwalk2(llhelper(FUNCNOARG_P, _switch_callback),
alternateanchor)
@@ -267,11 +282,6 @@
# This is a return that gave us a real handle. Store it.
return self.attach_handle_on_suspstack(h)
- def destroy(self, thrd, suspstack):
- h = suspstack.handle
- suspstack.handle = _c.null_handle
- _c.destroy(thrd._thrd, h)
-
def is_empty_handle(self, suspstack):
return not suspstack
diff --git a/rpython/rlib/_stacklet_shadowstack.py
b/rpython/rlib/_stacklet_shadowstack.py
--- a/rpython/rlib/_stacklet_shadowstack.py
+++ b/rpython/rlib/_stacklet_shadowstack.py
@@ -79,25 +79,18 @@
return get_result_suspstack(h)
new._dont_inline_ = True
- def switch(thrd, suspstack):
+ def switch(suspstack):
# suspstack has a handle to target, i.e. where to switch to
ll_assert(suspstack != gcrootfinder.oldsuspstack,
"stacklet: invalid use")
gcrootfinder.newsuspstack = suspstack
- thread_handle = thrd._thrd
h = llop.gc_shadowstackref_context(llmemory.Address, suspstack)
h = llmemory.cast_adr_to_ptr(h, _c.handle)
prepare_old_suspstack()
- h = _c.switch(thread_handle, h)
+ h = _c.switch(h)
return get_result_suspstack(h)
switch._dont_inline_ = True
- def destroy(thrd, suspstack):
- h = llop.gc_shadowstackref_context(llmemory.Address, suspstack)
- h = llmemory.cast_adr_to_ptr(h, _c.handle)
- llop.gc_shadowstackref_destroy(lltype.Void, suspstack)
- _c.destroy(thrd._thrd, h)
-
def is_empty_handle(suspstack):
return not suspstack
diff --git a/rpython/rlib/rstacklet.py b/rpython/rlib/rstacklet.py
--- a/rpython/rlib/rstacklet.py
+++ b/rpython/rlib/rstacklet.py
@@ -34,17 +34,11 @@
def switch(self, stacklet):
if DEBUG:
debug.remove(stacklet)
- h = self._gcrootfinder.switch(self, stacklet)
+ h = self._gcrootfinder.switch(stacklet)
if DEBUG:
debug.add(h)
return h
- @jit.dont_look_inside
- def destroy(self, stacklet):
- if DEBUG:
- debug.remove(stacklet)
- self._gcrootfinder.destroy(self, stacklet)
-
def is_empty_handle(self, stacklet):
# note that "being an empty handle" and being equal to
# "get_null_handle()" may be the same, or not; don't rely on it
diff --git a/rpython/rlib/test/test_rstacklet.py
b/rpython/rlib/test/test_rstacklet.py
--- a/rpython/rlib/test/test_rstacklet.py
+++ b/rpython/rlib/test/test_rstacklet.py
@@ -6,7 +6,7 @@
except CompilationError, e:
py.test.skip("cannot import rstacklet: %s" % e)
-from rpython.rlib import rrandom
+from rpython.rlib import rrandom, rgc
from rpython.rlib.rarithmetic import intmask
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
from rpython.translator.c.test.test_standalone import StandaloneTests
@@ -72,7 +72,9 @@
self.status = 0
h = self.sthread.new(switchbackonce_callback,
rffi.cast(llmemory.Address, 321))
- self.sthread.destroy(h)
+ # 'h' ignored
+ if (i % 5000) == 2500:
+ rgc.collect()
def any_alive(self):
for task in self.tasks:
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -890,8 +890,6 @@
raise NotImplementedError("gc_shadowstackref_new")
def op_gc_shadowstackref_context(self):
raise NotImplementedError("gc_shadowstackref_context")
- def op_gc_shadowstackref_destroy(self):
- raise NotImplementedError("gc_shadowstackref_destroy")
def op_gc_save_current_state_away(self):
raise NotImplementedError("gc_save_current_state_away")
def op_gc_forget_current_state(self):
diff --git a/rpython/rtyper/lltypesystem/lloperation.py
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -518,7 +518,6 @@
# for stacklet+shadowstack support
'gc_shadowstackref_new': LLOp(canmallocgc=True),
'gc_shadowstackref_context': LLOp(),
- 'gc_shadowstackref_destroy': LLOp(),
'gc_save_current_state_away': LLOp(),
'gc_forget_current_state': LLOp(),
'gc_restore_state_from': LLOp(),
diff --git a/rpython/translator/c/gc.py b/rpython/translator/c/gc.py
--- a/rpython/translator/c/gc.py
+++ b/rpython/translator/c/gc.py
@@ -313,19 +313,19 @@
def struct_setup(self, structdefnode, rtti):
if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
- destrptr = rtti._obj.destructor_funcptr
+ gctransf = self.db.gctransformer
+ TYPE = structdefnode.STRUCT
+ fptrs = gctransf.special_funcptr_for_type(TYPE)
# make sure this is seen by the database early, i.e. before
# finish_helpers() on the gctransformer
+ destrptr = rtti._obj.destructor_funcptr
self.db.get(destrptr)
# the following, on the other hand, will only discover ll_finalizer
# helpers. The get() sees and records a delayed pointer. It is
# still important to see it so that it can be followed as soon as
# the mixlevelannotator resolves it.
- gctransf = self.db.gctransformer
- TYPE = structdefnode.STRUCT
- kind_and_fptr = gctransf.special_funcptr_for_type(TYPE)
- if kind_and_fptr:
- self.db.get(kind_and_fptr[1])
+ for fptr in fptrs.values():
+ self.db.get(fptr)
def array_setup(self, arraydefnode):
pass
diff --git a/rpython/translator/c/src/stacklet/stacklet.c
b/rpython/translator/c/src/stacklet/stacklet.c
--- a/rpython/translator/c/src/stacklet/stacklet.c
+++ b/rpython/translator/c/src/stacklet/stacklet.c
@@ -52,6 +52,8 @@
* main stack.
*/
struct stacklet_s *stack_prev;
+
+ stacklet_thread_handle stack_thrd; /* the thread where the stacklet is */
};
void *(*_stacklet_switchstack)(void*(*)(void*, void*),
@@ -132,6 +134,7 @@
stacklet->stack_stop = thrd->g_current_stack_stop;
stacklet->stack_saved = 0;
stacklet->stack_prev = thrd->g_stack_chain_head;
+ stacklet->stack_thrd = thrd;
thrd->g_stack_chain_head = stacklet;
return 0;
}
@@ -293,10 +296,10 @@
return thrd->g_source;
}
-stacklet_handle stacklet_switch(stacklet_thread_handle thrd,
- stacklet_handle target)
+stacklet_handle stacklet_switch(stacklet_handle target)
{
long stackmarker;
+ stacklet_thread_handle thrd = target->stack_thrd;
if (thrd->g_current_stack_stop <= (char *)&stackmarker)
thrd->g_current_stack_stop = ((char *)&stackmarker) + 1;
@@ -305,15 +308,23 @@
return thrd->g_source;
}
-void stacklet_destroy(stacklet_thread_handle thrd, stacklet_handle target)
+void stacklet_destroy(stacklet_handle target)
{
- /* remove 'target' from the chained list 'unsaved_stack', if it is there */
- struct stacklet_s **pp = &thrd->g_stack_chain_head;
- for (; *pp != NULL; pp = &(*pp)->stack_prev)
- if (*pp == target) {
- *pp = target->stack_prev;
- break;
- }
+ if (target->stack_prev != NULL) {
+ /* 'target' appears to be in the chained list 'unsaved_stack',
+ so remove it from there. Note that if 'thrd' was already
+ deleted, it means that we left the thread and all stacklets
+ still in the thread should be fully copied away from the
+ stack --- so should have stack_prev == NULL. In this case
+ we don't even read 'stack_thrd', already deallocated. */
+ stacklet_thread_handle thrd = target->stack_thrd;
+ struct stacklet_s **pp = &thrd->g_stack_chain_head;
+ for (; *pp != NULL; pp = &(*pp)->stack_prev)
+ if (*pp == target) {
+ *pp = target->stack_prev;
+ break;
+ }
+ }
free(target);
}
diff --git a/rpython/translator/c/src/stacklet/stacklet.h
b/rpython/translator/c/src/stacklet/stacklet.h
--- a/rpython/translator/c/src/stacklet/stacklet.h
+++ b/rpython/translator/c/src/stacklet/stacklet.h
@@ -44,13 +44,12 @@
* Don't call this with an already-used target, with EMPTY_STACKLET_HANDLE,
* or with a stack handle from another thread (in multithreaded apps).
*/
-stacklet_handle stacklet_switch(stacklet_thread_handle thrd,
- stacklet_handle target);
+stacklet_handle stacklet_switch(stacklet_handle target);
/* Delete a stack handle without resuming it at all.
* (This works even if the stack handle is of a different thread)
*/
-void stacklet_destroy(stacklet_thread_handle thrd, stacklet_handle target);
+void stacklet_destroy(stacklet_handle target);
/* stacklet_handle _stacklet_switch_to_copy(stacklet_handle) --- later */
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit