[pypy-svn] r34886 - in pypy/branch/mininal-c-backend/pypy/translator: . c c/src c/test
ale at codespeak.net
ale at codespeak.net
Thu Nov 23 12:03:15 CET 2006
Author: ale
Date: Thu Nov 23 12:03:10 2006
New Revision: 34886
Added:
pypy/branch/mininal-c-backend/pypy/translator/c/src/instrument.h
- copied unchanged from r34885, pypy/dist/pypy/translator/c/src/instrument.h
Modified:
pypy/branch/mininal-c-backend/pypy/translator/c/database.py
pypy/branch/mininal-c-backend/pypy/translator/c/exceptiontransform.py
pypy/branch/mininal-c-backend/pypy/translator/c/extfunc.py
pypy/branch/mininal-c-backend/pypy/translator/c/funcgen.py
pypy/branch/mininal-c-backend/pypy/translator/c/genc.py
pypy/branch/mininal-c-backend/pypy/translator/c/node.py
pypy/branch/mininal-c-backend/pypy/translator/c/src/exception.h
pypy/branch/mininal-c-backend/pypy/translator/c/src/g_include.h
pypy/branch/mininal-c-backend/pypy/translator/c/src/main.h
pypy/branch/mininal-c-backend/pypy/translator/c/src/obmalloc.c
pypy/branch/mininal-c-backend/pypy/translator/c/src/standalone.h
pypy/branch/mininal-c-backend/pypy/translator/c/src/support.h
pypy/branch/mininal-c-backend/pypy/translator/c/test/test_standalone.py
pypy/branch/mininal-c-backend/pypy/translator/driver.py
Log:
svn merge -r 34627:HEAD
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/database.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/database.py (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/database.py Thu Nov 23 12:03:10 2006
@@ -62,6 +62,8 @@
self.gctransformer = self.gcpolicy.transformerclass(translator)
self.completed = False
+ self.instrument_ncounter = 0
+
def gettypedefnode(self, T, varlength=1):
if varlength <= 1:
varlength = 1 # it's C after all
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/exceptiontransform.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/exceptiontransform.py (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/exceptiontransform.py Thu Nov 23 12:03:10 2006
@@ -56,7 +56,6 @@
def rpyexc_occured():
exc_type = exc_data.exc_type
- lloperation.llop.debug_log_exc(lltype.Void, exc_type)
return exc_type is not null_type
# XXX tmp HACK for genllvm
@@ -64,7 +63,6 @@
# calling rpyexc_occured() from c code with lltype.Bool
def _rpyexc_occured():
exc_type = exc_data.exc_type
- lloperation.llop.debug_log_exc(lltype.Void, exc_type)
return exc_type is not null_type
def rpyexc_fetch_type():
@@ -87,7 +85,8 @@
rpyexc_occured, [], l2a(lltype.Bool))
self.rpyexc_occured_ptr = Constant(lltype.functionptr(
RPYEXC_OCCURED_TYPE, "RPyExceptionOccurred",
- graph=rpyexc_occured_graph),
+ graph=rpyexc_occured_graph,
+ exception_policy="exc_helper"),
lltype.Ptr(RPYEXC_OCCURED_TYPE))
# XXX tmp HACK for genllvm
@@ -96,7 +95,8 @@
_rpyexc_occured, [], l2a(lltype.Signed))
self._rpyexc_occured_ptr = Constant(lltype.functionptr(
_RPYEXC_OCCURED_TYPE, "_RPyExceptionOccurred",
- graph=_rpyexc_occured_graph),
+ graph=_rpyexc_occured_graph,
+ exception_policy="exc_helper"),
lltype.Ptr(_RPYEXC_OCCURED_TYPE))
RPYEXC_FETCH_TYPE_TYPE = lltype.FuncType([], self.lltype_of_exception_type)
@@ -105,7 +105,8 @@
l2a(self.lltype_of_exception_type))
self.rpyexc_fetch_type_ptr = Constant(lltype.functionptr(
RPYEXC_FETCH_TYPE_TYPE, "RPyFetchExceptionType",
- graph=rpyexc_fetch_type_graph),
+ graph=rpyexc_fetch_type_graph,
+ exception_policy="exc_helper"),
lltype.Ptr(RPYEXC_FETCH_TYPE_TYPE))
RPYEXC_FETCH_VALUE_TYPE = lltype.FuncType([], self.lltype_of_exception_value)
@@ -114,7 +115,8 @@
l2a(self.lltype_of_exception_value))
self.rpyexc_fetch_value_ptr = Constant(lltype.functionptr(
RPYEXC_FETCH_VALUE_TYPE, "RPyFetchExceptionValue",
- graph=rpyexc_fetch_value_graph),
+ graph=rpyexc_fetch_value_graph,
+ exception_policy="exc_helper"),
lltype.Ptr(RPYEXC_FETCH_VALUE_TYPE))
RPYEXC_CLEAR = lltype.FuncType([], lltype.Void)
@@ -122,7 +124,8 @@
rpyexc_clear, [], l2a(lltype.Void))
self.rpyexc_clear_ptr = Constant(lltype.functionptr(
RPYEXC_CLEAR, "RPyClearException",
- graph=rpyexc_clear_graph),
+ graph=rpyexc_clear_graph,
+ exception_policy="exc_helper"),
lltype.Ptr(RPYEXC_CLEAR))
RPYEXC_RAISE = lltype.FuncType([self.lltype_of_exception_type,
@@ -134,7 +137,8 @@
l2a(lltype.Void))
self.rpyexc_raise_ptr = Constant(lltype.functionptr(
RPYEXC_RAISE, "RPyRaiseException",
- graph=rpyexc_raise_graph),
+ graph=rpyexc_raise_graph,
+ exception_policy="exc_helper"),
lltype.Ptr(RPYEXC_RAISE))
mixlevelannotator.finish()
@@ -321,7 +325,6 @@
lltype.Bool)
else:
v_exc_type = self.ExcData_repr.getfield(self.cexcdata, 'exc_type', llops)
- llops.genop('debug_log_exc', [v_exc_type], lltype.Void)
var_exc_occured = llops.genop('ptr_nonzero', [v_exc_type],
lltype.Bool)
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/extfunc.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/extfunc.py (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/extfunc.py Thu Nov 23 12:03:10 2006
@@ -208,7 +208,7 @@
yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.fn_pyexcclass2exc)
yield ('_RPyExceptionOccurred', exctransformer._rpyexc_occured_ptr.value)
- yield ('RPyExceptionOccurred', exctransformer.rpyexc_occured_ptr.value)
+ yield ('RPyExceptionOccurred1', exctransformer.rpyexc_occured_ptr.value)
yield ('RPyFetchExceptionType', exctransformer.rpyexc_fetch_type_ptr.value)
yield ('RPyFetchExceptionValue', exctransformer.rpyexc_fetch_value_ptr.value)
yield ('RPyClearException', exctransformer.rpyexc_clear_ptr.value)
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/funcgen.py (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/funcgen.py Thu Nov 23 12:03:10 2006
@@ -27,7 +27,7 @@
if USESLOTS:
__slots__ = """graph db gcpolicy
- cpython_exc
+ exception_policy
more_ll_values
vars
lltypes
@@ -36,11 +36,11 @@
blocknum
oldgraph""".split()
- def __init__(self, graph, db, cpython_exc=False, functionname=None):
+ def __init__(self, graph, db, exception_policy=None, functionname=None):
self.graph = graph
self.db = db
self.gcpolicy = db.gcpolicy
- self.cpython_exc = cpython_exc
+ self.exception_policy = exception_policy
self.functionname = functionname
# apply the stackless transformation
if db.stacklesstransformer:
@@ -85,7 +85,7 @@
self.more_ll_values.append(link.llexitcase)
elif link.exitcase is not None:
mix.append(Constant(link.exitcase))
- if self.cpython_exc:
+ if self.exception_policy == "CPython":
v, exc_cleanup_ops = self.graph.exc_cleanup
mix.append(v)
for cleanupop in exc_cleanup_ops:
@@ -179,7 +179,7 @@
return self.db.get(ErrorValue(returnlltype))
def return_with_error(self):
- if self.cpython_exc:
+ if self.exception_policy == "CPython":
assert self.lltypemap(self.graph.getreturnvar()) == PyObjPtr
v, exc_cleanup_ops = self.graph.exc_cleanup
vanishing_exc_value = self.expr(v)
@@ -226,13 +226,15 @@
if len(block.exits) == 0:
assert len(block.inputargs) == 1
# regular return block
- if self.cpython_exc:
+ if self.exception_policy == "CPython":
assert self.lltypemap(self.graph.getreturnvar()) == PyObjPtr
yield 'if (RPyExceptionOccurred()) {'
yield '\tRPyConvertExceptionToCPython();'
yield '\treturn NULL;'
yield '}'
retval = self.expr(block.inputargs[0])
+ if self.exception_policy != "exc_helper":
+ yield 'RPY_DEBUG_RETURN();'
yield 'return %s;' % retval
continue
elif block.exitswitch is None:
@@ -717,12 +719,9 @@
c_string_constant(' '.join(format) + '\n\000'),
''.join([', ' + s for s in argv]))
- def OP_DEBUG_LOG_EXC(self, op):
- exc_type = self.expr(op.args[0])
- return 'RPY_LOG_EXC(%s);' % exc_type
-
def OP_DEBUG_ASSERT(self, op):
- return '/* debug_assert removed */'
+ return 'RPyAssert(%s, %s);' % (self.expr(op.args[0]),
+ c_string_constant(op.args[1].value))
def OP_DEBUG_FATALERROR(self, op):
# XXX
@@ -736,6 +735,13 @@
msg = 'RPyString_AsString(%s)' % self.expr(msg)
return 'fprintf(stderr, "%%s\\n", %s); abort();' % msg
+
+ def OP_INSTRUMENT_COUNT(self, op):
+ counter_label = op.args[1].value
+ self.db.instrument_ncounter = max(self.db.instrument_ncounter,
+ counter_label+1)
+ counter_label = self.expr(op.args[1])
+ return 'INSTRUMENT_COUNT(%s);' % counter_label
assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator)
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/genc.py (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/genc.py Thu Nov 23 12:03:10 2006
@@ -5,7 +5,7 @@
from pypy.translator.c.extfunc import pre_include_code_lines
from pypy.translator.gensupp import uniquemodulename, NameManager
from pypy.translator.tool.cbuild import compile_c_module
-from pypy.translator.tool.cbuild import build_executable, CCompiler
+from pypy.translator.tool.cbuild import build_executable, CCompiler, ProfOpt
from pypy.translator.tool.cbuild import import_module_from_directory
from pypy.translator.tool.cbuild import check_under_under_thread
from pypy.rpython.lltypesystem import lltype
@@ -132,6 +132,7 @@
if CBuilder.have___thread is None:
CBuilder.have___thread = check_under_under_thread()
if not self.standalone:
+ assert not self.config.translation.instrument
from pypy.translator.c.symboltable import SymbolTable
# XXX fix symboltable
#self.symboltable = SymbolTable()
@@ -140,6 +141,8 @@
exports = self.exports,
symboltable = self.symboltable)
else:
+ if self.config.translation.instrument:
+ defines['INSTRUMENT'] = 1
if CBuilder.have___thread:
if not self.config.translation.no__thread:
defines['USE___THREAD'] = 1
@@ -224,12 +227,19 @@
from distutils import sysconfig
python_inc = sysconfig.get_python_inc()
cc = self.config.translation.cc
- profopt = self.config.translation.profopt
+ profbased = None
+ if self.config.translation.instrumentctl is not None:
+ profbased = self.config.translation.instrumentctl
+ else:
+ profopt = self.config.translation.profopt
+ if profopt is not None:
+ profbased = (ProfOpt, profopt)
+
return CCompiler(
[self.c_source_filename] + self.extrafiles,
include_dirs = [autopath.this_dir, python_inc] + extra_includes,
libraries = self.libraries,
- compiler_exe = cc, profopt = profopt)
+ compiler_exe = cc, profbased = profbased)
def compile(self):
assert self.c_source_filename
@@ -641,6 +651,13 @@
gen_startupcode(f, database)
f.close()
+
+ if 'INSTRUMENT' in defines:
+ fi = incfilename.open('a')
+ n = database.instrument_ncounter
+ print >>fi, "#define INSTRUMENT_NCOUNTER %d" % n
+ fi.close()
+
return filename, sg.getextrafiles()
@@ -842,10 +859,13 @@
\trm -f $(OBJECTS) $(TARGET)
debug:
-\tmake CFLAGS="-g"
+\tmake CFLAGS="-g -DRPY_ASSERT"
debug_exc:
-\tmake CFLAGS="-g -DDO_LOG_EXC"
+\tmake CFLAGS="-g -DRPY_ASSERT -DDO_LOG_EXC"
+
+debug_mem:
+\tmake CFLAGS="-g -DRPY_ASSERT -DNO_OBMALLOC"
profile:
\tmake CFLAGS="-pg $(CFLAGS)" LDFLAGS="-pg $(LDFLAGS)"
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/node.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/node.py (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/node.py Thu Nov 23 12:03:10 2006
@@ -698,8 +698,9 @@
raise ValueError, "trying to compile suggested primitive %r" % (
fnobj._callable,)
elif hasattr(fnobj, 'graph'):
- cpython_exc = getattr(fnobj, 'exception_policy', None) == "CPython"
- return [FunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname)]
+ exception_policy = getattr(fnobj, 'exception_policy', None)
+ return [FunctionCodeGenerator(fnobj.graph, db, exception_policy,
+ functionname)]
elif getattr(fnobj, 'external', None) == 'C':
# deprecated case
if hasattr(fnobj, 'includes'):
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/src/exception.h
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/src/exception.h (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/src/exception.h Thu Nov 23 12:03:10 2006
@@ -6,7 +6,9 @@
PyObject *RPythonError;
#endif
-#define RPY_LOG_EXC(exc_type)
+/* just a renaming, unless DO_LOG_EXC is set */
+#define RPyExceptionOccurred RPyExceptionOccurred1
+#define RPY_DEBUG_RETURN() /* nothing */
#ifndef PyExceptionClass_Check /* Python < 2.5 */
# define PyExceptionClass_Check(x) PyClass_Check(x)
@@ -21,13 +23,27 @@
/******************************************************************/
#ifdef DO_LOG_EXC
-#undef RPY_LOG_EXC
-#define RPY_LOG_EXC(exc_type) if(exc_type) { \
- fprintf(stderr, "propagating %s:%ld %s %s\n", \
- __FILE__, __LINE__, __FUNCTION__, \
- exc_type->ov_name->items); \
+#undef RPyExceptionOccurred
+#undef RPY_DEBUG_RETURN
+#define RPyExceptionOccurred() RPyDebugException(" noticing a")
+#define RPY_DEBUG_RETURN() RPyDebugException("leaving with")
+#define RPyDebugException(msg) ( \
+ RPyExceptionOccurred1() \
+ ? (RPyDebugReturnShowException(msg, __FILE__, __LINE__, __FUNCTION__), 1) \
+ : 0 \
+ )
+void RPyDebugReturnShowException(const char *msg, const char *filename,
+ long lineno, const char *functionname);
+#ifndef PYPY_NOT_MAIN_FILE
+void RPyDebugReturnShowException(const char *msg, const char *filename,
+ long lineno, const char *functionname)
+{
+ fprintf(stderr, "%s %s: %s:%ld %s\n", msg,
+ RPyFetchExceptionType()->ov_name->items,
+ filename, lineno, functionname);
}
#endif
+#endif /* DO_LOG_EXC */
/* Hint: functions and macros not defined here, like RPyRaiseException,
come from exctransformer via the table in extfunc.py. */
@@ -109,7 +125,7 @@
#else /* non-RPython version of exceptions, using CPython only */
/******************************************************************/
-#define RPyExceptionOccurred() PyErr_Occurred()
+#define RPyExceptionOccurred1() PyErr_Occurred()
#define RPyRaiseException(etype, evalue) PyErr_Restore(etype, evalue, NULL)
#define RPyFetchException(etypevar, evaluevar, ignored) do { \
PyObject *__tb; \
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/src/g_include.h
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/src/g_include.h (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/src/g_include.h Thu Nov 23 12:03:10 2006
@@ -30,6 +30,8 @@
#include "src/float.h"
#include "src/address.h"
+#include "src/instrument.h"
+
/* optional assembler bits */
#if defined(__GNUC__) && defined(__i386__)
# include "src/asm_gcc_x86.h"
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/src/main.h
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/src/main.h (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/src/main.h Thu Nov 23 12:03:10 2006
@@ -20,6 +20,9 @@
char *errmsg;
int i, exitcode;
RPyListOfString *list;
+
+ instrument_setup();
+
errmsg = RPython_StartupCode();
if (errmsg) goto error;
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/src/obmalloc.c
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/src/obmalloc.c (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/src/obmalloc.c Thu Nov 23 12:03:10 2006
@@ -430,7 +430,7 @@
if (bp == NULL)
return NULL;
-#ifdef PYMALLOC_DEBUG
+#if 0 /* XXX removed for PyPy - #ifdef PYMALLOC_DEBUG */
if (Py_GETENV("PYTHONMALLOCSTATS"))
_PyObject_DebugMallocStats();
#endif
@@ -894,6 +894,16 @@
* it wraps a real allocator, adding extra debugging info to the memory blocks.
*/
+/* XXX added for PyPy for stand-alone usage */
+void Py_FatalError(const char *msg)
+{
+ fprintf(stderr, "Py_FatalError() called in obmalloc!\n%s\n", msg);
+ exit(1);
+}
+#define PyOS_snprintf snprintf
+/* end of XXX */
+
+
/* Special bytes broadcast into debug memory blocks at appropriate times.
* Strings of these are unlikely to be valid addresses, floats, ints or
* 7-bit ASCII.
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/src/standalone.h
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/src/standalone.h (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/src/standalone.h Thu Nov 23 12:03:10 2006
@@ -5,8 +5,16 @@
#include <math.h>
#ifndef PYPY_NOT_MAIN_FILE
-#ifndef WITH_PYMALLOC
-#define WITH_PYMALLOC
+
+#ifdef NO_OBMALLOC
+void *PyObject_Malloc(size_t n) { return malloc(n); }
+void *PyObject_Realloc(void *p, size_t n) { return realloc(p, n); }
+void PyObject_Free(void *p) { if (p) { *((int*)p) = 0xDDDDDDDD; } free(p); }
+#else
+# ifndef WITH_PYMALLOC
+# define WITH_PYMALLOC
+# endif
+# include "obmalloc.c"
#endif
-#include "obmalloc.c"
+
#endif
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/src/support.h
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/src/support.h (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/src/support.h Thu Nov 23 12:03:10 2006
@@ -25,6 +25,26 @@
memcpy(itemsarray->items, PyString_AS_STRING(s), \
itemsarray->length)
+#ifdef RPY_ASSERT
+# define RPyAssert(x, msg) \
+ if (!(x)) RPyAssertFailed(__FILE__, __LINE__, __FUNCTION__, msg)
+
+void RPyAssertFailed(const char* filename, long lineno,
+ const char* function, const char *msg);
+# ifndef PYPY_NOT_MAIN_FILE
+void RPyAssertFailed(const char* filename, long lineno,
+ const char* function, const char *msg) {
+ fprintf(stderr,
+ "PyPy assertion failed at %s:%d:\n"
+ "in %s: %s\n",
+ filename, lineno, function, msg);
+ abort();
+}
+# endif
+#else
+# define RPyAssert(x, msg) /* nothing */
+#endif
+
#ifdef __RPyListOfString_New /* :-( */
# define HAVE_RPY_LIST_OF_STRING
#endif
Modified: pypy/branch/mininal-c-backend/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/c/test/test_standalone.py (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/c/test/test_standalone.py Thu Nov 23 12:03:10 2006
@@ -1,7 +1,10 @@
+import py
+import sys, os
+
from pypy.translator.translator import TranslationContext
from pypy.translator.c.genc import CStandaloneBuilder
from pypy.annotation.listdef import s_list_of_strings
-import os
+from pypy.tool.udir import udir
def test_hello_world():
@@ -47,3 +50,61 @@
'''argument lengths: [2, 5]\n''')
# NB. RPython has only str, not repr, so str() on a list of strings
# gives the strings unquoted in the list
+
+def test_counters():
+ if sys.platform == 'win32':
+ py.test.skip("instrument counters support is unix only for now")
+ from pypy.rpython.lltypesystem import lltype
+ from pypy.rpython.lltypesystem.lloperation import llop
+ def entry_point(argv):
+ llop.instrument_count(lltype.Void, 'test', 2)
+ llop.instrument_count(lltype.Void, 'test', 1)
+ llop.instrument_count(lltype.Void, 'test', 1)
+ llop.instrument_count(lltype.Void, 'test', 2)
+ llop.instrument_count(lltype.Void, 'test', 1)
+ return 0
+ t = TranslationContext()
+ t.config.translation.instrument = True
+ t.buildannotator().build_types(entry_point, [s_list_of_strings])
+ t.buildrtyper().specialize()
+
+ cbuilder = CStandaloneBuilder(t, entry_point, config=t.config) # xxx
+ cbuilder.generate_source()
+ cbuilder.compile()
+
+ counters_fname = udir.join("_counters_")
+ os.putenv('_INSTRUMENT_COUNTERS', str(counters_fname))
+ try:
+ data = cbuilder.cmdexec()
+ finally:
+ os.unsetenv('_INSTRUMENT_COUNTERS')
+
+ f = counters_fname.open('rb')
+ counters_data = f.read()
+ f.close()
+
+ import struct
+ counters = struct.unpack("LLL", counters_data)
+
+ assert counters == (0,3,2)
+
+def test_prof_inline():
+ if sys.platform == 'win32':
+ py.test.skip("instrumentation support is unix only for now")
+ def add(a,b):
+ return a + b - b + b - b + b - b + b - b + b - b + b - b + b
+ def entry_point(argv):
+ tot = 0
+ x = int(argv[1])
+ while x > 0:
+ tot = add(tot, x)
+ x -= 1
+ os.write(1, str(tot))
+ return 0
+ from pypy.translator.interactive import Translation
+ t = Translation(entry_point, backend='c', standalone=True)
+ t.backendopt(profile_based_inline="500")
+ exe = t.compile()
+ out = py.process.cmdexec("%s 500" % exe)
+ assert int(out) == 500*501/2
+
Modified: pypy/branch/mininal-c-backend/pypy/translator/driver.py
==============================================================================
--- pypy/branch/mininal-c-backend/pypy/translator/driver.py (original)
+++ pypy/branch/mininal-c-backend/pypy/translator/driver.py Thu Nov 23 12:03:10 2006
@@ -51,6 +51,31 @@
def backend_to_typesystem(backend):
return _BACKEND_TO_TYPESYSTEM.get(backend, 'ootype')
+
+class Instrument(Exception):
+ pass
+
+
+class ProfInstrument(object):
+ name = "profinstrument"
+ def __init__(self, datafile, compiler):
+ self.datafile = datafile
+ self.compiler = compiler
+
+ def first(self):
+ self.compiler._build()
+
+ def probe(self, exe, args):
+ from py.compat import subprocess
+ env = os.environ.copy()
+ env['_INSTRUMENT_COUNTERS'] = str(self.datafile)
+ subprocess.call([exe, args], env=env)
+
+ def after(self):
+ # xxx
+ os._exit(0)
+
+
class TranslationDriver(SimpleTaskEngine):
def __init__(self, setopts=None, default_goal=None, disable=[],
@@ -183,6 +208,40 @@
self.entry_point = entry_point
self.translator = translator
+ self.translator.driver_instrument_result = self.instrument_result
+
+ def instrument_result(self, args):
+ backend, ts = self.get_backend_and_type_system()
+ if backend != 'c' or sys.platform == 'win32':
+ raise Exception("instrumentation requires the c backend"
+ " and unix for now")
+ from pypy.tool.udir import udir
+
+ datafile = udir.join('_instrument_counters')
+ makeProfInstrument = lambda compiler: ProfInstrument(datafile, compiler)
+
+ pid = os.fork()
+ if pid == 0:
+ # child compiling and running with instrumentation
+ self.config.translation.instrument = True
+ self.config.translation.instrumentctl = (makeProfInstrument,
+ args)
+ raise Instrument
+ else:
+ pid, status = os.waitpid(pid, 0)
+ if os.WIFEXITED(status):
+ status = os.WEXITSTATUS(status)
+ if status != 0:
+ raise Exception, "instrumentation child failed: %d" % status
+ else:
+ raise Exception, "instrumentation child aborted"
+ import array, struct
+ n = datafile.size()//struct.calcsize('L')
+ datafile = datafile.open('rb')
+ counters = array.array('L')
+ counters.fromfile(datafile, n)
+ datafile.close()
+ return counters
def info(self, msg):
log.info(msg)
@@ -194,9 +253,16 @@
return
else:
self.log.info("%s..." % title)
- res = func()
+ instrument = False
+ try:
+ res = func()
+ except Instrument:
+ instrument = True
if not func.task_idempotent:
self.done[goal] = True
+ if instrument:
+ self.proceed('compile')
+ assert False, 'we should not get here'
return res
def task_annotate(self):
More information about the Pypy-commit
mailing list