[pypy-svn] pypy arm-backend-2: merge default

bivab commits-noreply at bitbucket.org
Wed Feb 2 13:50:28 CET 2011


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r41553:ac3fe5c04e9b
Date: 2011-01-29 17:30 +0100
http://bitbucket.org/pypy/pypy/changeset/ac3fe5c04e9b/

Log:	merge default

diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -1045,20 +1045,6 @@
         except OverflowError:
             self.make_llexception()
 
-    def op_llong_neg_ovf(self, x):
-        assert type(x) is r_longlong
-        try:
-            return ovfcheck(-x)
-        except OverflowError:
-            self.make_llexception()
-
-    def op_llong_abs_ovf(self, x):
-        assert type(x) is r_longlong
-        try:
-            return ovfcheck(abs(x))
-        except OverflowError:
-            self.make_llexception()
-
     def op_int_lshift_ovf(self, x, y):
         assert isinstance(x, int)
         assert isinstance(y, int)

diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -154,6 +154,8 @@
         # unpack the ** arguments
         space = self.space
         if space.isinstance_w(w_starstararg, space.w_dict):
+            if not space.is_true(w_starstararg):
+                return False # don't call unpackiterable - it's jit-opaque
             keys_w = space.unpackiterable(w_starstararg)
         else:
             try:

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -199,6 +199,8 @@
             error = CANNOT_FAIL
     if type(error) is int:
         error = rffi.cast(restype, error)
+    expect_integer = (isinstance(restype, lltype.Primitive) and
+                      rffi.cast(restype, 0) == 0)
 
     def decorate(func):
         func_name = func.func_name
@@ -268,6 +270,9 @@
                             return None
                         else:
                             return api_function.error_value
+                    if not we_are_translated():
+                        got_integer = isinstance(res, (int, long, float))
+                        assert got_integer == expect_integer
                     if res is None:
                         return None
                     elif isinstance(res, Reference):


diff --git a/pypy/objspace/std/callmethod.py b/pypy/objspace/std/callmethod.py
--- a/pypy/objspace/std/callmethod.py
+++ b/pypy/objspace/std/callmethod.py
@@ -104,7 +104,10 @@
         if w_self is None:
             f.popvalue()    # removes w_self, which is None
         w_callable = f.popvalue()
-        w_result = f.space.call_args(w_callable, args)
+        if f.is_being_profiled and function.is_builtin_code(w_callable):
+            w_result = f.space.call_args_and_c_profile(f, w_callable, args)
+        else:
+            w_result = f.space.call_args(w_callable, args)
         rstack.resume_point("CALL_METHOD_KW", f, returns=w_result)
     f.pushvalue(w_result)
 

diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -39,6 +39,7 @@
     def optimize_block(self, block):
         if block.operations == ():
             return
+        self.remove_longlong_constants(block)
         self.vable_array_vars = {}
         self.vable_flags = {}
         renamings = {}
@@ -134,6 +135,55 @@
         block.exits = block.exits[:1]
         block.exitswitch = None
 
+    def remove_longlong_constants(self, block):
+        # remove all Constant({Un}signedLongLong), and replace them with
+        # cast_int_to_longlong(Constant(Signed)) or
+        # two_ints_to_longlong(Constant(Signed), Constant(Signed)).
+        operations = []
+        all_constants = {}
+        #
+        def _get_const_as_var(c):
+            v = all_constants.get(c)
+            if v is None:
+                from pypy.rlib.rarithmetic import intmask
+                v = varoftype(c.concretetype)
+                value = int(c.value)
+                c_hi = Constant(intmask(value >> 32), lltype.Signed)
+                c_lo = Constant(intmask(value), lltype.Signed)
+                if c_lo.value == value:
+                    # a long long constant, but it fits in 32 bits
+                    op1 = SpaceOperation('cast_int_to_longlong', [c_lo], v)
+                else:
+                    # a 64-bit long long constant, requires two ints
+                    op1 = SpaceOperation('two_ints_to_longlong', [c_lo, c_hi],
+                                         v)
+                operations.append(op1)
+                all_constants[c] = v
+            return v
+        #
+        for op in block.operations:
+            for i, v in enumerate(op.args):
+                if (isinstance(v, Constant) and
+                        self._is_longlong(v.concretetype)):
+                    args = op.args[:]
+                    args[i] = _get_const_as_var(v)
+                    op = SpaceOperation(op.opname, args, op.result)
+            operations.append(op)
+        #
+        last_op = None
+        if block.exitswitch == c_last_exception:
+            last_op = operations.pop()
+        for link in block.exits:
+            for i, v in enumerate(link.args):
+                if (isinstance(v, Constant) and
+                        self._is_longlong(v.concretetype)):
+                    args = link.args[:]
+                    args[i] = _get_const_as_var(v)
+                    link.args = args
+        if last_op is not None:
+            operations.append(last_op)
+        block.operations = operations
+
     # ----------
 
     def follow_constant_exit(self, block):
@@ -199,7 +249,6 @@
 
     rewrite_op_cast_pointer = rewrite_op_same_as
     rewrite_op_cast_opaque_ptr = rewrite_op_same_as   # rlib.rerased
-    def rewrite_op_cast_primitive(self, op): pass
     def rewrite_op_cast_bool_to_int(self, op): pass
     def rewrite_op_cast_bool_to_uint(self, op): pass
     def rewrite_op_cast_char_to_int(self, op): pass
@@ -424,6 +473,15 @@
     rewrite_op_int_mod_zer     = _do_builtin_call
     rewrite_op_int_lshift_ovf  = _do_builtin_call
     rewrite_op_int_abs         = _do_builtin_call
+    rewrite_op_llong_abs          = _do_builtin_call
+    rewrite_op_llong_floordiv     = _do_builtin_call
+    rewrite_op_llong_floordiv_zer = _do_builtin_call
+    rewrite_op_llong_mod          = _do_builtin_call
+    rewrite_op_llong_mod_zer      = _do_builtin_call
+    rewrite_op_ullong_floordiv     = _do_builtin_call
+    rewrite_op_ullong_floordiv_zer = _do_builtin_call
+    rewrite_op_ullong_mod          = _do_builtin_call
+    rewrite_op_ullong_mod_zer      = _do_builtin_call
     rewrite_op_gc_identityhash = _do_builtin_call
     rewrite_op_gc_id           = _do_builtin_call
 
@@ -779,6 +837,116 @@
         return result
 
     # ----------
