[pypy-commit] pypy shadowstack-perf: In-progress: try to use r15 for signalling exceptions.
arigo
noreply at buildbot.pypy.org
Fri Jul 8 21:27:04 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: shadowstack-perf
Changeset: r45424:65ec9d93dc63
Date: 2011-07-08 20:38 +0200
http://bitbucket.org/pypy/pypy/changeset/65ec9d93dc63/
Log: In-progress: try to use r15 for signalling exceptions.
diff --git a/pypy/rlib/register.py b/pypy/rlib/register.py
--- a/pypy/rlib/register.py
+++ b/pypy/rlib/register.py
@@ -15,10 +15,12 @@
# For now, only for x86-64. Tries to use the register r15.
eci = ExternalCompilationInfo(
- post_include_bits=['register void* pypy_r15 asm("r15");\n'
- '#define PYPY_GET_R15() pypy_r15\n'
- '#define PYPY_SET_R15(x) (pypy_r15 = x)\n'
- ],
+ post_include_bits=[
+ 'register void *pypy_r15 asm("r15");\n'
+ '#define PYPY_GET_SPECIAL_REG() pypy_r15\n'
+ '#define PYPY_SPECIAL_REG_NONNULL() (pypy_r15 != NULL)\n'
+ '#define PYPY_SET_SPECIAL_REG(x) (pypy_r15 = x)\n'
+ ],
)
_test_eci = eci.merge(ExternalCompilationInfo(
@@ -38,27 +40,42 @@
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
- # use load_from_reg(TYPE) and store_into_reg(llvalue) to load and store
- # a value out of the special register. When running on top of Python.
+ # use addr=load_from_reg() and store_into_reg(addr) to load and store
+ # an Address out of the special register. When running on top of Python,
# the behavior is emulated.
_value_reg = None
- def _pypy_get_r15():
+ def _pypy_get_special_reg():
assert _value_reg is not None
return _value_reg
- def _pypy_set_r15(addr):
+ def _pypy_special_reg_nonnull():
+ assert _value_reg is not None
+ return bool(_value_reg)
+
+ def _pypy_set_special_reg(addr):
global _value_reg
_value_reg = addr
- load_from_reg = rffi.llexternal('PYPY_GET_R15', [], llmemory.Address,
- _callable=_pypy_get_r15,
+ load_from_reg = rffi.llexternal('PYPY_GET_SPECIAL_REG', [],
+ llmemory.Address,
+ _callable=_pypy_get_special_reg,
compilation_info=eci,
_nowrapper=True)
- store_into_reg = rffi.llexternal('PYPY_SET_R15', [llmemory.Address],
- lltype.Void,
- _callable=_pypy_set_r15,
+ reg_is_nonnull = rffi.llexternal('PYPY_SPECIAL_REG_NONNULL', [],
+ lltype.Bool,
+ _callable=_pypy_special_reg_nonnull,
compilation_info=eci,
_nowrapper=True)
+
+ store_into_reg = rffi.llexternal('PYPY_SET_SPECIAL_REG',
+ [llmemory.Address],
+ lltype.Void,
+ _callable=_pypy_set_special_reg,
+ compilation_info=eci,
+ _nowrapper=True)
+
+ # xxx temporary
+ nonnull = llmemory.cast_int_to_adr(-1)
diff --git a/pypy/rlib/test/test_register.py b/pypy/rlib/test/test_register.py
--- a/pypy/rlib/test/test_register.py
+++ b/pypy/rlib/test/test_register.py
@@ -1,6 +1,7 @@
import py
from pypy.rlib import register
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.translator.c.test.test_standalone import StandaloneTests
def test_register():
@@ -36,13 +37,19 @@
res = interpret(f, [41])
assert res == 41
+
+class TestLoadStoreCompiled(StandaloneTests):
+ def setup_class(cls):
+ if register.register_number is None:
+ py.test.skip("rlib/register not supported on this platform")
+
def test_compiled(self):
- from pypy.translator.c.test.test_genc import compile
- def f(n):
- a = rffi.cast(llmemory.Address, n)
+ def f(argv):
+ a = rffi.cast(llmemory.Address, 43)
register.store_into_reg(a)
b = register.load_from_reg()
- return rffi.cast(lltype.Signed, b)
- cfn = compile(f, [int])
- res = cfn(43)
- assert res == 43
+ print rffi.cast(lltype.Signed, b)
+ return 0
+ t, cbuilder = self.compile(f)
+ data = cbuilder.cmdexec('')
+ assert data.startswith('43\n')
diff --git a/pypy/translator/c/src/main.h b/pypy/translator/c/src/main.h
--- a/pypy/translator/c/src/main.h
+++ b/pypy/translator/c/src/main.h
@@ -34,6 +34,10 @@
char *errmsg;
int i, exitcode;
RPyListOfString *list;
+#ifdef PYPY_GET_SPECIAL_REG
+ void *pypy_reg_oldvalue = PYPY_GET_SPECIAL_REG();
+ PYPY_SET_SPECIAL_REG((void*)-1);
+#endif
pypy_asm_stack_bottom();
instrument_setup();
@@ -70,6 +74,10 @@
pypy_debug_catch_fatal_exception();
}
+#ifdef PYPY_GET_SPECIAL_REG
+ PYPY_SET_SPECIAL_REG(pypy_reg_oldvalue);
+#endif
+
return exitcode;
memory_out:
@@ -79,7 +87,7 @@
fprintf(stderr, "Fatal error during initialization: %s\n", errmsg);
#endif
abort();
- return 1;
+ return 1; /* not actually reachable */
}
int PYPY_MAIN_FUNCTION(int argc, char *argv[])
diff --git a/pypy/translator/exceptiontransform.py b/pypy/translator/exceptiontransform.py
--- a/pypy/translator/exceptiontransform.py
+++ b/pypy/translator/exceptiontransform.py
@@ -14,6 +14,7 @@
from pypy.rlib.rarithmetic import r_singlefloat
from pypy.rlib.debug import ll_assert
from pypy.rlib.rstackovf import _StackOverflow
+from pypy.rlib import register
from pypy.annotation import model as annmodel
from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
from pypy.tool.sourcetools import func_with_new_name
@@ -72,9 +73,19 @@
assertion_error_ll_exc_type)
self.c_n_i_error_ll_exc_type = constant_value(n_i_error_ll_exc_type)
+ if register.register_number is not None:
+ self.c_nonnull_specialregister = constant_value(register.nonnull)
+ self.c_load_from_reg = constant_value(register.load_from_reg)
+ self.c_reg_is_nonnull = constant_value(register.reg_is_nonnull)
+ self.c_store_into_reg = constant_value(register.store_into_reg)
+
def rpyexc_occured():
- exc_type = exc_data.exc_type
- return bool(exc_type)
+ if register.register_number is None:
+ exc_type = exc_data.exc_type
+ return bool(exc_type)
+ else:
+ # an exception occurred iff the special register is 0
+ return register.load_from_reg() == llmemory.NULL
def rpyexc_fetch_type():
return exc_data.exc_type
@@ -83,6 +94,8 @@
return exc_data.exc_value
def rpyexc_clear():
+ if register.register_number is not None:
+ register.store_into_reg(register.nonnull)
exc_data.exc_type = null_type
exc_data.exc_value = null_value
@@ -99,11 +112,15 @@
exc_data.exc_type = etype
exc_data.exc_value = evalue
lloperation.llop.debug_start_traceback(lltype.Void, etype)
+ if register.register_number is not None:
+ register.store_into_reg(llmemory.NULL)
def rpyexc_reraise(etype, evalue):
exc_data.exc_type = etype
exc_data.exc_value = evalue
lloperation.llop.debug_reraise_traceback(lltype.Void, etype)
+ if register.register_number is not None:
+ register.store_into_reg(llmemory.NULL)
def rpyexc_fetch_exception():
evalue = rpyexc_fetch_value()
@@ -114,6 +131,8 @@
if evalue:
exc_data.exc_type = rclass.ll_inst_type(evalue)
exc_data.exc_value = evalue
+ if register.register_number is not None:
+ register.store_into_reg(llmemory.NULL)
def rpyexc_raise_stack_overflow():
rpyexc_raise(stackovf_ll_exc_type, stackovf_ll_exc)
@@ -409,6 +428,8 @@
#
self.gen_setfield('exc_value', self.c_null_evalue, llops)
self.gen_setfield('exc_type', self.c_null_etype, llops)
+ if register.register_number is not None:
+ self.gen_setspecialregister(self.c_nonnull_specialregister, llops)
excblock.operations[:] = llops
newgraph.exceptblock.inputargs[0].concretetype = self.lltype_of_exception_type
newgraph.exceptblock.inputargs[1].concretetype = self.lltype_of_exception_value
@@ -432,9 +453,11 @@
if alloc_shortcut:
T = spaceop.result.concretetype
var_no_exc = self.gen_nonnull(spaceop.result, llops)
- else:
+ elif register.register_number is None:
v_exc_type = self.gen_getfield('exc_type', llops)
var_no_exc = self.gen_isnull(v_exc_type, llops)
+ else:
+ var_no_exc = self.gen_specialreg_no_exc(llops)
block.operations.extend(llops)
@@ -527,6 +550,17 @@
def gen_nonnull(self, v, llops):
return llops.genop('ptr_nonzero', [v], lltype.Bool)
+ def gen_getspecialregister(self, llops):
+ return llops.genop('direct_call', [self.c_load_from_reg],
+ resulttype = llmemory.Address)
+
+ def gen_specialreg_no_exc(self, llops):
+ return llops.genop('direct_call', [self.c_reg_is_nonnull],
+ resulttype = lltype.Bool)
+
+ def gen_setspecialregister(self, v, llops):
+ llops.genop('direct_call', [self.c_store_into_reg, v])
+
def same_obj(self, ptr1, ptr2):
return ptr1._same_obj(ptr2)
More information about the pypy-commit
mailing list