[pypy-svn] r76432 - in pypy/branch/x86-64-jit-backend: . lib-python/modified-2.5.2/ctypes lib_pypy/_ctypes lib_pypy/pypy_test pypy/interpreter/astcompiler pypy/interpreter/test pypy/jit/backend/x86 pypy/jit/backend/x86/test pypy/jit/metainterp pypy/jit/metainterp/test pypy/module/__builtin__ pypy/module/_ast pypy/module/_ast/test pypy/objspace/std pypy/objspace/std/test pypy/rlib pypy/rlib/test pypy/rpython/lltypesystem
jcreigh at codespeak.net
jcreigh at codespeak.net
Mon Aug 2 17:26:56 CEST 2010
Author: jcreigh
Date: Mon Aug 2 17:26:53 2010
New Revision: 76432
Modified:
pypy/branch/x86-64-jit-backend/ (props changed)
pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/ctypes/__init__.py
pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/__init__.py
pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/array.py
pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/builtin.py
pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/primitive.py
pypy/branch/x86-64-jit-backend/lib_pypy/pypy_test/test_ctypes_support.py
pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/assemble.py
pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/codegen.py
pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/consts.py
pypy/branch/x86-64-jit-backend/pypy/interpreter/test/test_compiler.py
pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py
pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py
pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py
pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeopt.py
pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop.py
pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop_spec.py
pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizeopt.py
pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/compiling.py
pypy/branch/x86-64-jit-backend/pypy/module/_ast/__init__.py
pypy/branch/x86-64-jit-backend/pypy/module/_ast/test/test_ast.py
pypy/branch/x86-64-jit-backend/pypy/objspace/std/callmethod.py
pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_callmethod.py
pypy/branch/x86-64-jit-backend/pypy/rlib/objectmodel.py
pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_objectmodel.py
pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rstr.py
Log:
merged changes from trunk through r76430
Modified: pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/ctypes/__init__.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/ctypes/__init__.py (original)
+++ pypy/branch/x86-64-jit-backend/lib-python/modified-2.5.2/ctypes/__init__.py Mon Aug 2 17:26:53 2010
@@ -471,7 +471,7 @@
# functions
-from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
+from _ctypes import _memmove_addr, _memset_addr, _cast_addr
## void *memmove(void *, const void *, size_t);
memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
@@ -490,24 +490,34 @@
def cast(obj, typ):
return _cast(obj, obj, typ)
-_string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
+try:
+ from _ctypes import _string_at_addr
+except ImportError:
+ from _ctypes import _string_at
+else:
+ _string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
+
def string_at(ptr, size=-1):
"""string_at(addr[, size]) -> string
Return the string at addr."""
return _string_at(ptr, size)
+def wstring_at(ptr, size=-1):
+ """wstring_at(addr[, size]) -> string
+
+ Return the string at addr."""
+ return _wstring_at(ptr, size)
+
try:
from _ctypes import _wstring_at_addr
except ImportError:
- pass
+ try:
+ from _ctypes import _wstring_at
+ except ImportError:
+ del wstring_at
else:
_wstring_at = CFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
- def wstring_at(ptr, size=-1):
- """wstring_at(addr[, size]) -> string
-
- Return the string at addr."""
- return _wstring_at(ptr, size)
if _os.name in ("nt", "ce"): # COM stuff
Modified: pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/__init__.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/__init__.py (original)
+++ pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/__init__.py Mon Aug 2 17:26:53 2010
@@ -7,8 +7,8 @@
from _ctypes.dll import dlopen
from _ctypes.structure import Structure
from _ctypes.array import Array
-from _ctypes.builtin import _memmove_addr, _string_at_addr, _memset_addr,\
- set_conversion_mode, _wstring_at_addr
+from _ctypes.builtin import _memmove_addr, _string_at, _memset_addr,\
+ set_conversion_mode, _wstring_at
from _ctypes.union import Union
import os as _os
Modified: pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/array.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/array.py (original)
+++ pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/array.py Mon Aug 2 17:26:53 2010
@@ -4,7 +4,6 @@
from _ctypes.basics import _CData, cdata_from_address, _CDataMeta, sizeof
from _ctypes.basics import keepalive_key, store_reference, ensure_objects
from _ctypes.basics import CArgObject
-from _ctypes.builtin import _string_at_addr, _wstring_at_addr
def _create_unicode(buffer, maxlength):
res = []
Modified: pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/builtin.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/builtin.py (original)
+++ pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/builtin.py Mon Aug 2 17:26:53 2010
@@ -8,10 +8,10 @@
_memmove_addr = _rawffi.get_libc().getaddressindll('memmove')
_memset_addr = _rawffi.get_libc().getaddressindll('memset')
-def _string_at_addr(addr, lgt):
+def _string_at(addr, lgt):
# address here can be almost anything
import ctypes
- arg = ctypes.c_char_p._CData_value(addr)
+ arg = ctypes.c_void_p._CData_value(addr)
return _rawffi.charp2rawstring(arg, lgt)
def set_conversion_mode(encoding, errors):
@@ -20,9 +20,9 @@
ConvMode.encoding = encoding
return old_cm
-def _wstring_at_addr(addr, lgt):
+def _wstring_at(addr, lgt):
import ctypes
- arg = ctypes.c_wchar_p._CData_value(addr)
+ arg = ctypes.c_void_p._CData_value(addr)
# XXX purely applevel
if lgt == -1:
lgt = sys.maxint
Modified: pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/primitive.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/primitive.py (original)
+++ pypy/branch/x86-64-jit-backend/lib_pypy/_ctypes/primitive.py Mon Aug 2 17:26:53 2010
@@ -86,6 +86,8 @@
return value
if isinstance(value, _Pointer):
return cls.from_address(value._buffer.buffer)
+ if isinstance(value, (int, long)):
+ return cls(value)
FROM_PARAM_BY_TYPE = {
'z': from_param_char_p,
@@ -141,13 +143,13 @@
result.value = property(_getvalue, _setvalue)
elif tp == 'Z':
# c_wchar_p
- from _ctypes import Array, _Pointer, _wstring_at_addr
+ from _ctypes import Array, _Pointer, _wstring_at
def _getvalue(self):
addr = self._buffer[0]
if addr == 0:
return None
else:
- return _wstring_at_addr(addr, -1)
+ return _wstring_at(addr, -1)
def _setvalue(self, value):
if isinstance(value, basestring):
@@ -216,14 +218,14 @@
SysAllocStringLen = windll.oleaut32.SysAllocStringLen
SysStringLen = windll.oleaut32.SysStringLen
SysFreeString = windll.oleaut32.SysFreeString
- from _ctypes import _wstring_at_addr
+ from _ctypes import _wstring_at
def _getvalue(self):
addr = self._buffer[0]
if addr == 0:
return None
else:
size = SysStringLen(addr)
- return _wstring_at_addr(addr, size)
+ return _wstring_at(addr, size)
def _setvalue(self, value):
if isinstance(value, basestring):
@@ -254,18 +256,21 @@
from_address = cdata_from_address
def from_param(self, value):
+ if isinstance(value, self):
+ return value
+
from_param_f = FROM_PARAM_BY_TYPE.get(self._type_)
if from_param_f:
res = from_param_f(self, value)
if res is not None:
return res
-
- if isinstance(value, self):
- return value
- try:
- return self(value)
- except (TypeError, ValueError):
- return super(SimpleType, self).from_param(value)
+ else:
+ try:
+ return self(value)
+ except (TypeError, ValueError):
+ pass
+
+ return super(SimpleType, self).from_param(value)
def _CData_output(self, resbuffer, base=None, index=-1):
output = super(SimpleType, self)._CData_output(resbuffer, base, index)
Modified: pypy/branch/x86-64-jit-backend/lib_pypy/pypy_test/test_ctypes_support.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/lib_pypy/pypy_test/test_ctypes_support.py (original)
+++ pypy/branch/x86-64-jit-backend/lib_pypy/pypy_test/test_ctypes_support.py Mon Aug 2 17:26:53 2010
@@ -20,3 +20,14 @@
assert get_errno() != 0
set_errno(0)
assert get_errno() == 0
+
+def test_argument_conversion_and_checks():
+ import ctypes
+ libc = ctypes.cdll.LoadLibrary("libc.so.6")
+ libc.strlen.argtypes = ctypes.c_char_p,
+ libc.strlen.restype = ctypes.c_size_t
+ assert libc.strlen("eggs") == 4
+
+ # Should raise ArgumentError, not segfault
+ py.test.raises(ctypes.ArgumentError, libc.strlen, False)
+
Modified: pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/assemble.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/assemble.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/assemble.py Mon Aug 2 17:26:53 2010
@@ -566,22 +566,22 @@
return (oparg % 256) + 2 * (oparg / 256)
def _compute_CALL_FUNCTION(arg):
- return _num_args(arg)
+ return -_num_args(arg)
def _compute_CALL_FUNCTION_VAR(arg):
- return _num_args(arg) - 1
+ return -_num_args(arg) - 1
def _compute_CALL_FUNCTION_KW(arg):
- return _num_args(arg) - 1
+ return -_num_args(arg) - 1
def _compute_CALL_FUNCTION_VAR_KW(arg):
- return _num_args(arg) - 2
+ return -_num_args(arg) - 2
def _compute_CALL_LIKELY_BUILTIN(arg):
return -(arg & 0xFF) + 1
def _compute_CALL_METHOD(arg):
- return -arg - 1
+ return -_num_args(arg) - 1
_stack_effect_computers = {}
Modified: pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/codegen.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/codegen.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/codegen.py Mon Aug 2 17:26:53 2010
@@ -960,9 +960,12 @@
elif call_type == 3:
op = ops.CALL_FUNCTION_VAR_KW
self.emit_op_arg(op, arg)
+
+ def _call_has_no_star_args(self, call):
+ return not call.starargs and not call.kwargs
def _call_has_simple_args(self, call):
- return not call.starargs and not call.kwargs and not call.keywords
+ return self._call_has_no_star_args(call) and not call.keywords
def _optimize_builtin_call(self, call):
if not self.space.config.objspace.opcodes.CALL_LIKELY_BUILTIN or \
@@ -988,7 +991,7 @@
def _optimize_method_call(self, call):
if not self.space.config.objspace.opcodes.CALL_METHOD or \
- not self._call_has_simple_args(call) or \
+ not self._call_has_no_star_args(call) or \
not isinstance(call.func, ast.Attribute):
return False
attr_lookup = call.func
@@ -1000,7 +1003,12 @@
arg_count = len(call.args)
else:
arg_count = 0
- self.emit_op_arg(ops.CALL_METHOD, arg_count)
+ if call.keywords:
+ self.visit_sequence(call.keywords)
+ kwarg_count = len(call.keywords)
+ else:
+ kwarg_count = 0
+ self.emit_op_arg(ops.CALL_METHOD, (kwarg_count << 8) | arg_count)
return True
def _listcomp_generator(self, list_name, gens, gen_index, elt):
Modified: pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/consts.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/consts.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/interpreter/astcompiler/consts.py Mon Aug 2 17:26:53 2010
@@ -18,4 +18,4 @@
PyCF_SOURCE_IS_UTF8 = 0x0100
PyCF_DONT_IMPLY_DEDENT = 0x0200
-PyCF_AST_ONLY = 0x0400
+PyCF_ONLY_AST = 0x0400
Modified: pypy/branch/x86-64-jit-backend/pypy/interpreter/test/test_compiler.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/interpreter/test/test_compiler.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/interpreter/test/test_compiler.py Mon Aug 2 17:26:53 2010
@@ -4,6 +4,7 @@
from pypy.interpreter.pycode import PyCode
from pypy.interpreter.error import OperationError
from pypy.interpreter.argument import Arguments
+from pypy.conftest import gettestobjspace
class BaseTestCompiler:
def setup_method(self, method):
@@ -848,14 +849,38 @@
import StringIO, sys, dis
s = StringIO.StringIO()
+ out = sys.stdout
sys.stdout = s
try:
dis.dis(code)
finally:
- sys.stdout = sys.__stdout__
+ sys.stdout = out
output = s.getvalue()
assert "LOAD_GLOBAL" not in output
+class AppTestCallMethod(object):
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{'objspace.opcodes.CALL_METHOD': True})
+
+ def test_call_method_kwargs(self):
+ source = """def _f(a):
+ return a.f(a=a)
+ """
+ exec source
+ code = _f.func_code
+
+ import StringIO, sys, dis
+ s = StringIO.StringIO()
+ out = sys.stdout
+ sys.stdout = s
+ try:
+ dis.dis(code)
+ finally:
+ sys.stdout = out
+ output = s.getvalue()
+ assert "CALL_METHOD" in output
+
+
class AppTestExceptions:
def test_indentation_error(self):
source = """if 1:
Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/assembler.py Mon Aug 2 17:26:53 2010
@@ -1,4 +1,4 @@
-import sys
+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,\
@@ -30,6 +30,7 @@
from pypy.rlib.debug import debug_print
from pypy.rlib import rgc
from pypy.jit.backend.x86.jump import remap_frame_layout
+from pypy.rlib.streamio import open_file_as_stream
# darwin requires the stack to be 16 bytes aligned on calls. Same for gcc 4.5.0,
# better safe than sorry
@@ -154,6 +155,7 @@
mc_size = MachineCodeBlockWrapper.MC_DEFAULT_SIZE
_float_constants = None
_regalloc = None
+ _output_loop_log = None
def __init__(self, cpu, translate_support_code=False,
failargs_limit=1000):
@@ -168,18 +170,26 @@
self.fail_boxes_ptr = values_array(llmemory.GCREF, failargs_limit)
self.fail_boxes_float = values_array(lltype.Float, failargs_limit)
self.fail_ebp = 0
+ self.loop_run_counter = values_array(lltype.Signed, 10000)
+ self.loop_names = []
+ # if we have 10000 loops, we have some other problems I guess
self.float_const_neg_addr = 0
self.float_const_abs_addr = 0
self.malloc_fixedsize_slowpath1 = 0
self.malloc_fixedsize_slowpath2 = 0
self.pending_guard_tokens = []
self.setup_failure_recovery()
+ self._loop_counter = 0
+ self._debug = False
def leave_jitted_hook(self):
ptrs = self.fail_boxes_ptr.ar
llop.gc_assume_young_pointers(lltype.Void,
llmemory.cast_ptr_to_adr(ptrs))
+ def set_debug(self, v):
+ self._debug = v
+
def make_sure_mc_exists(self):
if self.mc is None:
# the address of the function called by 'new'
@@ -209,6 +219,22 @@
self._build_float_constants()
if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
self._build_malloc_fixedsize_slowpath()
+ s = os.environ.get('PYPYLOG')
+ if s:
+ if s.find(':') != -1:
+ s = s.split(':')[-1]
+ self.set_debug(True)
+ self._output_loop_log = s + ".count"
+
+ def finish_once(self):
+ if self._debug:
+ output_log = self._output_loop_log
+ assert output_log is not None
+ f = open_file_as_stream(output_log, "w")
+ for i in range(self._loop_counter):
+ f.write(self.loop_names[i] + ":" +
+ str(self.loop_run_counter.getitem(i)) + "\n")
+ f.close()
def _build_float_constants(self):
# 44 bytes: 32 bytes for the data, and up to 12 bytes for alignment
@@ -267,9 +293,9 @@
# Arguments should be unique
assert len(set(inputargs)) == len(inputargs)
+ self.make_sure_mc_exists()
funcname = self._find_debug_merge_point(operations)
- self.make_sure_mc_exists()
regalloc = RegAlloc(self, self.cpu.translate_support_code)
arglocs = regalloc.prepare_loop(inputargs, operations, looptoken)
@@ -302,9 +328,9 @@
# Arguments should be unique
assert len(set(inputargs)) == len(inputargs)
+ self.make_sure_mc_exists()
funcname = self._find_debug_merge_point(operations)
- self.make_sure_mc_exists()
arglocs = self.rebuild_faillocs_from_descr(
faildescr._x86_failure_recovery_bytecode)
if not we_are_translated():
@@ -357,10 +383,18 @@
self.mc.done()
def _find_debug_merge_point(self, operations):
+
for op in operations:
if op.opnum == rop.DEBUG_MERGE_POINT:
- return op.args[0]._get_str()
- return ""
+ funcname = op.args[0]._get_str()
+ break
+ else:
+ funcname = "<loop %d>" % self._loop_counter
+ # invent the counter, so we don't get too confused
+ if self._debug:
+ self.loop_names.append(funcname)
+ self._loop_counter += 1
+ return funcname
def patch_jump_for_descr(self, faildescr, adr_new_target):
adr_jump_offset = faildescr._x86_adr_jump_offset
@@ -384,6 +418,15 @@
def _assemble(self, regalloc, operations):
self._regalloc = regalloc
+ if self._debug:
+ # before doing anything, let's increase a counter
+ # we need one register free (a bit of a hack, but whatever)
+ self.mc.PUSH(eax)
+ adr = self.loop_run_counter.get_addr_for_num(self._loop_counter - 1)
+ self.mc.MOV(eax, heap(adr))
+ self.mc.ADD(eax, imm(1))
+ self.mc.MOV(heap(adr), eax)
+ self.mc.POP(eax)
regalloc.walk_operations(operations)
self.mc.done()
if we_are_translated() or self.cpu.dont_keepalive_stuff:
Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/runner.py Mon Aug 2 17:26:53 2010
@@ -46,6 +46,7 @@
self.profile_agent.startup()
def finish_once(self):
+ self.assembler.finish_once()
self.profile_agent.shutdown()
def compile_loop(self, inputargs, operations, looptoken):
Modified: pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/jit/backend/x86/test/test_runner.py Mon Aug 2 17:26:53 2010
@@ -9,8 +9,11 @@
from pypy.jit.metainterp.resoperation import rop
from pypy.jit.metainterp.executor import execute
from pypy.jit.backend.test.runner_test import LLtypeBackendTest
+from pypy.jit.metainterp.test.oparser import parse
+from pypy.tool.udir import udir
import ctypes
import sys
+import os
CPU = getcpuclass()
@@ -453,3 +456,36 @@
# Really just a sanity check. We're actually interested in
# whether the test segfaults.
assert self.cpu.get_latest_value_int(0) == finished.value
+
+
+class TestDebuggingAssembler(object):
+ def setup_method(self, meth):
+ self.pypylog = os.environ.get('PYPYLOG', None)
+ self.logfile = str(udir.join('x86_runner.log'))
+ os.environ['PYPYLOG'] = "mumble:" + self.logfile
+ self.cpu = CPU(rtyper=None, stats=FakeStats())
+
+ def teardown_method(self, meth):
+ if self.pypylog is not None:
+ os.environ['PYPYLOG'] = self.pypylog
+
+ def test_debugger_on(self):
+ loop = """
+ [i0]
+ debug_merge_point('xyz')
+ i1 = int_add(i0, 1)
+ i2 = int_ge(i1, 10)
+ guard_false(i2) []
+ jump(i1)
+ """
+ ops = parse(loop)
+ self.cpu.assembler.set_debug(True)
+ self.cpu.compile_loop(ops.inputargs, ops.operations, ops.token)
+ self.cpu.set_future_value_int(0, 0)
+ self.cpu.execute_token(ops.token)
+ # check debugging info
+ assert self.cpu.assembler.loop_names == ["xyz"]
+ assert self.cpu.assembler.loop_run_counter.getitem(0) == 10
+ self.cpu.finish_once()
+ lines = py.path.local(self.logfile + ".count").readlines()
+ assert lines[0] == 'xyz:10\n'
Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeopt.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/optimizeopt.py Mon Aug 2 17:26:53 2010
@@ -1001,6 +1001,17 @@
self.make_equal_to(op.result, v1)
else:
return self.optimize_default(op)
+
+ def optimize_INT_ADD(self, op):
+ v1 = self.getvalue(op.args[0])
+ v2 = self.getvalue(op.args[1])
+ # If one side of the op is 0 the result is the other side.
+ if v1.is_constant() and v1.box.getint() == 0:
+ self.make_equal_to(op.result, v2)
+ elif v2.is_constant() and v2.box.getint() == 0:
+ self.make_equal_to(op.result, v1)
+ else:
+ self.optimize_default(op)
optimize_ops = _findall(Optimizer, 'optimize_')
Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop.py Mon Aug 2 17:26:53 2010
@@ -9,6 +9,10 @@
class LoopTest(object):
optimizer = OPTIMIZER_SIMPLE
+ automatic_promotion_result = {
+ 'int_add' : 6, 'int_gt' : 1, 'guard_false' : 1, 'jump' : 1,
+ 'guard_value' : 3
+ }
def meta_interp(self, f, args, policy=None):
return ll_meta_interp(f, args, optimizer=self.optimizer,
@@ -477,9 +481,9 @@
res = self.meta_interp(main_interpreter_loop, [1])
assert res == main_interpreter_loop(1)
self.check_loop_count(1)
- # XXX maybe later optimize guard_value away
- self.check_loops({'int_add' : 6, 'int_gt' : 1,
- 'guard_false' : 1, 'jump' : 1, 'guard_value' : 3})
+ # These loops do different numbers of ops based on which optimizer we
+ # are testing with.
+ self.check_loops(self.automatic_promotion_result)
def test_can_enter_jit_outside_main_loop(self):
myjitdriver = JitDriver(greens=[], reds=['i', 'j', 'a'])
Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop_spec.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop_spec.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_loop_spec.py Mon Aug 2 17:26:53 2010
@@ -5,6 +5,10 @@
class LoopSpecTest(test_loop.LoopTest):
optimizer = OPTIMIZER_FULL
+ automatic_promotion_result = {
+ 'int_add' : 3, 'int_gt' : 1, 'guard_false' : 1, 'jump' : 1,
+ 'guard_value' : 1
+ }
# ====> test_loop.py
Modified: pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizeopt.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/jit/metainterp/test/test_optimizeopt.py Mon Aug 2 17:26:53 2010
@@ -2063,6 +2063,28 @@
jump(i0)
"""
self.optimize_loop(ops, 'Not', expected)
+
+ ops = """
+ [i0]
+ i1 = int_add(i0, 0)
+ jump(i1)
+ """
+ expected = """
+ [i0]
+ jump(i0)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
+ ops = """
+ [i0]
+ i1 = int_add(0, i0)
+ jump(i1)
+ """
+ expected = """
+ [i0]
+ jump(i0)
+ """
+ self.optimize_loop(ops, 'Not', expected)
# ----------
Modified: pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/compiling.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/compiling.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/module/__builtin__/compiling.py Mon Aug 2 17:26:53 2010
@@ -38,7 +38,7 @@
str_ = space.str_w(w_source)
ec = space.getexecutioncontext()
- if flags & ~(ec.compiler.compiler_flags | consts.PyCF_AST_ONLY |
+ if flags & ~(ec.compiler.compiler_flags | consts.PyCF_ONLY_AST |
consts.PyCF_DONT_IMPLY_DEDENT | consts.PyCF_SOURCE_IS_UTF8):
raise OperationError(space.w_ValueError,
space.wrap("compile() unrecognized flags"))
@@ -53,7 +53,7 @@
"or 'eval' or 'single'"))
if ast_node is None:
- if flags & consts.PyCF_AST_ONLY:
+ if flags & consts.PyCF_ONLY_AST:
mod = ec.compiler.compile_to_ast(str_, filename, mode, flags)
return space.wrap(mod)
else:
Modified: pypy/branch/x86-64-jit-backend/pypy/module/_ast/__init__.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/module/_ast/__init__.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/module/_ast/__init__.py Mon Aug 2 17:26:53 2010
@@ -5,7 +5,7 @@
class Module(MixedModule):
interpleveldefs = {
- "PyCF_AST_ONLY" : "space.wrap(%s)" % consts.PyCF_AST_ONLY
+ "PyCF_ONLY_AST" : "space.wrap(%s)" % consts.PyCF_ONLY_AST
}
appleveldefs = {}
Modified: pypy/branch/x86-64-jit-backend/pypy/module/_ast/test/test_ast.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/module/_ast/test/test_ast.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/module/_ast/test/test_ast.py Mon Aug 2 17:26:53 2010
@@ -10,7 +10,7 @@
cls.w_get_ast = cls.space.appexec([], """():
def get_ast(source, mode="exec"):
import _ast as ast
- mod = compile(source, "<test>", mode, ast.PyCF_AST_ONLY)
+ mod = compile(source, "<test>", mode, ast.PyCF_ONLY_AST)
assert isinstance(mod, ast.mod)
return mod
return get_ast""")
Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/callmethod.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/objspace/std/callmethod.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/callmethod.py Mon Aug 2 17:26:53 2010
@@ -12,7 +12,7 @@
from pypy.interpreter import function
from pypy.objspace.descroperation import object_getattribute
-from pypy.rlib import rstack # for resume points
+from pypy.rlib import jit, rstack # for resume points
# This module exports two extra methods for StdObjSpaceFrame implementing
# the LOOKUP_METHOD and CALL_METHOD opcodes in an efficient way, as well
@@ -56,16 +56,42 @@
f.pushvalue(w_value)
f.pushvalue(None)
-def CALL_METHOD(f, nargs, *ignored):
- # 'nargs' is the argument count excluding the implicit 'self'
- w_self = f.peekvalue(nargs)
- w_callable = f.peekvalue(nargs + 1)
- n = nargs + (w_self is not None)
- try:
- w_result = f.space.call_valuestack(w_callable, n, f)
- rstack.resume_point("CALL_METHOD", f, nargs, returns=w_result)
- finally:
- f.dropvalues(nargs + 2)
+ at jit.unroll_safe
+def CALL_METHOD(f, oparg, *ignored):
+ # opargs contains the arg, and kwarg count, excluding the implicit 'self'
+ n_args = oparg & 0xff
+ n_kwargs = (oparg >> 8) & 0xff
+ w_self = f.peekvalue(n_args + (2 * n_kwargs))
+ w_callable = f.peekvalue(n_args + (2 * n_kwargs) + 1)
+ n = n_args + (w_self is not None)
+
+ if not n_kwargs:
+ try:
+ w_result = f.space.call_valuestack(w_callable, n, f)
+ rstack.resume_point("CALL_METHOD_no_kwargs", f, n_args, returns=w_result)
+ finally:
+ f.dropvalues(n_args + 2)
+ else:
+ keywords = [None] * n_kwargs
+ keywords_w = [None] * n_kwargs
+ while True:
+ n_kwargs -= 1
+ if n_kwargs < 0:
+ break
+ w_value = f.popvalue()
+ w_key = f.popvalue()
+ key = f.space.str_w(w_key)
+ keywords[n_kwargs] = key
+ keywords_w[n_kwargs] = w_value
+
+ arguments = f.popvalues(n)
+ args = f.argument_factory(arguments, keywords, keywords_w, None, None)
+
+ try:
+ w_result = f.space.call_args(w_callable, args)
+ rstack.resume_point("CALL_METHOD", f, w_self, returns=w_result)
+ finally:
+ f.dropvalues(1 + (w_self is None))
f.pushvalue(w_result)
Modified: pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_callmethod.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_callmethod.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/objspace/std/test/test_callmethod.py Mon Aug 2 17:26:53 2010
@@ -106,6 +106,15 @@
else:
raise Exception("did not raise?")
"""
+
+ def test_kwargs(self):
+ exec """if 1:
+ class C(object):
+ def f(self, a):
+ return a + 2
+
+ assert C().f(a=3) == 5
+ """
class AppTestCallMethodWithGetattributeShortcut(AppTestCallMethod):
Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/objectmodel.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/rlib/objectmodel.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/rlib/objectmodel.py Mon Aug 2 17:26:53 2010
@@ -26,7 +26,7 @@
by a call result then.
"""
def decorated_func(func):
- func._annspecialcase_ = 'specialize:memo()'
+ func._annspecialcase_ = 'specialize:memo'
return func
return decorated_func
@@ -63,7 +63,7 @@
for example). Same warnings about exponential behavior apply.
"""
def decorated_func(func):
- func._annspecialcase_ = 'specialize:ll()'
+ func._annspecialcase_ = 'specialize:ll'
return func
return decorated_func
@@ -82,6 +82,17 @@
specialize = _Specialize()
+def enforceargs(*args):
+ """ Decorate a function with forcing of RPython-level types on arguments.
+ None means no enforcing.
+
+ XXX shouldn't we also add asserts in function body?
+ """
+ def decorator(f):
+ f._annenforceargs_ = args
+ return f
+ return decorator
+
# ____________________________________________________________
class Symbolic(object):
Modified: pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_objectmodel.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_objectmodel.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/rlib/test/test_objectmodel.py Mon Aug 2 17:26:53 2010
@@ -404,6 +404,13 @@
assert f._annspecialcase_ == 'specialize:arg(1)'
+def test_enforceargs_decorator():
+ @enforceargs(int, str, None)
+ def f(a, b, c):
+ pass
+
+ assert f._annenforceargs_ == (int, str, None)
+
def getgraph(f, argtypes):
from pypy.translator.translator import TranslationContext, graphof
from pypy.translator.backendopt.all import backend_optimizations
Modified: pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rstr.py (original)
+++ pypy/branch/x86-64-jit-backend/pypy/rpython/lltypesystem/rstr.py Mon Aug 2 17:26:53 2010
@@ -2,7 +2,7 @@
from pypy.tool.pairtype import pairtype
from pypy.rpython.error import TyperError
from pypy.rlib.objectmodel import malloc_zero_filled, we_are_translated
-from pypy.rlib.objectmodel import _hash_string
+from pypy.rlib.objectmodel import _hash_string, enforceargs
from pypy.rlib.debug import ll_assert
from pypy.rlib.jit import purefunction
from pypy.rpython.robject import PyObjRepr, pyobj_repr
@@ -56,6 +56,7 @@
llmemory.itemoffsetof(TP.chars, 0) +
llmemory.sizeof(CHAR_TP) * item)
+ @enforceargs(None, None, int, int, int)
def copy_string_contents(src, dst, srcstart, dststart, length):
assert srcstart >= 0
assert dststart >= 0
More information about the Pypy-commit
mailing list