+    # Long longs, for 32-bit only.  Supported operations are left unmodified,
+    # and unsupported ones are turned into a call to a function from
+    # jit.codewriter.support.
+
+    if lltype.SignedLongLong != lltype.Signed:
+        @staticmethod
+        def _is_longlong(TYPE):
+            return (TYPE == lltype.SignedLongLong or
+                    TYPE == lltype.UnsignedLongLong)
+    else:
+        # on 64-bit, _is_longlong() returns always False
+        @staticmethod
+        def _is_longlong(TYPE):
+            return False
+
+    for _op, _oopspec in [('llong_invert',  'INVERT'),
+                          ('ullong_invert', 'INVERT'),
+                          ('llong_lt',      'LT'),
+                          ('llong_le',      'LE'),
+                          ('llong_eq',      'EQ'),
+                          ('llong_ne',      'NE'),
+                          ('llong_gt',      'GT'),
+                          ('llong_ge',      'GE'),
+                          ('ullong_lt',     'ULT'),
+                          ('ullong_le',     'ULE'),
+                          ('ullong_eq',     'EQ'),
+                          ('ullong_ne',     'NE'),
+                          ('ullong_gt',     'UGT'),
+                          ('ullong_ge',     'UGE'),
+                          ('llong_add',     'ADD'),
+                          ('llong_sub',     'SUB'),
+                          ('llong_mul',     'MUL'),
+                          ('llong_and',     'AND'),
+                          ('llong_or',      'OR'),
+                          ('llong_xor',     'XOR'),
+                          ('ullong_add',    'ADD'),
+                          ('ullong_sub',    'SUB'),
+                          ('ullong_mul',    'MUL'),
+                          ('ullong_and',    'AND'),
+                          ('ullong_or',     'OR'),
+                          ('ullong_xor',    'XOR'),
+                          ('llong_lshift',  'LSHIFT'),
+                          ('llong_rshift',  'RSHIFT'),
+                          ('ullong_lshift', 'LSHIFT'),
+                          ('ullong_rshift', 'URSHIFT'),
+                          ('cast_int_to_longlong',     'FROM_INT'),
+                          ('truncate_longlong_to_int', 'TO_INT'),
+                          ('cast_float_to_longlong',   'FROM_FLOAT'),
+                          ('cast_longlong_to_float',   'TO_FLOAT'),
+                          # internal pseuso-operation:
+                          ('two_ints_to_longlong',     'FROM_TWO_INTS'),
+                          ]:
+        exec py.code.Source('''
+            def rewrite_op_%s(self, op):
+                args = op.args
+                op1 = self.prepare_builtin_call(op, "llong_%s", args)
+                op2 = self._handle_oopspec_call(op1, args,
+                                                EffectInfo.OS_LLONG_%s,
+                                                EffectInfo.EF_PURE)
+                return op2
+        ''' % (_op, _oopspec.lower(), _oopspec)).compile()
+
+    def _normalize(self, oplist):
+        if isinstance(oplist, SpaceOperation):
+            return [oplist]
+        else:
+            assert type(oplist) is list
+            return oplist
+
+    def rewrite_op_llong_neg(self, op):
+        v = varoftype(lltype.SignedLongLong)
+        op0 = SpaceOperation('cast_int_to_longlong',
+                             [Constant(0, lltype.Signed)],
+                             v)
+        args = [v, op.args[0]]
+        op1 = SpaceOperation('llong_sub', args, op.result)
+        return (self._normalize(self.rewrite_operation(op0)) +
+                self._normalize(self.rewrite_operation(op1)))
+
+    def rewrite_op_llong_is_true(self, op):
+        v = varoftype(lltype.SignedLongLong)
+        op0 = SpaceOperation('cast_int_to_longlong',
+                             [Constant(0, lltype.Signed)],
+                             v)
+        args = [op.args[0], v]
+        op1 = SpaceOperation('llong_ne', args, op.result)
+        return (self._normalize(self.rewrite_operation(op0)) +
+                self._normalize(self.rewrite_operation(op1)))
+
+    rewrite_op_ullong_is_true = rewrite_op_llong_is_true
+
+    def rewrite_op_cast_primitive(self, op):
+        fromll = self._is_longlong(op.args[0].concretetype)
+        toll   = self._is_longlong(op.result.concretetype)
+        if fromll != toll:
+            args = op.args
+            if fromll:
+                opname = 'truncate_longlong_to_int'
+            else:
+                from pypy.rpython.lltypesystem import rffi
+                if rffi.cast(op.args[0].concretetype, -1) < 0:
+                    opname = 'cast_int_to_longlong'
+                else:
+                    opname = 'two_ints_to_longlong'
+                    c_hi = Constant(0, lltype.Signed)
+                    args = [args[0], c_hi]
+            op1 = SpaceOperation(opname, args, op.result)
+            return self.rewrite_operation(op1)
+
+    # ----------
     # Renames, from the _old opname to the _new one.
     # The new operation is optionally further processed by rewrite_operation().
     for _old, _new in [('bool_not', 'int_is_zero'),
@@ -1107,9 +1275,11 @@
     # Strings and Unicodes.
 
     def _handle_oopspec_call(self, op, args, oopspecindex, extraeffect=None):
-        calldescr = self.callcontrol.getcalldescr(op, oopspecindex)
-        if extraeffect:
-            calldescr.get_extra_info().extraeffect = extraeffect
+        calldescr = self.callcontrol.getcalldescr(op, oopspecindex,
+                                                  extraeffect)
+        if extraeffect is not None:
+            assert (type(calldescr) is str      # for tests
+                    or calldescr.get_extra_info().extraeffect == extraeffect)
         if isinstance(op.args[0].value, str):
             pass  # for tests only
         else:

diff --git a/pypy/jit/metainterp/test/test_basic.py b/pypy/jit/metainterp/test/test_basic.py
--- a/pypy/jit/metainterp/test/test_basic.py
+++ b/pypy/jit/metainterp/test/test_basic.py
@@ -7,6 +7,7 @@
 from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
 from pypy.jit.backend.llgraph import runner
 from pypy.jit.metainterp import pyjitpl, history
+from pypy.jit.metainterp.warmstate import set_future_value
 from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy
 from pypy import conftest
 from pypy.rlib.rarithmetic import ovfcheck
@@ -14,7 +15,8 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.ootypesystem import ootype
 
-def _get_jitcodes(testself, CPUClass, func, values, type_system):
+def _get_jitcodes(testself, CPUClass, func, values, type_system,
+                  supports_longlong=False, **kwds):
     from pypy.jit.codewriter import support, codewriter
     from pypy.jit.metainterp import simple_optimize
 
@@ -57,7 +59,9 @@
     cpu = CPUClass(rtyper, stats, None, False)
     cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
     testself.cw = cw
-    cw.find_all_graphs(JitPolicy())
+    policy = JitPolicy()
+    policy.set_supports_longlong(supports_longlong)
+    cw.find_all_graphs(policy)
     #
     testself.warmrunnerstate = FakeWarmRunnerState()
     testself.warmrunnerstate.cpu = cpu
@@ -119,6 +123,29 @@
     else:
         raise Exception("FAILED")
 
+def _run_with_machine_code(testself, args):
+    metainterp = testself.metainterp
+    num_green_args = metainterp.jitdriver_sd.num_green_args
+    loop_tokens = metainterp.get_compiled_merge_points(args[:num_green_args])
+    if len(loop_tokens) != 1:
+        return NotImplemented
+    # a loop was successfully created by _run_with_pyjitpl(); call it
+    cpu = metainterp.cpu
+    for i in range(len(args) - num_green_args):
+        x = args[num_green_args + i]
+        typecode = history.getkind(lltype.typeOf(x))
+        set_future_value(cpu, i, x, typecode)
+    faildescr = cpu.execute_token(loop_tokens[0])
+    assert faildescr.__class__.__name__.startswith('DoneWithThisFrameDescr')
+    if metainterp.jitdriver_sd.result_type == history.INT:
+        return cpu.get_latest_value_int(0)
+    elif metainterp.jitdriver_sd.result_type == history.REF:
+        return cpu.get_latest_value_ref(0)
+    elif metainterp.jitdriver_sd.result_type == history.FLOAT:
+        return cpu.get_latest_value_float(0)
+    else:
+        return None
+
 
 class JitMixin:
     basic = True
@@ -156,12 +183,15 @@
 
     def interp_operations(self, f, args, **kwds):
         # get the JitCodes for the function f
-        _get_jitcodes(self, self.CPUClass, f, args, self.type_system)
+        _get_jitcodes(self, self.CPUClass, f, args, self.type_system, **kwds)
         # try to run it with blackhole.py
         result1 = _run_with_blackhole(self, args)
         # try to run it with pyjitpl.py
         result2 = _run_with_pyjitpl(self, args)
         assert result1 == result2
+        # try to run it by running the code compiled just before
+        result3 = _run_with_machine_code(self, args)
+        assert result1 == result3 or result3 == NotImplemented
         return result1
 
     def check_history(self, expected=None, **isns):
@@ -1261,20 +1291,6 @@
         res = self.interp_operations(f, [5])
         assert res == f(5)
 
-    def test_long_long(self):
-        from pypy.rlib.rarithmetic import r_longlong, intmask
-        def g(n, m, o):
-            # This function should be completely marked as residual by
-            # codewriter.py on 32-bit platforms.  On 64-bit platforms,
-            # this function should be JITted and the test should pass too.
-            n = r_longlong(n)
-            m = r_longlong(m)
-            return intmask((n*m) // o)
-        def f(n, m, o):
-            return g(n, m, o) // 3
-        res = self.interp_operations(f, [1000000000, 90, 91])
-        assert res == (1000000000 * 90 // 91) // 3
-
     def test_free_object(self):
         import weakref
         from pypy.rlib import rgc

diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -86,6 +86,7 @@
 
 class BaseCPU(model.AbstractCPU):
     supports_floats = True
+    supports_longlong = True
 
     def __init__(self, rtyper, stats=None, opts=None,
                  translate_support_code=False,

diff --git a/pypy/translator/c/src/math.c b/pypy/translator/c/src/math.c
deleted file mode 100644
--- a/pypy/translator/c/src/math.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/* Definitions of some C99 math library functions, for those platforms
-   that don't implement these functions already. */
-
-#include <errno.h>
-
-/* The following macros are copied from CPython header files */
-
-#ifdef _MSC_VER
-#include <float.h>
-#define PyPy_IS_NAN _isnan
-#define PyPy_IS_INFINITY(X) (!_finite(X) && !_isnan(X))
-#define copysign _copysign
-#else
-#define PyPy_IS_NAN(X) ((X) != (X))
-#define PyPy_IS_INFINITY(X) ((X) &&                                   \
-                             (Py_FORCE_DOUBLE(X)*0.5 == Py_FORCE_DOUBLE(X)))
-#endif
-
-#undef PyPy_NAN
-
-int
-_pypy_math_isinf(double x)
-{
-    return PyPy_IS_INFINITY(x);
-}
-
-int
-_pypy_math_isnan(double x)
-{
-    return PyPy_IS_NAN(x);
-}
-
-/* The following copyright notice applies to the original
-   implementations of acosh, asinh and atanh. */
-
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-double _pypy_math_log1p(double x);
-
-static const double ln2 = 6.93147180559945286227E-01;
-static const double two_pow_m28 = 3.7252902984619141E-09; /* 2**-28 */
-static const double two_pow_p28 = 268435456.0; /* 2**28 */
-static const double zero = 0.0;
-
-/* acosh(x)
- * Method :
- *      Based on
- *            acosh(x) = log [ x + sqrt(x*x-1) ]
- *      we have
- *            acosh(x) := log(x)+ln2, if x is large; else
- *            acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
- *            acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
- *
- * Special cases:
- *      acosh(x) is NaN with signal if x<1.
- *      acosh(NaN) is NaN without signal.
- */
-
-double
-_pypy_math_acosh(double x)
-{
-    if (PyPy_IS_NAN(x)) {
-        return x+x;
-    }
-    if (x < 1.) {                       /* x < 1;  return a signaling NaN */
-        errno = EDOM;
-#ifdef PyPy_NAN
-        return PyPy_NAN;
-#else
-        return (x-x)/(x-x);
-#endif
-    }
-    else if (x >= two_pow_p28) {        /* x > 2**28 */
-        if (PyPy_IS_INFINITY(x)) {
-            return x+x;
-        } else {
-            return log(x)+ln2;                  /* acosh(huge)=log(2x) */
-        }
-    }
-    else if (x == 1.) {
-        return 0.0;                             /* acosh(1) = 0 */
-    }
-    else if (x > 2.) {                          /* 2 < x < 2**28 */
-        double t = x*x;
-        return log(2.0*x - 1.0 / (x + sqrt(t - 1.0)));
-    }
-    else {                              /* 1 < x <= 2 */
-        double t = x - 1.0;
-        return _pypy_math_log1p(t + sqrt(2.0*t + t*t));
-    }
-}
-
-
-/* asinh(x)
- * Method :
- *      Based on
- *              asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
- *      we have
- *      asinh(x) := x  if  1+x*x=1,
- *               := sign(x)*(log(x)+ln2)) for large |x|, else
- *               := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
- *               := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
- */
-
-double
-_pypy_math_asinh(double x)
-{
-    double w;
-    double absx = fabs(x);
-
-    if (PyPy_IS_NAN(x) || PyPy_IS_INFINITY(x)) {
-        return x+x;
-    }
-    if (absx < two_pow_m28) {           /* |x| < 2**-28 */
-        return x;               /* return x inexact except 0 */
-    }
-    if (absx > two_pow_p28) {           /* |x| > 2**28 */
-        w = log(absx)+ln2;
-    }
-    else if (absx > 2.0) {              /* 2 < |x| < 2**28 */
-        w = log(2.0*absx + 1.0 / (sqrt(x*x + 1.0) + absx));
-    }
-    else {                              /* 2**-28 <= |x| < 2= */
-        double t = x*x;
-        w = _pypy_math_log1p(absx + t / (1.0 + sqrt(1.0 + t)));
-    }
-    return copysign(w, x);
-
-}
-
-/* atanh(x)
- * Method :
- *    1.Reduced x to positive by atanh(-x) = -atanh(x)
- *    2.For x>=0.5
- *                1           2x                          x
- *      atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
- *                2          1 - x                    1 - x
- *
- *      For x<0.5
- *      atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
- *
- * Special cases:
- *      atanh(x) is NaN if |x| >= 1 with signal;
- *      atanh(NaN) is that NaN with no signal;
- *
- */
-
-double
-_pypy_math_atanh(double x)
-{
-    double absx;
-    double t;
-
-    if (PyPy_IS_NAN(x)) {
-        return x+x;
-    }
-    absx = fabs(x);
-    if (absx >= 1.) {                   /* |x| >= 1 */
-        errno = EDOM;
-#ifdef PyPy_NAN
-        return PyPy_NAN;
-#else
-        return x/zero;
-#endif
-    }
-    if (absx < two_pow_m28) {           /* |x| < 2**-28 */
-        return x;
-    }
-    if (absx < 0.5) {                   /* |x| < 0.5 */
-        t = absx+absx;
-        t = 0.5 * _pypy_math_log1p(t + t*absx / (1.0 - absx));
-    }
-    else {                              /* 0.5 <= |x| <= 1.0 */
-        t = 0.5 * _pypy_math_log1p((absx + absx) / (1.0 - absx));
-    }
-    return copysign(t, x);
-}
-
-/* Mathematically, expm1(x) = exp(x) - 1.  The expm1 function is designed
-   to avoid the significant loss of precision that arises from direct
-   evaluation of the expression exp(x) - 1, for x near 0. */
-
-double
-_pypy_math_expm1(double x)
-{
-    /* For abs(x) >= log(2), it's safe to evaluate exp(x) - 1 directly; this
-       also works fine for infinities and nans.
-
-       For smaller x, we can use a method due to Kahan that achieves close to
-       full accuracy.
-    */
-
-    if (fabs(x) < 0.7) {
-        double u;
-        u  = exp(x);
-        if (u == 1.0)
-            return x;
-        else
-            return (u - 1.0) * x / log(u);
-    }
-    else
-        return exp(x) - 1.0;
-}
-
-/* log1p(x) = log(1+x).  The log1p function is designed to avoid the
-   significant loss of precision that arises from direct evaluation when x is
-   small. */
-
-double
-_pypy_math_log1p(double x)
-{
-    /* For x small, we use the following approach.  Let y be the nearest float
-       to 1+x, then
-
-      1+x = y * (1 - (y-1-x)/y)
-
-       so log(1+x) = log(y) + log(1-(y-1-x)/y).  Since (y-1-x)/y is tiny, the
-       second term is well approximated by (y-1-x)/y.  If abs(x) >=
-       DBL_EPSILON/2 or the rounding-mode is some form of round-to-nearest
-       then y-1-x will be exactly representable, and is computed exactly by
-       (y-1)-x.
-
-       If abs(x) < DBL_EPSILON/2 and the rounding mode is not known to be
-       round-to-nearest then this method is slightly dangerous: 1+x could be
-       rounded up to 1+DBL_EPSILON instead of down to 1, and in that case
-       y-1-x will not be exactly representable any more and the result can be
-       off by many ulps.  But this is easily fixed: for a floating-point
-       number |x| < DBL_EPSILON/2., the closest floating-point number to
-       log(1+x) is exactly x.
-    */
-
-    double y;
-    if (fabs(x) < DBL_EPSILON/2.) {
-        return x;
-    } else if (-0.5 <= x && x <= 1.) {
-    /* WARNING: it's possible than an overeager compiler
-       will incorrectly optimize the following two lines
-       to the equivalent of "return log(1.+x)". If this
-       happens, then results from log1p will be inaccurate
-       for small x. */
-        y = 1.+x;
-        return log(y)-((y-1.)-x)/y;
-    } else {
-    /* NaNs and infinities should end up here */
-        return log(1.+x);
-    }
-}

diff --git a/pypy/jit/tl/pypyjit.py b/pypy/jit/tl/pypyjit.py
--- a/pypy/jit/tl/pypyjit.py
+++ b/pypy/jit/tl/pypyjit.py
@@ -30,7 +30,6 @@
     BACKEND = 'c'
 
 config = get_pypy_config(translating=True)
-config.translation.backendopt.inline_threshold = 0.1
 config.translation.gc = 'boehm'
 config.objspace.nofaking = True
 config.translating = True

diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -5,7 +5,7 @@
 import os
 from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr,
                                          ResOperation, BoxPtr, ConstFloat,
-                                         LoopToken, INT, REF, FLOAT)
+                                         BoxFloat, LoopToken, INT, REF, FLOAT)
 from pypy.jit.backend.x86.regloc import *
 from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi, rstr
 from pypy.rlib.objectmodel import we_are_translated
@@ -13,12 +13,14 @@
 from pypy.jit.backend.llsupport import symbolic
 from pypy.jit.backend.x86.jump import remap_frame_layout
 from pypy.jit.codewriter import heaptracker
+from pypy.jit.codewriter.effectinfo import EffectInfo
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.backend.llsupport.descr import BaseFieldDescr, BaseArrayDescr
 from pypy.jit.backend.llsupport.descr import BaseCallDescr, BaseSizeDescr
 from pypy.jit.backend.llsupport.regalloc import FrameManager, RegisterManager,\
      TempBox, compute_vars_longevity, compute_loop_consts
 from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE, IS_X86_32, IS_X86_64
+from pypy.rlib.rarithmetic import r_longlong, r_uint
 
 class X86RegisterManager(RegisterManager):
 
@@ -72,6 +74,12 @@
         rffi.cast(rffi.CArrayPtr(rffi.DOUBLE), adr)[0] = c.getfloat()
         return ConstFloatLoc(adr)
 
+    def convert_to_imm_16bytes_align(self, c):
+        adr = self.assembler.datablockwrapper.malloc_aligned(16, 16)
+        rffi.cast(rffi.CArrayPtr(rffi.DOUBLE), adr)[0] = c.getfloat()
+        rffi.cast(rffi.CArrayPtr(rffi.DOUBLE), adr)[1] = 0.0
+        return ConstFloatLoc(adr)
+
     def after_call(self, v):
         # the result is stored in st0, but we don't have this around,
         # so genop_call will move it to some frame location immediately
@@ -229,6 +237,14 @@
             return self.rm.force_allocate_reg(var, forbidden_vars,
                                               selected_reg, need_lower_byte)
 
+    def load_xmm_aligned_16_bytes(self, var, forbidden_vars=[]):
+        # Load 'var' in a register; but if it is a constant, we can return
+        # a 16-bytes-aligned ConstFloatLoc.
+        if isinstance(var, Const):
+            return self.xrm.convert_to_imm_16bytes_align(var)
+        else:
+            return self.xrm.make_sure_var_in_reg(var, forbidden_vars)
+
     def _update_bindings(self, locs, inputargs):
         # XXX this should probably go to llsupport/regalloc.py
         used = {}
@@ -269,6 +285,11 @@
             self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
         self.assembler.regalloc_perform(op, arglocs, result_loc)
 
+    def PerformLLong(self, op, arglocs, result_loc):
+        if not we_are_translated():
+            self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
+        self.assembler.regalloc_perform_llong(op, arglocs, result_loc)
+
     def locs_for_fail(self, guard_op):
         return [self.loc(v) for v in guard_op.getfailargs()]
 
@@ -583,6 +604,110 @@
         self.Perform(op, [loc0], loc1)
         self.rm.possibly_free_var(op.getarg(0))
 
+    def _consider_llong_binop_xx(self, op):
+        # must force both arguments into xmm registers, because we don't
+        # know if they will be suitably aligned.  Exception: if the second
+        # argument is a constant, we can ask it to be aligned to 16 bytes.
+        args = [op.getarg(1), op.getarg(2)]
+        loc1 = self.load_xmm_aligned_16_bytes(args[1])
+        loc0 = self.xrm.force_result_in_reg(op.result, args[0], args)
+        self.PerformLLong(op, [loc0, loc1], loc0)
+        self.xrm.possibly_free_vars(args)
+
+    def _consider_llong_eq_ne_xx(self, op):
+        # must force both arguments into xmm registers, because we don't
+        # know if they will be suitably aligned.  Exception: if they are
+        # constants, we can ask them to be aligned to 16 bytes.
+        args = [op.getarg(1), op.getarg(2)]
+        loc1 = self.load_xmm_aligned_16_bytes(args[0])
+        loc2 = self.load_xmm_aligned_16_bytes(args[1], args)
+        tmpxvar = TempBox()
+        loc3 = self.xrm.force_allocate_reg(tmpxvar, args)
+        self.xrm.possibly_free_var(tmpxvar)
+        loc0 = self.rm.force_allocate_reg(op.result, need_lower_byte=True)
+        self.PerformLLong(op, [loc1, loc2, loc3], loc0)
+        self.xrm.possibly_free_vars(args)
+
+    def _maybe_consider_llong_lt(self, op):
+        # XXX just a special case for now
+        from pypy.rlib.longlong2float import longlong2float
+        box = op.getarg(2)
+        if not isinstance(box, ConstFloat):
+            return False
+        if not (box.value == longlong2float(r_longlong(0))):
+            return False
+        # "x < 0"
+        box = op.getarg(1)
+        assert isinstance(box, BoxFloat)
+        loc1 = self.xrm.make_sure_var_in_reg(box)
+        loc0 = self.rm.force_allocate_reg(op.result)
+        self.PerformLLong(op, [loc1], loc0)
+        self.xrm.possibly_free_var(box)
+        return True
+
+    def _consider_llong_to_int(self, op):
+        # accept an argument in a xmm register or in the stack
+        loc1 = self.xrm.loc(op.getarg(1))
+        loc0 = self.rm.force_allocate_reg(op.result)
+        self.PerformLLong(op, [loc1], loc0)
+        self.xrm.possibly_free_var(op.getarg(1))
+
+    def _loc_of_const_longlong(self, value64):
+        from pypy.rlib.longlong2float import longlong2float
+        c = ConstFloat(longlong2float(value64))
+        return self.xrm.convert_to_imm(c)
+
+    def _consider_llong_from_int(self, op):
+        assert IS_X86_32
+        loc0 = self.xrm.force_allocate_reg(op.result)
+        box = op.getarg(1)
+        if isinstance(box, ConstInt):
+            loc1 = self._loc_of_const_longlong(r_longlong(box.value))
+            loc2 = None    # unused
+        else:
+            # requires the argument to be in eax, and trash edx.
+            loc1 = self.rm.make_sure_var_in_reg(box, selected_reg=eax)
+            tmpvar = TempBox()
+            self.rm.force_allocate_reg(tmpvar, [box], selected_reg=edx)
+            self.rm.possibly_free_var(tmpvar)
+            tmpxvar = TempBox()
+            loc2 = self.xrm.force_allocate_reg(tmpxvar, [op.result])
+            self.xrm.possibly_free_var(tmpxvar)
+        self.PerformLLong(op, [loc1, loc2], loc0)
+        self.rm.possibly_free_var(box)
+
+    def _consider_llong_from_two_ints(self, op):
+        assert IS_X86_32
+        box1 = op.getarg(1)
+        box2 = op.getarg(2)
+        loc0 = self.xrm.force_allocate_reg(op.result)
+        #
+        if isinstance(box1, ConstInt) and isinstance(box2, ConstInt):
+            # all-constant arguments: load the result value in a single step
+            value64 = r_longlong(box2.value) << 32
+            value64 |= r_longlong(r_uint(box1.value))
+            loc1 = self._loc_of_const_longlong(value64)
+            loc2 = None    # unused
+            loc3 = None    # unused
+        #
+        else:
+            tmpxvar = TempBox()
+            loc3 = self.xrm.force_allocate_reg(tmpxvar, [op.result])
+            self.xrm.possibly_free_var(tmpxvar)
+            #
+            if isinstance(box1, ConstInt):
+                loc1 = self._loc_of_const_longlong(r_longlong(box1.value))
+            else:
+                loc1 = self.rm.make_sure_var_in_reg(box1)
+            #
+            if isinstance(box2, ConstInt):
+                loc2 = self._loc_of_const_longlong(r_longlong(box2.value))
+            else:
+                loc2 = self.rm.make_sure_var_in_reg(box2, [box1])
+        #
+        self.PerformLLong(op, [loc1, loc2, loc3], loc0)
+        self.rm.possibly_free_vars_for_op(op)
+
     def _call(self, op, arglocs, force_store=[], guard_not_forced_op=None):
         save_all_regs = guard_not_forced_op is not None
         self.rm.before_call(force_store, save_all_regs=save_all_regs)
@@ -614,6 +739,31 @@
                    guard_not_forced_op=guard_not_forced_op)
 
     def consider_call(self, op):
+        if IS_X86_32:
+            # support for some of the llong operations,
+            # which only exist on x86-32
+            effectinfo = op.getdescr().get_extra_info()
+            if effectinfo is not None:
+                oopspecindex = effectinfo.oopspecindex
+                if oopspecindex in (EffectInfo.OS_LLONG_ADD,
+                                    EffectInfo.OS_LLONG_SUB,
+                                    EffectInfo.OS_LLONG_AND,
+                                    EffectInfo.OS_LLONG_OR,
+                                    EffectInfo.OS_LLONG_XOR):
+                    return self._consider_llong_binop_xx(op)
+                if oopspecindex == EffectInfo.OS_LLONG_TO_INT:
+                    return self._consider_llong_to_int(op)
+                if oopspecindex == EffectInfo.OS_LLONG_FROM_INT:
+                    return self._consider_llong_from_int(op)
+                if oopspecindex == EffectInfo.OS_LLONG_FROM_TWO_INTS:
+                    return self._consider_llong_from_two_ints(op)
+                if (oopspecindex == EffectInfo.OS_LLONG_EQ or
+                    oopspecindex == EffectInfo.OS_LLONG_NE):
+                    return self._consider_llong_eq_ne_xx(op)
+                if oopspecindex == EffectInfo.OS_LLONG_LT:
+                    if self._maybe_consider_llong_lt(op):
+                        return
+        #
         self._consider_call(op)
 
     def consider_call_may_force(self, op, guard_op):

diff --git a/pypy/interpreter/test/test_executioncontext.py b/pypy/interpreter/test/test_executioncontext.py
--- a/pypy/interpreter/test/test_executioncontext.py
+++ b/pypy/interpreter/test/test_executioncontext.py
@@ -164,6 +164,25 @@
         events = space.unwrap(w_events)
         assert events == ['return', 'c_call', 'c_return', 'return', 'c_call']
 
+    def test_c_call_setprofile_kwargs(self):
+        space = self.space
+        w_events = space.appexec([], """():
+        import sys
+        l = []
+        def profile(frame, event, arg):
+            l.append(event)
+
+        def bar():
+            sys.setprofile(profile)
+            [].sort(reverse=True)
+            sys.setprofile(None)
+
+        bar()
+        return l
+        """)
+        events = space.unwrap(w_events)
+        assert events == ['c_call', 'c_return', 'c_call']
+
     def test_c_call_setprofile_strange_method(self):
         space = self.space
         w_events = space.appexec([], """():

diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -49,6 +49,7 @@
              absolute   = "from __future__ import absolute_import\nimport string",
              relative_b = "from __future__ import absolute_import\nfrom . import string",
              relative_c = "from __future__ import absolute_import\nfrom .string import inpackage",
+             relative_f = "from .os import sep",
              )
     setuppkg("pkg.pkg1", 
              a          = '',
@@ -189,6 +190,13 @@
     def test_import_keywords(self):
         __import__(name='sys', level=0)
 
+    def test_import_by_filename(self):
+        import pkg.a
+        filename = pkg.a.__file__
+        assert filename.endswith('.py')
+        exc = raises(ImportError, __import__, filename[:-3])
+        assert exc.value.message == "Import by filename is not supported."
+
     def test_import_badcase(self):
         def missing(name):
             try:
@@ -269,7 +277,7 @@
     def test_import_relative_partial_success(self):
         def imp():
             import pkg_r.inpkg
-        raises(ImportError,imp)
+        raises(ImportError, imp)
 
     def test_import_builtin_inpackage(self):
         def imp():
@@ -347,6 +355,12 @@
         from pkg import relative_b
         assert relative_b.string.inpackage == 1
 
+    def test_no_relative_import(self):
+        def imp():
+            from pkg import relative_f
+        exc = raises(ImportError, imp)
+        assert exc.value.message == "No module named pkg.os"
+
     def test_future_relative_import_level_1(self):
         from pkg import relative_c
         assert relative_c.inpackage == 1
@@ -722,6 +736,7 @@
     def test_write_compiled_module(self):
         space = self.space
         pathname = _testfilesource()
+        os.chmod(pathname, 0777)
         stream = streamio.open_file_as_stream(pathname, "r")
         try:
             w_ret = importing.parse_source_module(space,
@@ -733,10 +748,12 @@
         assert type(pycode) is pypy.interpreter.pycode.PyCode
 
         cpathname = str(udir.join('cpathname.pyc'))
+        mode = 0777
         mtime = 12345
         importing.write_compiled_module(space,
                                         pycode,
                                         cpathname,
+                                        mode,
                                         mtime)
 
         # check
@@ -746,6 +763,9 @@
         assert ret is not None
         ret.close()
 
+        # Check that the executable bit was removed
+        assert os.stat(cpathname).st_mode & 0111 == 0
+
         # read compiled module
         stream = streamio.open_file_as_stream(cpathname, "rb")
         try:

diff --git a/pypy/translator/c/src/signals.h b/pypy/translator/c/src/signals.h
--- a/pypy/translator/c/src/signals.h
+++ b/pypy/translator/c/src/signals.h
@@ -117,8 +117,11 @@
         pypysig_counter.value = -1;
       }
 
-    if (wakeup_fd != -1)
-      write(wakeup_fd, "\0", 1);
+    if (wakeup_fd != -1) 
+      {
+        write(wakeup_fd, "\0", 1);
+        /* the return value is ignored here */
+      }
 }
 
 void pypysig_setflag(int signum)

diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -23,12 +23,16 @@
 
 from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated
 from pypy.rlib.rarithmetic import ovfcheck
+from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
+from pypy.rlib.longlong2float import longlong2float, float2longlong
 
 import py
 from pypy.tool.ansi_print import ansi_log
 log = py.log.Producer('runner')
 py.log.setconsumer('runner', ansi_log)
 
+IS_32_BIT = r_ulonglong is not r_uint
+
 
 def _from_opaque(opq):
     return opq._obj.externalobj
@@ -1071,14 +1075,26 @@
 def cast_from_ptr(TYPE, x):
     return lltype.cast_opaque_ptr(TYPE, x)
 
-def cast_to_float(x):      # not really a cast, just a type check
+def cast_to_float(x):
+    if isinstance(x, float):
+        return x      # common case
+    if IS_32_BIT:
+        if isinstance(x, r_longlong):
+            return longlong2float(x)
+        if isinstance(x, r_ulonglong):
+            return longlong2float(rffi.cast(lltype.SignedLongLong, x))
+    raise TypeError(type(x))
+
+def cast_from_float(TYPE, x):
     assert isinstance(x, float)
-    return x
-
-def cast_from_float(TYPE, x):   # not really a cast, just a type check
-    assert TYPE is lltype.Float
-    assert isinstance(x, float)
-    return x
+    if TYPE is lltype.Float:
+        return x
+    if IS_32_BIT:
+        if TYPE is lltype.SignedLongLong:
+            return float2longlong(x)
+        if TYPE is lltype.UnsignedLongLong:
+            return r_ulonglong(float2longlong(x))
+    raise TypeError(TYPE)
 
 
 def new_frame(is_oo, cpu):
@@ -1518,7 +1534,9 @@
                     assert n == 'r'
                 x = argsiter_r.next()
                 x = cast_from_ptr(TYPE, x)
-            elif TYPE is lltype.Float:
+            elif TYPE is lltype.Float or (
+                    IS_32_BIT and TYPE in (lltype.SignedLongLong,
+                                           lltype.UnsignedLongLong)):
                 if args_in_order is not None:
                     n = orderiter.next()
                     assert n == 'f'

diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -90,7 +90,7 @@
         self.callinfocollection = FakeCallInfoCollection()
     def guess_call_kind(self, op):
         return 'builtin'
-    def getcalldescr(self, op, oopspecindex=None):
+    def getcalldescr(self, op, oopspecindex=None, extraeffect=None):
         assert oopspecindex is not None    # in this test
         EI = effectinfo.EffectInfo
         if oopspecindex != EI.OS_ARRAYCOPY:

diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -46,6 +46,32 @@
     OS_LIBFFI_PREPARE           = 60
     OS_LIBFFI_PUSH_ARG          = 61
     OS_LIBFFI_CALL              = 62
+    #
+    OS_LLONG_INVERT             = 69
+    OS_LLONG_ADD                = 70
+    OS_LLONG_SUB                = 71
+    OS_LLONG_MUL                = 72
+    OS_LLONG_LT                 = 73
+    OS_LLONG_LE                 = 74
+    OS_LLONG_EQ                 = 75
+    OS_LLONG_NE                 = 76
+    OS_LLONG_GT                 = 77
+    OS_LLONG_GE                 = 78
+    OS_LLONG_AND                = 79
+    OS_LLONG_OR                 = 80
+    OS_LLONG_LSHIFT             = 81
+    OS_LLONG_RSHIFT             = 82
+    OS_LLONG_XOR                = 83
+    OS_LLONG_FROM_INT           = 84
+    OS_LLONG_TO_INT             = 85
+    OS_LLONG_FROM_FLOAT         = 86
+    OS_LLONG_TO_FLOAT           = 87
+    OS_LLONG_ULT                = 88
+    OS_LLONG_ULE                = 89
+    OS_LLONG_UGT                = 90
+    OS_LLONG_UGE                = 91
+    OS_LLONG_URSHIFT            = 92
+    OS_LLONG_FROM_TWO_INTS      = 93
 
     def __new__(cls, readonly_descrs_fields,
                 write_descrs_fields, write_descrs_arrays,

diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1163,7 +1163,7 @@
                     src_r += 1
                     if box.type == history.REF:
                         break
-            elif kind == history.FLOAT:
+            elif kind == history.FLOAT or kind == 'L':    # long long
                 while True:
                     box = argboxes[src_f]
                     src_f += 1

diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -10,7 +10,7 @@
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable
 from pypy.interpreter.eval import Code
-from pypy.rlib import streamio, jit
+from pypy.rlib import streamio, jit, rposix
 from pypy.rlib.streamio import StreamErrors
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.objectmodel import we_are_translated, specialize
@@ -127,42 +127,58 @@
     if (level != 0 and
         w_globals is not None and
         space.isinstance_w(w_globals, space.w_dict)):
+
         ctxt_w_name = space.finditem(w_globals, w('__name__'))
         ctxt_w_path = space.finditem(w_globals, w('__path__'))
+
+        ctxt_name = None
         if ctxt_w_name is not None:
             try:
                 ctxt_name = space.str_w(ctxt_w_name)
             except OperationError, e:
                 if not e.match(space, space.w_TypeError):
                     raise
-            else:
-                ctxt_name_prefix_parts = ctxt_name.split('.')
-                if level > 0:
-                    n = len(ctxt_name_prefix_parts)-level+1
-                    assert n>=0
-                    ctxt_name_prefix_parts = ctxt_name_prefix_parts[:n]
-                if ctxt_name_prefix_parts and ctxt_w_path is None: # plain module
-                    ctxt_name_prefix_parts.pop()
-                if ctxt_name_prefix_parts:
-                    rel_modulename = '.'.join(ctxt_name_prefix_parts)
-                    if modulename:
-                        rel_modulename += '.' + modulename
-                baselevel = len(ctxt_name_prefix_parts)
-                if rel_modulename is not None:
-                    w_mod = check_sys_modules(space, w(rel_modulename))
-                    if (w_mod is None or
-                        not space.is_w(w_mod, space.w_None)):
-                        w_mod = absolute_import(space, rel_modulename,
-                                                baselevel,
-                                                fromlist_w, tentative=1)
-                        if w_mod is not None:
-                            space.timer.stop_name("importhook", modulename)
-                            return w_mod
+
+        if ctxt_name is not None:
+            ctxt_name_prefix_parts = ctxt_name.split('.')
+            if level > 0:
+                n = len(ctxt_name_prefix_parts)-level+1
+                assert n>=0
+                ctxt_name_prefix_parts = ctxt_name_prefix_parts[:n]
+            if ctxt_name_prefix_parts and ctxt_w_path is None: # plain module
+                ctxt_name_prefix_parts.pop()
+            if ctxt_name_prefix_parts:
+                rel_modulename = '.'.join(ctxt_name_prefix_parts)
+                if modulename:
+                    rel_modulename += '.' + modulename
+            baselevel = len(ctxt_name_prefix_parts)
+            if rel_modulename is not None:
+                # XXX What is this check about? There is no test for it
+                w_mod = check_sys_modules(space, w(rel_modulename))
+
+                if (w_mod is None or
+                    not space.is_w(w_mod, space.w_None)):
+
+                    # if no level was set, ignore import errors, and
+                    # fall back to absolute import at the end of the
+                    # function.
+                    if level == -1:
+                        tentative = True
                     else:
-                        rel_modulename = None
-    if level > 0:
-        msg = "Attempted relative import in non-package"
-        raise OperationError(space.w_ValueError, w(msg))
+                        tentative = False
+
+                    w_mod = absolute_import(space, rel_modulename,
+                                            baselevel, fromlist_w,
+                                            tentative=tentative)
+                    if w_mod is not None:
+                        space.timer.stop_name("importhook", modulename)
+                        return w_mod
+                else:
+                    rel_modulename = None
+
+        if level > 0:
+            msg = "Attempted relative import in non-package"
+            raise OperationError(space.w_ValueError, w(msg))
     w_mod = absolute_import_try(space, modulename, 0, fromlist_w)
     if w_mod is None or space.is_w(w_mod, space.w_None):
         w_mod = absolute_import(space, modulename, 0, fromlist_w, tentative=0)
@@ -226,6 +242,10 @@
 def _absolute_import(space, modulename, baselevel, fromlist_w, tentative):
     w = space.wrap
 
+    if '/' in modulename or '\\' in modulename:
+        raise OperationError(space.w_ImportError, space.wrap(
+            "Import by filename is not supported."))
+
     w_mod = None
     parts = modulename.split('.')
     prefix = []
@@ -720,11 +740,14 @@
 
     if space.config.objspace.usepycfiles:
         cpathname = pathname + 'c'
-        mtime = int(os.stat(pathname)[stat.ST_MTIME])
+        src_stat = os.stat(pathname)
+        mtime = int(src_stat[stat.ST_MTIME])
+        mode = src_stat[stat.ST_MODE]
         stream = check_compiled_module(space, cpathname, mtime)
     else:
         cpathname = None
         mtime = 0
+        mode = 0
         stream = None
 
     if stream:
@@ -738,7 +761,7 @@
         code_w = parse_source_module(space, pathname, source)
 
         if space.config.objspace.usepycfiles and write_pyc:
-            write_compiled_module(space, code_w, cpathname, mtime)
+            write_compiled_module(space, code_w, cpathname, mode, mtime)
 
     exec_code_module(space, w_mod, code_w)
 
@@ -825,8 +848,18 @@
 
     return w_mod
 
+def open_exclusive(space, cpathname, mode):
+    try:
+        os.unlink(cpathname)
+    except OSError:
+        pass
 
-def write_compiled_module(space, co, cpathname, mtime):
+    flags = (os.O_EXCL|os.O_CREAT|os.O_WRONLY|os.O_TRUNC|
+             streamio.O_BINARY)
+    fd = os.open(cpathname, flags, mode)
+    return streamio.fdopen_as_stream(fd, "wb")
+
+def write_compiled_module(space, co, cpathname, src_mode, src_mtime):
     """
     Write a compiled module to a file, placing the time of last
     modification of its source into the header.
@@ -847,10 +880,16 @@
     # Careful here: we must not crash nor leave behind something that looks
     # too much like a valid pyc file but really isn't one.
     #
+    mode = src_mode & ~0111
     try:
-        stream = streamio.open_file_as_stream(cpathname, "wb")
-    except StreamErrors:
-        return    # cannot create file
+        stream = open_exclusive(space, cpathname, mode)
+    except (OSError, StreamErrors):
+        try:
+            os.unlink(cpathname)
+        except OSError:
+            pass
+        return
+
     try:
         try:
             # will patch the header later; write zeroes until we are sure that
@@ -862,7 +901,7 @@
             # should be ok (XXX or should call os.fsync() to be sure?)
             stream.seek(0, 0)
             _w_long(stream, get_pyc_magic(space))
-            _w_long(stream, mtime)
+            _w_long(stream, src_mtime)
         finally:
             stream.close()
     except StreamErrors:

diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -13,6 +13,7 @@
 class AbstractX86CPU(AbstractLLCPU):
     debug = True
     supports_floats = True
+    supports_longlong = True
 
     BOOTSTRAP_TP = lltype.FuncType([], lltype.Signed)
     dont_keepalive_stuff = False # for tests


diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -265,8 +265,8 @@
     'uint_ge':              LLOp(canfold=True),
     'uint_and':             LLOp(canfold=True),
     'uint_or':              LLOp(canfold=True),
-    'uint_lshift':          LLOp(canfold=True),
-    'uint_rshift':          LLOp(canfold=True),
+    'uint_lshift':          LLOp(canfold=True),  # args (r_uint, int)
+    'uint_rshift':          LLOp(canfold=True),  # args (r_uint, int)
     'uint_xor':             LLOp(canfold=True),
 
     'float_is_true':        LLOp(canfold=True),  # it really means "x != 0.0"
@@ -288,9 +288,7 @@
 
     'llong_is_true':        LLOp(canfold=True),
     'llong_neg':            LLOp(canfold=True),
-    'llong_neg_ovf':        LLOp(canraise=(OverflowError,), tryfold=True),
     'llong_abs':            LLOp(canfold=True),
-    'llong_abs_ovf':        LLOp(canraise=(OverflowError,), tryfold=True),
     'llong_invert':         LLOp(canfold=True),
 
     'llong_add':            LLOp(canfold=True),
@@ -308,8 +306,8 @@
     'llong_ge':             LLOp(canfold=True),
     'llong_and':            LLOp(canfold=True),
     'llong_or':             LLOp(canfold=True),
-    'llong_lshift':         LLOp(canfold=True),
-    'llong_rshift':         LLOp(canfold=True),
+    'llong_lshift':         LLOp(canfold=True),  # args (r_longlong, int)
+    'llong_rshift':         LLOp(canfold=True),  # args (r_longlong, int)
     'llong_xor':            LLOp(canfold=True),
 
     'ullong_is_true':       LLOp(canfold=True),
@@ -330,8 +328,8 @@
     'ullong_ge':            LLOp(canfold=True),
     'ullong_and':           LLOp(canfold=True),
     'ullong_or':            LLOp(canfold=True),
-    'ullong_lshift':        LLOp(canfold=True),
-    'ullong_rshift':        LLOp(canfold=True),
+    'ullong_lshift':        LLOp(canfold=True),  # args (r_ulonglong, int)
+    'ullong_rshift':        LLOp(canfold=True),  # args (r_ulonglong, int)
     'ullong_xor':           LLOp(canfold=True),
 
     'cast_primitive':       LLOp(canfold=True),

diff --git a/pypy/jit/backend/llsupport/test/test_descr.py b/pypy/jit/backend/llsupport/test/test_descr.py
--- a/pypy/jit/backend/llsupport/test/test_descr.py
+++ b/pypy/jit/backend/llsupport/test/test_descr.py
@@ -5,7 +5,7 @@
 from pypy.rpython.annlowlevel import llhelper
 from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr
 from pypy.jit.metainterp import history
-import struct
+import sys, struct, py
 
 def test_get_size_descr():
     c0 = GcCache(False)
@@ -95,6 +95,16 @@
             descr_x = get_field_descr(c2, S, 'x')
             assert descr_x.is_field_signed() == signed
 
+def test_get_field_descr_longlong():
+    if sys.maxint > 2147483647:
+        py.test.skip("long long: for 32-bit only")
+    c0 = GcCache(False)
+    S = lltype.GcStruct('S', ('y', lltype.UnsignedLongLong))
+    descr = get_field_descr(c0, S, 'y')
+    assert not descr.is_pointer_field()
+    assert descr.is_float_field()
+    assert descr.get_field_size(False) == 8
+
 
 def test_get_array_descr():
     U = lltype.Struct('U')
@@ -226,6 +236,21 @@
     assert descr4.get_return_type() == history.FLOAT
     assert descr4.arg_classes == "ff"
 
+def test_get_call_descr_not_translated_longlong():
+    if sys.maxint > 2147483647:
+        py.test.skip("long long: for 32-bit only")
+    c0 = GcCache(False)
+    #
+    descr5 = get_call_descr(c0, [lltype.SignedLongLong], lltype.Signed)
+    assert descr5.get_result_size(False) == 4
+    assert descr5.get_return_type() == history.INT
+    assert descr5.arg_classes == "L"
+    #
+    descr6 = get_call_descr(c0, [lltype.Signed], lltype.SignedLongLong)
+    assert descr6.get_result_size(False) == 8
+    assert descr6.get_return_type() == history.FLOAT
+    assert descr6.arg_classes == "i"
+
 def test_get_call_descr_translated():
     c1 = GcCache(True)
     T = lltype.GcStruct('T')

diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -6,6 +6,8 @@
 from pypy.jit.metainterp import history
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.codewriter import heaptracker
+from pypy.rlib.rarithmetic import r_longlong, r_ulonglong
+from pypy.rlib.longlong2float import longlong2float, float2longlong
 
 # The point of the class organization in this file is to make instances
 # as compact as possible.  This is done by not storing the field size or
@@ -29,6 +31,14 @@
         assert isinstance(ARRAY, lltype.GcArray)
 
 
+if lltype.SignedLongLong is lltype.Signed:
+    def is_longlong(TYPE):
+        return False
+else:
+    assert rffi.sizeof(lltype.SignedLongLong) == rffi.sizeof(lltype.Float)
+    def is_longlong(TYPE):
+        return TYPE in (lltype.SignedLongLong, lltype.UnsignedLongLong)
+
 # ____________________________________________________________
 # SizeDescrs
 
@@ -264,6 +274,8 @@
 
     def create_call_stub(self, rtyper, RESULT):
         def process(c):
+            if c == 'L':
+                return 'float2longlong(%s)' % (process('f'),)
             arg = 'args_%s[%d]' % (c, seen[c])
             seen[c] += 1
             return arg
@@ -277,6 +289,10 @@
                 return llmemory.GCREF
             elif arg == 'v':
                 return lltype.Void
+            elif arg == 'L':
+                return lltype.SignedLongLong
+            else:
+                raise AssertionError(arg)
 
         seen = {'i': 0, 'r': 0, 'f': 0}
         args = ", ".join([process(c) for c in self.arg_classes])
@@ -286,7 +302,7 @@
         elif self.get_return_type() == history.REF:
             result = 'lltype.cast_opaque_ptr(llmemory.GCREF, res)'
         elif self.get_return_type() == history.FLOAT:
-            result = 'res'
+            result = 'cast_to_float(res)'
         elif self.get_return_type() == history.VOID:
             result = 'None'
         else:
@@ -308,11 +324,21 @@
         assert self._return_type == return_type
         assert self.arg_classes.count('i') == len(args_i or ())
         assert self.arg_classes.count('r') == len(args_r or ())
-        assert self.arg_classes.count('f') == len(args_f or ())
+        assert (self.arg_classes.count('f') +
+                self.arg_classes.count('L')) == len(args_f or ())
 
     def repr_of_descr(self):
         return '<%s>' % self._clsname
 
+def cast_to_float(x):
+    if isinstance(x, r_longlong):
+        return longlong2float(x)
+    if isinstance(x, r_ulonglong):
+        return longlong2float(rffi.cast(lltype.SignedLongLong, x))
+    assert isinstance(x, float)
+    return x
+cast_to_float._annspecialcase_ = 'specialize:argtype(0)'
+
 
 class BaseIntCallDescr(BaseCallDescr):
     # Base class of the various subclasses of descrs corresponding to
@@ -371,6 +397,9 @@
     def get_result_size(self, translate_support_code):
         return symbolic.get_size(lltype.Float, translate_support_code)
 
+class LongLongCallDescr(FloatCallDescr):
+    _clsname = 'LongLongCallDescr'
+
 class VoidCallDescr(BaseCallDescr):
     _clsname = 'VoidCallDescr'
     _return_type = history.VOID
@@ -383,6 +412,8 @@
         return VoidCallDescr
     if RESULT is lltype.Float:
         return FloatCallDescr
+    if is_longlong(RESULT):
+        return LongLongCallDescr
     return getDescrClass(RESULT, BaseIntCallDescr, GcPtrCallDescr,
                          NonGcPtrCallDescr, 'Call', 'get_result_size',
                          Ellipsis,  # <= floatattrname should not be used here
@@ -394,7 +425,11 @@
         kind = getkind(ARG)
         if   kind == 'int': arg_classes.append('i')
         elif kind == 'ref': arg_classes.append('r')
-        elif kind == 'float': arg_classes.append('f')
+        elif kind == 'float':
+            if is_longlong(ARG):
+                arg_classes.append('L')
+            else:
+                arg_classes.append('f')
         else:
             raise NotImplementedError('ARG = %r' % (ARG,))
     arg_classes = ''.join(arg_classes)
@@ -432,7 +467,7 @@
             return symbolic.get_size(TYPE, translate_support_code)
         setattr(Descr, methodname, method)
         #
-        if TYPE is lltype.Float:
+        if TYPE is lltype.Float or is_longlong(TYPE):
             setattr(Descr, floatattrname, True)
         elif TYPE is not lltype.Bool and rffi.cast(TYPE, -1) == -1:
             setattr(Descr, signedattrname, True)

diff --git a/pypy/rlib/rsre/rsre_core.py b/pypy/rlib/rsre/rsre_core.py
--- a/pypy/rlib/rsre/rsre_core.py
+++ b/pypy/rlib/rsre/rsre_core.py
@@ -385,10 +385,13 @@
                 marks = p.marks
                 enum = p.enum.move_to_next_result(ctx)
             #
+            # zero-width match protection
             min = ctx.pat(ppos+1)
-            if (enum is not None and
-                (ptr != ctx.match_end or self.num_pending < min)):
-                #               ^^^^^^^^^^ zero-width match protection
+            if self.num_pending >= min:
+                while enum is not None and ptr == ctx.match_end:
+                    enum = enum.move_to_next_result(ctx)
+            #
+            if enum is not None:
                 # matched one more 'item'.  record it and continue.
                 self.pending = Pending(ptr, marks, enum, self.pending)
                 self.num_pending += 1
@@ -436,12 +439,15 @@
             if max == 65535 or self.num_pending < max:
                 # try to match one more 'item'
                 enum = sre_match(ctx, ppos + 3, ptr, marks)
+                #
+                # zero-width match protection
+                if self.num_pending >= min:
+                    while enum is not None and ptr == ctx.match_end:
+                        enum = enum.move_to_next_result(ctx)
             else:
                 enum = None    # 'max' reached, no more matches
 
-            while (enum is None or
-                   (ptr == ctx.match_end and self.num_pending >= min)):
-                #                   ^^^^^^^^^^ zero-width match protection
+            while enum is None:
                 # 'item' does not match; try to get further results from
                 # the 'pending' list.
                 p = self.pending

diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -177,6 +177,13 @@
             #print 'wrapping', x, '->', w_result
             return w_result
         if isinstance(x, base_int):
+            if self.config.objspace.std.withsmalllong:
+                from pypy.objspace.std.smalllongobject import W_SmallLongObject
+                from pypy.rlib.rarithmetic import r_longlong, r_ulonglong
+                from pypy.rlib.rarithmetic import longlongmax
+                if (not isinstance(x, r_ulonglong)
+                    or x <= r_ulonglong(longlongmax)):
+                    return W_SmallLongObject(r_longlong(x))
             x = widen(x)
             if isinstance(x, int):
                 return self.newint(x)
@@ -207,6 +214,16 @@
         # The following cases are even stranger.
         # Really really only for tests.
         if type(x) is long:
+            if self.config.objspace.std.withsmalllong:
+                from pypy.rlib.rarithmetic import r_longlong
+                try:
+                    rx = r_longlong(x)
+                except OverflowError:
+                    pass
+                else:
+                    from pypy.objspace.std.smalllongobject import \
+                                                   W_SmallLongObject
+                    return W_SmallLongObject(rx)
             return W_LongObject.fromlong(x)
         if isinstance(x, slice):
             return W_SliceObject(self.wrap(x.start),
@@ -269,6 +286,9 @@
         return unpackcomplex(self, w_complex)
 
     def newlong(self, val): # val is an int
+        if self.config.objspace.std.withsmalllong:
+            from pypy.objspace.std.smalllongobject import W_SmallLongObject
+            return W_SmallLongObject.fromint(val)
         return W_LongObject.fromint(self, val)
 
     def newlong_from_rbigint(self, val):

diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -155,6 +155,7 @@
         if policy is None:
             policy = JitPolicy()
         policy.set_supports_floats(self.cpu.supports_floats)
+        policy.set_supports_longlong(self.cpu.supports_longlong)
         graphs = self.codewriter.find_all_graphs(policy)
         policy.dump_unsafe_loops()
         self.check_access_directly_sanity(graphs)

diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -4,6 +4,11 @@
 
 class AbstractCPU(object):
     supports_floats = False
+    supports_longlong = False
+    # ^^^ This is only useful on 32-bit platforms.  If True,
+    # longlongs are supported by the JIT, but stored as doubles.
+    # Boxes and Consts are BoxFloats and ConstFloats.
+
     done_with_this_frame_void_v = -1
     done_with_this_frame_int_v = -1
     done_with_this_frame_ref_v = -1

diff --git a/pypy/module/cpyext/include/modsupport.inl b/pypy/module/cpyext/include/modsupport.inl
deleted file mode 100644
--- a/pypy/module/cpyext/include/modsupport.inl
+++ /dev/null
@@ -1,29 +0,0 @@
-/* -*- C -*- */
-/* Module support interface */
-
-#ifndef Py_MODSUPPORT_INL
-#define Py_MODSUPPORT_INL
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef PYPY_STANDALONE
-/* XXX1 On translation, forwarddecl.h is included after this file */
-/* XXX2 genc.py transforms "const char*" into "char*" */
-extern PyObject *_Py_InitPyPyModule(char *, PyMethodDef *, char *, PyObject *, int);
-#endif
-
-Py_LOCAL_INLINE(PyObject *) Py_InitModule4(
-        const char* name, PyMethodDef* methods,
-        const char* doc, PyObject *self,
-        int api_version)
-{
-    return _Py_InitPyPyModule((char*)name, methods,
-                              (char*)doc, self,
-                              api_version);
-}
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* !Py_MODSUPPORT_INL */

diff --git a/pypy/jit/codewriter/call.py b/pypy/jit/codewriter/call.py
--- a/pypy/jit/codewriter/call.py
+++ b/pypy/jit/codewriter/call.py
@@ -188,7 +188,8 @@
                                          FUNC.RESULT)
         return (fnaddr, calldescr)
 
-    def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE):
+    def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE,
+                     extraeffect=None):
         """Return the calldescr that describes all calls done by 'op'.
         This returns a calldescr that we can put in the corresponding
         call operation in the calling jitcode.  It gets an effectinfo
@@ -216,17 +217,18 @@
                 assert not NON_VOID_ARGS, ("arguments not supported for "
                                            "loop-invariant function!")
         # build the extraeffect
-        if self.virtualizable_analyzer.analyze(op):
-            extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
-        elif loopinvariant:
-            extraeffect = EffectInfo.EF_LOOPINVARIANT
-        elif pure:
-            # XXX check what to do about exceptions (also MemoryError?)
-            extraeffect = EffectInfo.EF_PURE
-        elif self._canraise(op):
-            extraeffect = EffectInfo.EF_CAN_RAISE
-        else:
-            extraeffect = EffectInfo.EF_CANNOT_RAISE
+        if extraeffect is None:
+            if self.virtualizable_analyzer.analyze(op):
+                extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
+            elif loopinvariant:
+                extraeffect = EffectInfo.EF_LOOPINVARIANT
+            elif pure:
+                # XXX check what to do about exceptions (also MemoryError?)
+                extraeffect = EffectInfo.EF_PURE
+            elif self._canraise(op):
+                extraeffect = EffectInfo.EF_CAN_RAISE
+            else:
+                extraeffect = EffectInfo.EF_CANNOT_RAISE
         #
         effectinfo = effectinfo_from_writeanalyze(
             self.readwrite_analyzer.analyze(op), self.cpu, extraeffect,

diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -37,6 +37,7 @@
 from pypy.rlib import rgc
 from pypy.jit.backend.x86.jump import remap_frame_layout
 from pypy.jit.metainterp.history import ConstInt, BoxInt
+from pypy.jit.codewriter.effectinfo import EffectInfo
 
 # darwin requires the stack to be 16 bytes aligned on calls. Same for gcc 4.5.0,
 # better safe than sorry
@@ -769,6 +770,11 @@
     def regalloc_perform_discard(self, op, arglocs):
         genop_discard_list[op.getopnum()](self, op, arglocs)
 
+    def regalloc_perform_llong(self, op, arglocs, resloc):
+        effectinfo = op.getdescr().get_extra_info()
+        oopspecindex = effectinfo.oopspecindex
+        genop_llong_list[oopspecindex](self, op, arglocs, resloc)
+
     def regalloc_perform_with_guard(self, op, guard_op, faillocs,
                                     arglocs, resloc, current_depths):
         faildescr = guard_op.getdescr()
@@ -1115,6 +1121,88 @@
         self.mc.XOR_rr(edx.value, edx.value)
         self.mc.DIV_r(ecx.value)
 
+    genop_llong_add = _binaryop("PADDQ", True)
+    genop_llong_sub = _binaryop("PSUBQ")
+    genop_llong_and = _binaryop("PAND",  True)
+    genop_llong_or  = _binaryop("POR",   True)
+    genop_llong_xor = _binaryop("PXOR",  True)
+
+    def genop_llong_to_int(self, op, arglocs, resloc):
+        loc = arglocs[0]
+        assert isinstance(resloc, RegLoc)
+        if isinstance(loc, RegLoc):
+            self.mc.MOVD_rx(resloc.value, loc.value)
+        elif isinstance(loc, StackLoc):
+            self.mc.MOV_rb(resloc.value, loc.value)
+        else:
+            not_implemented("llong_to_int: %s" % (loc,))
+
+    def genop_llong_from_int(self, op, arglocs, resloc):
+        loc = arglocs[0]
+        if isinstance(loc, ConstFloatLoc):
+            self.mc.MOVSD(resloc, loc)
+        else:
+            assert loc is eax
+            assert isinstance(resloc, RegLoc)
+            loc2 = arglocs[1]
+            assert isinstance(loc2, RegLoc)
+            self.mc.CDQ()       # eax -> eax:edx
+            self.mc.MOVD_xr(resloc.value, eax.value)
+            self.mc.MOVD_xr(loc2.value, edx.value)
+            self.mc.PUNPCKLDQ_xx(resloc.value, loc2.value)
+
+    def genop_llong_from_two_ints(self, op, arglocs, resloc):
+        assert isinstance(resloc, RegLoc)
+        loc1, loc2, loc3 = arglocs
+        #
+        if isinstance(loc1, ConstFloatLoc):
+            self.mc.MOVSD(resloc, loc1)
+        else:
+            assert isinstance(loc1, RegLoc)
+            self.mc.MOVD_xr(resloc.value, loc1.value)
+        #
+        if loc2 is not None:
+            assert isinstance(loc3, RegLoc)
+            if isinstance(loc2, ConstFloatLoc):
+                self.mc.MOVSD(loc3, loc2)
+            else:
+                assert isinstance(loc2, RegLoc)
+                self.mc.MOVD_xr(loc3.value, loc2.value)
+            self.mc.PUNPCKLDQ_xx(resloc.value, loc3.value)
+
+    def genop_llong_eq(self, op, arglocs, resloc):
+        loc1, loc2, locxtmp = arglocs
+        self.mc.MOVSD(locxtmp, loc1)
+        self.mc.PCMPEQD(locxtmp, loc2)
+        self.mc.PMOVMSKB_rx(resloc.value, locxtmp.value)
+        # Now the lower 8 bits of resloc contain 0x00, 0x0F, 0xF0 or 0xFF
+        # depending on the result of the comparison of each of the two
+        # double-words of loc1 and loc2.  The higher 8 bits contain random
+        # results.  We want to map 0xFF to 1, and 0x00, 0x0F and 0xF0 to 0.
+        self.mc.CMP8_ri(resloc.value | rx86.BYTE_REG_FLAG, -1)
+        self.mc.SBB_rr(resloc.value, resloc.value)
+        self.mc.ADD_ri(resloc.value, 1)
+
+    def genop_llong_ne(self, op, arglocs, resloc):
+        loc1, loc2, locxtmp = arglocs
+        self.mc.MOVSD(locxtmp, loc1)
+        self.mc.PCMPEQD(locxtmp, loc2)
+        self.mc.PMOVMSKB_rx(resloc.value, locxtmp.value)
+        # Now the lower 8 bits of resloc contain 0x00, 0x0F, 0xF0 or 0xFF
+        # depending on the result of the comparison of each of the two
+        # double-words of loc1 and loc2.  The higher 8 bits contain random
+        # results.  We want to map 0xFF to 0, and 0x00, 0x0F and 0xF0 to 1.
+        self.mc.CMP8_ri(resloc.value | rx86.BYTE_REG_FLAG, -1)
+        self.mc.SBB_rr(resloc.value, resloc.value)
+        self.mc.NEG_r(resloc.value)
+
+    def genop_llong_lt(self, op, arglocs, resloc):
+        # XXX just a special case for now: "x < 0"
+        loc1, = arglocs
+        self.mc.PMOVMSKB_rx(resloc.value, loc1.value)
+        self.mc.SHR_ri(resloc.value, 7)
+        self.mc.AND_ri(resloc.value, 1)
+
     def genop_new_with_vtable(self, op, arglocs, result_loc):
         assert result_loc is eax
         loc_vtable = arglocs[-1]
@@ -1725,7 +1813,14 @@
         self._emit_call(x, arglocs, 3, tmp=tmp)
 
         if IS_X86_32 and isinstance(resloc, StackLoc) and resloc.width == 8:
-            self.mc.FSTP_b(resloc.value)   # float return
+            # a float or a long long return
+            from pypy.jit.backend.llsupport.descr import LongLongCallDescr
+            if isinstance(op.getdescr(), LongLongCallDescr):
+                self.mc.MOV_br(resloc.value, eax.value)      # long long
+                self.mc.MOV_br(resloc.value + 4, edx.value)
+                # XXX should ideally not move the result on the stack
+            else:
+                self.mc.FSTP_b(resloc.value)   # float return
         elif size == WORD:
             assert resloc is eax or resloc is xmm0    # a full word
         elif size == 0:
@@ -1959,6 +2054,7 @@
         
 genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST
 genop_list = [Assembler386.not_implemented_op] * rop._LAST
+genop_llong_list = {}
 genop_guard_list = [Assembler386.not_implemented_op_guard] * rop._LAST
 
 for name, value in Assembler386.__dict__.iteritems():
@@ -1970,6 +2066,10 @@
         opname = name[len('genop_guard_'):]
         num = getattr(rop, opname.upper())
         genop_guard_list[num] = value
+    elif name.startswith('genop_llong_'):
+        opname = name[len('genop_llong_'):]
+        num = getattr(EffectInfo, 'OS_LLONG_' + opname.upper())
+        genop_llong_list[num] = value
     elif name.startswith('genop_'):
         opname = name[len('genop_'):]
         num = getattr(rop, opname.upper())

diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -19,6 +19,7 @@
 from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
 from pypy.jit.metainterp.typesystem import deref
 from pypy.rlib import rgc
+from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint, intmask
 
 def getargtypes(annotator, values):
     if values is None:    # for backend tests producing stand-alone exe's
@@ -222,6 +223,136 @@
         return x
 
 
+# long long support
+# -----------------
+
+def u_to_longlong(x):
+    return rffi.cast(lltype.SignedLongLong, x)
+
+def _ll_1_llong_invert(xll):
+    y = ~r_ulonglong(xll)
+    return u_to_longlong(y)
+
+def _ll_2_llong_lt(xll, yll):
+    return xll < yll
+
+def _ll_2_llong_le(xll, yll):
+    return xll <= yll
+
+def _ll_2_llong_eq(xll, yll):
+    return xll == yll
+
+def _ll_2_llong_ne(xll, yll):
+    return xll != yll
+
+def _ll_2_llong_gt(xll, yll):
+    return xll > yll
+
+def _ll_2_llong_ge(xll, yll):
+    return xll >= yll
+
+def _ll_2_llong_ult(xull, yull):
+    return xull < yull
+
+def _ll_2_llong_ule(xull, yull):
+    return xull <= yull
+
+def _ll_2_llong_ugt(xull, yull):
+    return xull > yull
+
+def _ll_2_llong_uge(xull, yull):
+    return xull >= yull
+
+def _ll_2_llong_add(xll, yll):
+    z = r_ulonglong(xll) + r_ulonglong(yll)
+    return u_to_longlong(z)
+
+def _ll_2_llong_sub(xll, yll):
+    z = r_ulonglong(xll) - r_ulonglong(yll)
+    return u_to_longlong(z)
+
+def _ll_2_llong_mul(xll, yll):
+    z = r_ulonglong(xll) * r_ulonglong(yll)
+    return u_to_longlong(z)
+
+def _ll_2_llong_and(xll, yll):
+    z = r_ulonglong(xll) & r_ulonglong(yll)
+    return u_to_longlong(z)
+
+def _ll_2_llong_or(xll, yll):
+    z = r_ulonglong(xll) | r_ulonglong(yll)
+    return u_to_longlong(z)
+
+def _ll_2_llong_xor(xll, yll):
+    z = r_ulonglong(xll) ^ r_ulonglong(yll)
+    return u_to_longlong(z)
+
+def _ll_2_llong_lshift(xll, y):
+    z = r_ulonglong(xll) << y
+    return u_to_longlong(z)
+
+def _ll_2_llong_rshift(xll, y):
+    return xll >> y
+
+def _ll_2_llong_urshift(xull, y):
+    return xull >> y
+
+def _ll_1_llong_from_int(x):
+    return r_longlong(intmask(x))
+
+def _ll_2_llong_from_two_ints(x_lo, x_hi):
+    z = (r_ulonglong(r_uint(x_hi)) << 32) | r_ulonglong(r_uint(x_lo))
+    return u_to_longlong(z)
+
+def _ll_1_llong_to_int(xll):
+    return intmask(xll)
+
+def _ll_1_llong_from_float(xf):
+    return r_longlong(xf)
+
+def _ll_1_llong_to_float(xll):
+    return float(rffi.cast(lltype.SignedLongLong, xll))
+
+
+def _ll_1_llong_abs(xll):
+    if xll < 0:
+        return -xll
+    else:
+        return xll
+
+def _ll_2_llong_floordiv(xll, yll):
+    return llop.llong_floordiv(lltype.SignedLongLong, xll, yll)
+
+def _ll_2_llong_floordiv_zer(xll, yll):
+    if yll == 0:
+        raise ZeroDivisionError
+    return llop.llong_floordiv(lltype.SignedLongLong, xll, yll)
+
+def _ll_2_llong_mod(xll, yll):
+    return llop.llong_mod(lltype.SignedLongLong, xll, yll)
+
+def _ll_2_llong_mod_zer(xll, yll):
+    if yll == 0:
+        raise ZeroDivisionError
+    return llop.llong_mod(lltype.SignedLongLong, xll, yll)
+
+def _ll_2_ullong_floordiv(xll, yll):
+    return llop.ullong_floordiv(lltype.SignedLongLong, xll, yll)
+
+def _ll_2_ullong_floordiv_zer(xll, yll):
+    if yll == 0:
+        raise ZeroDivisionError
+    return llop.ullong_floordiv(lltype.SignedLongLong, xll, yll)
+
+def _ll_2_ullong_mod(xll, yll):
+    return llop.ullong_mod(lltype.SignedLongLong, xll, yll)
+
+def _ll_2_ullong_mod_zer(xll, yll):
+    if yll == 0:
+        raise ZeroDivisionError
+    return llop.ullong_mod(lltype.SignedLongLong, xll, yll)
+
+
 # libffi support
 # --------------
 

diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -4,6 +4,7 @@
 from pypy.config.config import OptionDescription, BoolOption, IntOption, ArbitraryOption
 from pypy.config.config import ChoiceOption, StrOption, to_optparse, Config
 from pypy.config.config import ConflictConfigError
+from pypy.config.translationoption import IS_64_BITS
 
 modulepath = py.path.local(__file__).dirpath().dirpath().join("module")
 all_modules = [p.basename for p in modulepath.listdir()
@@ -212,6 +213,11 @@
         IntOption("prebuiltintto", "highest integer which is prebuilt",
                   default=100, cmdline="--prebuiltintto"),
 
+        BoolOption("withsmalllong", "use a version of 'long' in a C long long",
+                   default=False,
+                   requires=[("objspace.std.withsmallint", False)]),
+                             #  ^^^ because of missing delegate_xx2yy
+
         BoolOption("withstrjoin", "use strings optimized for addition",
                    default=False),
 
@@ -345,6 +351,8 @@
         config.objspace.std.suggest(optimized_list_getitem=True)
         config.objspace.std.suggest(getattributeshortcut=True)
         config.objspace.std.suggest(newshortcut=True)        
+        if not IS_64_BITS:
+            config.objspace.std.suggest(withsmalllong=True)
 
     # extra costly optimizations only go in level 3
     if level == '3':
@@ -360,6 +368,8 @@
         config.objspace.std.suggest(withmapdict=True)
         config.objspace.std.suggest(withstrslice=True)
         config.objspace.std.suggest(withstrjoin=True)
+        if not IS_64_BITS:
+            config.objspace.std.suggest(withsmalllong=True)
         # xxx other options? ropes maybe?
 
     # completely disable geninterp in a level 0 translation


More information about the Pypy-commit mailing list