From fijal at codespeak.net Mon Oct 1 08:57:51 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 1 Oct 2007 08:57:51 +0200 (CEST) Subject: [pypy-svn] r47055 - in pypy/dist/pypy/module/rctime: . test Message-ID: <20071001065751.2B2B88125@code0.codespeak.net> Author: fijal Date: Mon Oct 1 08:57:49 2007 New Revision: 47055 Modified: pypy/dist/pypy/module/rctime/__init__.py pypy/dist/pypy/module/rctime/app_time.py pypy/dist/pypy/module/rctime/interp_time.py pypy/dist/pypy/module/rctime/test/test_rctime.py Log: Move rctime from rctypes to rffi (name makes no longer sense). Next step: * unify with time * check locking Modified: pypy/dist/pypy/module/rctime/__init__.py ============================================================================== --- pypy/dist/pypy/module/rctime/__init__.py (original) +++ pypy/dist/pypy/module/rctime/__init__.py Mon Oct 1 08:57:49 2007 @@ -18,6 +18,7 @@ 'localtime': 'interp_time.localtime', 'mktime': 'interp_time.mktime', 'strftime': 'interp_time.strftime', + 'sleep' : 'interp_time.sleep', } def buildloaders(cls): @@ -25,10 +26,7 @@ import os if os.name == "posix": - Module.appleveldefs['sleep'] = 'app_time.sleep' Module.interpleveldefs['tzset'] = 'interp_time.tzset' - elif os.name == "nt": - Module.interpleveldefs['sleep'] = 'interp_time.sleep' # this machinery is needed to expose constants # that have to be initialized one time only Modified: pypy/dist/pypy/module/rctime/app_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/app_time.py (original) +++ pypy/dist/pypy/module/rctime/app_time.py Mon Oct 1 08:57:49 2007 @@ -19,20 +19,6 @@ tm_yday = structseqfield(7) tm_isdst = structseqfield(8) - -if _POSIX: - from select import select - - def sleep(secs): - """sleep(seconds) - - Delay execution for a given number of seconds. The argument may be - a floating point number for subsecond precision.""" - if secs is None: - raise TypeError('a float is required') - select([], [], [], secs) - - def strptime(string, format="%a %b %d %H:%M:%S %Y"): """strptime(string, format) -> struct_time Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Mon Oct 1 08:57:49 2007 @@ -1,54 +1,55 @@ -from pypy.rpython.rctypes.tool import ctypes_platform -from pypy.rpython.rctypes.tool.libc import libc -import pypy.rpython.rctypes.implementation # this defines rctypes magic -from pypy.rpython.rctypes.aerrno import geterrno +from pypy.rpython.tool import rffi_platform as platform +from pypy.rpython.lltypesystem import rffi from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import W_Root, ObjSpace +from pypy.rpython.lltypesystem import lltype from pypy.rlib.rarithmetic import ovfcheck_float_to_int -from ctypes import * import math import os import sys +import time as pytime _POSIX = os.name == "posix" _WIN = os.name == "nt" -_include = "#include " +_includes = ["time.h"] if _POSIX: - _include = """%s - #include """ % _include - + _includes.append('sys/time.h') + class CConfig: - _header_ = _include - CLOCKS_PER_SEC = ctypes_platform.ConstantInteger("CLOCKS_PER_SEC") - clock_t = ctypes_platform.SimpleType("clock_t", c_ulong) - time_t = ctypes_platform.SimpleType("time_t", c_long) - size_t = ctypes_platform.SimpleType("size_t", c_long) + _includes_ = _includes + CLOCKS_PER_SEC = platform.ConstantInteger("CLOCKS_PER_SEC") + clock_t = platform.SimpleType("clock_t", rffi.ULONG) + time_t = platform.SimpleType("time_t", rffi.LONG) + size_t = platform.SimpleType("size_t", rffi.LONG) + has_gettimeofday = platform.Has('gettimeofday') if _POSIX: - CConfig.timeval = ctypes_platform.Struct("struct timeval", [("tv_sec", c_int), - ("tv_usec", c_int)]) - CConfig.tm = ctypes_platform.Struct("struct tm", [("tm_sec", c_int), - ("tm_min", c_int), ("tm_hour", c_int), ("tm_mday", c_int), - ("tm_mon", c_int), ("tm_year", c_int), ("tm_wday", c_int), - ("tm_yday", c_int), ("tm_isdst", c_int), ("tm_gmtoff", c_long), - ("tm_zone", c_char_p)]) + calling_conv = 'c' + CConfig.timeval = platform.Struct("struct timeval", + [("tv_sec", rffi.INT), + ("tv_usec", rffi.INT)]) + CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), + ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), + ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), + ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT), ("tm_gmtoff", rffi.LONG), + ("tm_zone", rffi.CCHARP)]) elif _WIN: - from ctypes import wintypes - CConfig.tm = ctypes_platform.Struct("struct tm", [("tm_sec", c_int), - ("tm_min", c_int), ("tm_hour", c_int), ("tm_mday", c_int), - ("tm_mon", c_int), ("tm_year", c_int), ("tm_wday", c_int), - ("tm_yday", c_int), ("tm_isdst", c_int)]) - - LARGE_INTEGER = wintypes.LARGE_INTEGER - BOOL = wintypes.BOOL - DWORD = wintypes.DWORD + calling_conf = 'win' + CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), + ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), + ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), + ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT)]) class cConfig: pass -cConfig.__dict__.update(ctypes_platform.configure(CConfig)) +cConfig.__dict__.update(platform.configure(CConfig)) cConfig.tm.__name__ = "_tm" +def external(name, args, result): + return rffi.llexternal(name, args, result, + includes=_includes, calling_conv=calling_conv) + if _POSIX: cConfig.timeval.__name__ = "_timeval" timeval = cConfig.timeval @@ -58,40 +59,35 @@ time_t = cConfig.time_t size_t = cConfig.size_t tm = cConfig.tm +glob_buf = lltype.malloc(tm, flavor='raw') -has_gettimeofday = False -if hasattr(libc, "gettimeofday"): - libc.gettimeofday.argtypes = [c_void_p, c_void_p] - libc.gettimeofday.restype = c_int - has_gettimeofday = True -libc.clock.restype = clock_t -libc.time.argtypes = [POINTER(time_t)] -libc.time.restype = time_t -libc.ctime.argtypes = [POINTER(time_t)] -libc.ctime.restype = c_char_p -libc.gmtime.argtypes = [POINTER(time_t)] -libc.gmtime.restype = POINTER(tm) -libc.localtime.argtypes = [POINTER(time_t)] -libc.localtime.restype = POINTER(tm) -libc.mktime.argtypes = [POINTER(tm)] -libc.mktime.restype = time_t -libc.asctime.argtypes = [POINTER(tm)] -libc.asctime.restype = c_char_p +if cConfig.has_gettimeofday: + c_gettimeofday = external('gettimeofday', [rffi.VOIDP, rffi.VOIDP], rffi.INT) +TIME_TP = lltype.Ptr(rffi.CFixedArray(time_t, 1)) +TM_P = lltype.Ptr(tm) +c_clock = external('clock', [TIME_TP], clock_t) +c_time = external('time', [TIME_TP], time_t) +c_ctime = external('ctime', [TIME_TP], rffi.CCHARP) +c_gmtime = external('gmtime', [TIME_TP], TM_P) +c_mktime = external('mktime', [TM_P], time_t) +c_asctime = external('asctime', [TM_P], rffi.CCHARP) +c_localtime = external('localtime', [TIME_TP], TM_P) if _POSIX: - libc.tzset.restype = None # tzset() returns void + c_tzset = external('tzset', [], lltype.Void) elif _WIN: - QueryPerformanceCounter = windll.kernel32.QueryPerformanceCounter - QueryPerformanceCounter.argtypes = [POINTER(LARGE_INTEGER)] - QueryPerformanceCounter.restype = BOOL - QueryPerformanceFrequency = windll.kernel32.QueryPerformanceFrequency - QueryPerformanceFrequency.argtypes = [POINTER(LARGE_INTEGER)] - QueryPerformanceFrequency.restype = BOOL - Sleep = windll.kernel32.Sleep - Sleep.argtypes = [DWORD] - Sleep.restype = None -libc.strftime.argtypes = [c_char_p, size_t, c_char_p, POINTER(tm)] -libc.strftime.restype = size_t - + XXX + #c_QueryPerformanceCounter = external( + #QueryPerformanceCounter = windll.kernel32.QueryPerformanceCounter + #QueryPerformanceCounter.argtypes = [POINTER(LARGE_INTEGER)] + #QueryPerformanceCounter.restype = BOOL + #QueryPerformanceFrequency = windll.kernel32.QueryPerformanceFrequency + #QueryPerformanceFrequency.argtypes = [POINTER(LARGE_INTEGER)] + #QueryPerformanceFrequency.restype = BOOL + #Sleep = windll.kernel32.Sleep + #Sleep.argtypes = [DWORD] + #Sleep.restype = None +c_strftime = external('strftime', [rffi.CCHARP, size_t, rffi.CCHARP, TM_P], + size_t) def _init_accept2dyear(): return (1, 0)[bool(os.getenv("PYTHONY2K"))] @@ -117,81 +113,42 @@ if _POSIX: YEAR = (365 * 24 + 6) * 3600 - t = (((libc.time(byref(time_t(0)))) / YEAR) * YEAR) - tt = time_t(t) - p = libc.localtime(byref(tt)).contents - janzone = -p.tm_gmtoff - janname = [" ", p.tm_zone][bool(p.tm_zone)] - tt = time_t(tt.value + YEAR / 2) - p = libc.localtime(byref(tt)).contents - julyzone = -p.tm_gmtoff - julyname = [" ", p.tm_zone][bool(p.tm_zone)] + t = (((c_time(lltype.nullptr(TIME_TP.TO))) / YEAR) * YEAR) + # we cannot have reference to stack variable, put it on the heap + t_ref = lltype.malloc(TIME_TP.TO, flavor='raw') + t_ref[0] = t + p = c_localtime(t_ref) + janzone = -p.c_tm_gmtoff + janname = [" ", p.c_tm_zone][bool(p.c_tm_zone)] + tt = t + YEAR / 2 + t_ref[0] = tt + p = c_localtime(t_ref) + lltype.free(t_ref, flavor='raw') + julyzone = -p.c_tm_gmtoff + julyname = [" ", p.c_tm_zone][bool(p.c_tm_zone)] if janzone < julyzone: # DST is reversed in the southern hemisphere timezone = julyzone altzone = janzone daylight = int(janzone != julyzone) - tzname = [julyname, janname] + tzname = (julyname, janname) else: timezone = janzone altzone = julyzone daylight = int(janzone != julyzone) - tzname = [janname, julyname] - - return timezone, daylight, tzname, altzone + tzname = (janname, julyname) + start, end = tzname + + return timezone, daylight, [rffi.charp2str(start), rffi.charp2str(end)], altzone def _get_error_msg(): - errno = geterrno() + errno = rff.get_errno() return os.strerror(errno) - -def _floattime(): - """ _floattime() -> computes time since the Epoch for various platforms. - - Since on some system gettimeofday may fail we fall back on ftime - or time. - gettimeofday() has a resolution in microseconds - ftime() has a resolution in milliseconds and it never fails - time() has a resolution in seconds - """ - - if has_gettimeofday: - t = timeval() - if libc.gettimeofday(byref(t), c_void_p(None)) == 0: - return float(t.tv_sec) + t.tv_usec * 0.000001 - - return float(libc.time(None)) - - # elif hasattr(_libc, "ftime"): - # t = _timeb() - # _libc.ftime.argtypes = [c_void_p] - # _libc.ftime(byref(t)) - # return float(t.time) + float(t.millitm) * 0.001 - # elif hasattr(_libc, "time"): - # t = c_long() - # _libc.time.argtypes = [c_void_p] - # _libc.time(byref(t)) - # return t.value - -if _WIN: - def sleep(space, w_secs): - """sleep(seconds) - - Delay execution for a given number of seconds. The argument may be - a floating point number for subsecond precision.""" - - secs = space.float_w(w_secs) - if secs < 0.0: - secs = 0.0 - msecs = secs * 1000.0 - try: - msecs = ovfcheck_float_to_int(msecs) - except OverflowError: - raise OperationError(space.w_OverflowError, - space.wrap("sleep length is too large")) - ul_millis = c_ulong(msecs) - Sleep(ul_millis) +def sleep(secs): + pytime.sleep(secs) +sleep.unwrap_spec = [float] def _get_module_object(space, obj_name): w_module = space.getbuiltinmodule('time') @@ -206,7 +163,7 @@ # w_seconds can be a wrapped None (it will be automatically wrapped # in the callers, so we never get a real None here). if space.is_w(w_seconds, space.w_None): - seconds = _floattime() + seconds = pytime.time() else: seconds = space.float_w(w_seconds) try: @@ -218,15 +175,15 @@ def _tm_to_tuple(space, t): time_tuple = [] - time_tuple.append(space.wrap(t.tm_year + 1900)) - time_tuple.append(space.wrap(t.tm_mon + 1)) # want january == 1 - time_tuple.append(space.wrap(t.tm_mday)) - time_tuple.append(space.wrap(t.tm_hour)) - time_tuple.append(space.wrap(t.tm_min)) - time_tuple.append(space.wrap(t.tm_sec)) - time_tuple.append(space.wrap((t.tm_wday + 6) % 7)) # want monday == 0 - time_tuple.append(space.wrap(t.tm_yday + 1)) # want january, 1 == 1 - time_tuple.append(space.wrap(t.tm_isdst)) + time_tuple.append(space.wrap(t.c_tm_year + 1900)) + time_tuple.append(space.wrap(t.c_tm_mon + 1)) # want january == 1 + time_tuple.append(space.wrap(t.c_tm_mday)) + time_tuple.append(space.wrap(t.c_tm_hour)) + time_tuple.append(space.wrap(t.c_tm_min)) + time_tuple.append(space.wrap(t.c_tm_sec)) + time_tuple.append(space.wrap((t.c_tm_wday + 6) % 7)) # want monday == 0 + time_tuple.append(space.wrap(t.c_tm_yday + 1)) # want january, 1 == 1 + time_tuple.append(space.wrap(t.c_tm_isdst)) w_struct_time = _get_module_object(space, 'struct_time') w_time_tuple = space.newtuple(time_tuple) @@ -235,12 +192,15 @@ def _gettmarg(space, w_tup, allowNone=True): if allowNone and space.is_w(w_tup, space.w_None): # default to the current local time - tt = time_t(int(_floattime())) - pbuf = libc.localtime(byref(tt)) + tt = int(pytime.time()) + t_ref = lltype.malloc(TIME_TP.TO, flavor='raw') + t_ref[0] = tt + pbuf = c_localtime(t_ref) + lltype.free(t_ref, flavor='raw') if not pbuf: raise OperationError(space.w_ValueError, space.wrap(_get_error_msg())) - return pbuf.contents + return pbuf tup_w = space.unpackiterable(w_tup) if len(tup_w) != 9: @@ -248,16 +208,16 @@ space.wrap("argument must be sequence of " "length 9, not %d" % len(tup_w))) - buf = tm() y = space.int_w(tup_w[0]) - buf.tm_mon = space.int_w(tup_w[1]) - buf.tm_mday = space.int_w(tup_w[2]) - buf.tm_hour = space.int_w(tup_w[3]) - buf.tm_min = space.int_w(tup_w[4]) - buf.tm_sec = space.int_w(tup_w[5]) - buf.tm_wday = space.int_w(tup_w[6]) - buf.tm_yday = space.int_w(tup_w[7]) - buf.tm_isdst = space.int_w(tup_w[8]) + glob_buf.c_tm_mon = space.int_w(tup_w[1]) + glob_buf.c_tm_mday = space.int_w(tup_w[2]) + glob_buf.c_tm_hour = space.int_w(tup_w[3]) + glob_buf.c_tm_min = space.int_w(tup_w[4]) + glob_buf.c_tm_sec = space.int_w(tup_w[5]) + glob_buf.c_tm_wday = space.int_w(tup_w[6]) + glob_buf.c_tm_yday = space.int_w(tup_w[7]) + glob_buf.c_tm_isdst = space.int_w(tup_w[8]) + glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) w_accept2dyear = _get_module_object(space, "accept2dyear") accept2dyear = space.int_w(w_accept2dyear) @@ -275,16 +235,16 @@ raise OperationError(space.w_ValueError, space.wrap("year out of range")) - if buf.tm_wday < 0: + if glob_buf.c_tm_wday < 0: raise OperationError(space.w_ValueError, space.wrap("day of week out of range")) - buf.tm_year = y - 1900 - buf.tm_mon = buf.tm_mon - 1 - buf.tm_wday = (buf.tm_wday + 1) % 7 - buf.tm_yday = buf.tm_yday - 1 + glob_buf.c_tm_year = y - 1900 + glob_buf.c_tm_mon = glob_buf.c_tm_mon - 1 + glob_buf.c_tm_wday = (glob_buf.c_tm_wday + 1) % 7 + glob_buf.c_tm_yday = glob_buf.c_tm_yday - 1 - return buf + return glob_buf def time(space): """time() -> floating point number @@ -292,7 +252,7 @@ Return the current time in seconds since the Epoch. Fractions of a second may be present if the system clock provides them.""" - secs = _floattime() + secs = pytime.time() return space.wrap(secs) if _WIN: @@ -300,7 +260,7 @@ pass pccache = PCCache() pccache.divisor = 0.0 - pccache.ctrStart = LARGE_INTEGER() + pccache.ctrStart = 0 def clock(space): """clock() -> floating point number @@ -309,22 +269,7 @@ the first call to clock(). This has as much precision as the system records.""" - if _POSIX: - res = float(libc.clock()) / CLOCKS_PER_SEC - return space.wrap(res) - elif _WIN: - if pccache.divisor == 0.0: - freq = LARGE_INTEGER() - res = QueryPerformanceFrequency(byref(freq)) - if not res or not freq: - return space.wrap(float(libc.clock()) / CLOCKS_PER_SEC) - pccache.divisor = float(freq.value) - QueryPerformanceCounter(byref(pccache.ctrStart)) - - now = LARGE_INTEGER() - QueryPerformanceCounter(byref(now)) - diff = float(now.value - pccache.ctrStart.value) - return space.wrap(diff / pccache.divisor) + return space.wrap(pytime.clock()) def ctime(space, w_seconds=None): """ctime([seconds]) -> string @@ -334,14 +279,16 @@ not present, current time as returned by localtime() is used.""" seconds = _get_inttime(space, w_seconds) - tt = time_t(seconds) - - p = libc.ctime(byref(tt)) + + t_ref = lltype.malloc(TIME_TP.TO, flavor='raw') + t_ref[0] = seconds + p = c_ctime(t_ref) + lltype.free(t_ref, flavor='raw') if not p: raise OperationError(space.w_ValueError, space.wrap("unconvertible time")) - return space.wrap(p[:-1]) # get rid of new line + return space.wrap(rffi.charp2str(p)[:-1]) # get rid of new line ctime.unwrap_spec = [ObjSpace, W_Root] # by now w_tup is an optional argument (and not *args) @@ -353,12 +300,12 @@ When the time tuple is not present, current time as returned by localtime() is used.""" buf_value = _gettmarg(space, w_tup) - p = libc.asctime(byref(buf_value)) + p = c_asctime(buf_value) if not p: raise OperationError(space.w_ValueError, space.wrap("unconvertible time")) - return space.wrap(p[:-1]) # get rid of new line + return space.wrap(rffi.charp2str(p)[:-1]) # get rid of new line asctime.unwrap_spec = [ObjSpace, W_Root] def gmtime(space, w_seconds=None): @@ -372,12 +319,14 @@ # rpython does not support that a variable has two incompatible builtins # as value so we have to duplicate the code. NOT GOOD! see localtime() too seconds = _get_inttime(space, w_seconds) - whent = time_t(seconds) - p = libc.gmtime(byref(whent)) + t_ref = lltype.malloc(TIME_TP.TO, flavor='raw') + t_ref[0] = seconds + p = c_gmtime(t_ref) + lltype.free(t_ref, flavor='raw') if not p: raise OperationError(space.w_ValueError, space.wrap(_get_error_msg())) - return _tm_to_tuple(space, p.contents) + return _tm_to_tuple(space, p) gmtime.unwrap_spec = [ObjSpace, W_Root] def localtime(space, w_seconds=None): @@ -388,12 +337,14 @@ When 'seconds' is not passed in, convert the current time instead.""" seconds = _get_inttime(space, w_seconds) - whent = time_t(seconds) - p = libc.localtime(byref(whent)) + t_ref = lltype.malloc(TIME_TP.TO, flavor='raw') + t_ref[0] = seconds + p = c_localtime(t_ref) + lltype.free(t_ref, flavor='raw') if not p: raise OperationError(space.w_ValueError, space.wrap(_get_error_msg())) - return _tm_to_tuple(space, p.contents) + return _tm_to_tuple(space, p) localtime.unwrap_spec = [ObjSpace, W_Root] def mktime(space, w_tup): @@ -402,7 +353,7 @@ Convert a time tuple in local time to seconds since the Epoch.""" buf = _gettmarg(space, w_tup, allowNone=False) - tt = libc.mktime(byref(buf)) + tt = c_mktime(buf) if tt == -1: raise OperationError(space.w_OverflowError, space.wrap("mktime argument out of range")) @@ -424,7 +375,7 @@ the local timezone used by methods such as localtime, but this behaviour should not be relied on""" - libc.tzset() + c_tzset() # reset timezone, altzone, daylight and tzname timezone, daylight, tzname, altzone = _init_timezone() @@ -441,40 +392,39 @@ Convert a time tuple to a string according to a format specification. See the library reference manual for formatting codes. When the time tuple is not present, current time as returned by localtime() is used.""" - buf_value = _gettmarg(space, w_tup) - + # Checks added to make sure strftime() does not crash Python by # indexing blindly into some array for a textual representation # by some bad index (fixes bug #897625). # No check for year since handled in gettmarg(). - if buf_value.tm_mon < 0 or buf_value.tm_mon > 11: + if buf_value.c_tm_mon < 0 or buf_value.c_tm_mon > 11: raise OperationError(space.w_ValueError, - space.wrap("month out of range")) - if buf_value.tm_mday < 1 or buf_value.tm_mday > 31: + space.wrap("month out of range")) + if buf_value.c_tm_mday < 1 or buf_value.c_tm_mday > 31: raise OperationError(space.w_ValueError, - space.wrap("day of month out of range")) - if buf_value.tm_hour < 0 or buf_value.tm_hour > 23: + space.wrap("day of month out of range")) + if buf_value.c_tm_hour < 0 or buf_value.c_tm_hour > 23: raise OperationError(space.w_ValueError, - space.wrap("hour out of range")) - if buf_value.tm_min < 0 or buf_value.tm_min > 59: + space.wrap("hour out of range")) + if buf_value.c_tm_min < 0 or buf_value.c_tm_min > 59: raise OperationError(space.w_ValueError, - space.wrap("minute out of range")) - if buf_value.tm_sec < 0 or buf_value.tm_sec > 61: + space.wrap("minute out of range")) + if buf_value.c_tm_sec < 0 or buf_value.c_tm_sec > 61: raise OperationError(space.w_ValueError, - space.wrap("seconds out of range")) - if buf_value.tm_yday < 0 or buf_value.tm_yday > 365: + space.wrap("seconds out of range")) + if buf_value.c_tm_yday < 0 or buf_value.c_tm_yday > 365: raise OperationError(space.w_ValueError, - space.wrap("day of year out of range")) - if buf_value.tm_isdst < -1 or buf_value.tm_isdst > 1: + space.wrap("day of year out of range")) + if buf_value.c_tm_isdst < -1 or buf_value.c_tm_isdst > 1: raise OperationError(space.w_ValueError, - space.wrap("daylight savings flag out of range")) + space.wrap("daylight savings flag out of range")) i = 1024 while True: - outbuf = create_string_buffer(i) - buflen = libc.strftime(outbuf, i, format, byref(buf_value)) - + outbuf = lltype.malloc(rffi.CCHARP.TO, i + 1, flavor='raw') + buflen = c_strftime(outbuf, i, format, buf_value) + if buflen > 0 or i >= 256 * len(format): # if the buffer is 256 times as long as the format, # it's probably not failing for lack of room! @@ -482,7 +432,10 @@ # e.g. an empty format, or %Z when the timezone # is unknown. if buflen < 0: buflen = 0 # should not occur - return space.wrap(outbuf.value[:buflen]) + outbuf[buflen] = '\x00' + result = rffi.charp2str(outbuf) + lltype.free(outbuf, flavor='raw') + return space.wrap(result) i += i strftime.unwrap_spec = [ObjSpace, str, W_Root] Modified: pypy/dist/pypy/module/rctime/test/test_rctime.py ============================================================================== --- pypy/dist/pypy/module/rctime/test/test_rctime.py (original) +++ pypy/dist/pypy/module/rctime/test/test_rctime.py Mon Oct 1 08:57:49 2007 @@ -198,7 +198,7 @@ elif os.environ.has_key('TZ'): del os.environ['TZ'] rctime.tzset() - + def test_strftime(self): import time as rctime From fijal at codespeak.net Mon Oct 1 09:09:01 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 1 Oct 2007 09:09:01 +0200 (CEST) Subject: [pypy-svn] r47056 - pypy/dist/pypy/module/rctime Message-ID: <20071001070901.23E0C8125@code0.codespeak.net> Author: fijal Date: Mon Oct 1 09:08:59 2007 New Revision: 47056 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: Fix translation (thanks checkmodule) Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Mon Oct 1 09:08:59 2007 @@ -119,31 +119,31 @@ t_ref[0] = t p = c_localtime(t_ref) janzone = -p.c_tm_gmtoff - janname = [" ", p.c_tm_zone][bool(p.c_tm_zone)] + tm_zone = rffi.charp2str(p.c_tm_zone) + janname = [" ", tm_zone][bool(tm_zone)] tt = t + YEAR / 2 t_ref[0] = tt p = c_localtime(t_ref) lltype.free(t_ref, flavor='raw') julyzone = -p.c_tm_gmtoff - julyname = [" ", p.c_tm_zone][bool(p.c_tm_zone)] + julyname = [" ", tm_zone][bool(tm_zone)] if janzone < julyzone: # DST is reversed in the southern hemisphere timezone = julyzone altzone = janzone daylight = int(janzone != julyzone) - tzname = (julyname, janname) + tzname = [julyname, janname] else: timezone = janzone altzone = julyzone daylight = int(janzone != julyzone) - tzname = (janname, julyname) - start, end = tzname + tzname = [janname, julyname] - return timezone, daylight, [rffi.charp2str(start), rffi.charp2str(end)], altzone + return timezone, daylight, tzname, altzone def _get_error_msg(): - errno = rff.get_errno() + errno = rffi.get_errno() return os.strerror(errno) def sleep(secs): From fijal at codespeak.net Mon Oct 1 09:17:12 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 1 Oct 2007 09:17:12 +0200 (CEST) Subject: [pypy-svn] r47057 - pypy/dist/pypy/rpython/module Message-ID: <20071001071712.A98498129@code0.codespeak.net> Author: fijal Date: Mon Oct 1 09:17:12 2007 New Revision: 47057 Modified: pypy/dist/pypy/rpython/module/ll_time.py Log: add threadsafe=False flag to most of the low level time interface Modified: pypy/dist/pypy/rpython/module/ll_time.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_time.py (original) +++ pypy/dist/pypy/rpython/module/ll_time.py Mon Oct 1 09:17:12 2007 @@ -56,11 +56,11 @@ if self.GETTIMEOFDAY_NO_TZ: c_gettimeofday = self.llexternal('gettimeofday', [self.TIMEVALP], rffi.INT, - _nowrapper=True) + _nowrapper=True, threadsafe=False) else: c_gettimeofday = self.llexternal('gettimeofday', [self.TIMEVALP, rffi.VOIDP], rffi.INT, - _nowrapper=True) + _nowrapper=True, threadsafe=False) else: c_gettimeofday = None @@ -68,12 +68,12 @@ self.configure(CConfigForFTime) c_ftime = self.llexternal('ftime', [lltype.Ptr(self.TIMEB)], lltype.Void, - _nowrapper=True) + _nowrapper=True, threadsafe=False) else: c_ftime = None # to not confuse the flow space c_time = self.llexternal('time', [rffi.VOIDP], self.TIME_T, - _nowrapper=True) + _nowrapper=True, threadsafe=False) def time_time_llimpl(): void = lltype.nullptr(rffi.VOIDP.TO) @@ -105,14 +105,17 @@ @registering(time.clock) def register_time_clock(self): - c_clock = self.llexternal('clock', [], self.CLOCK_T) + c_clock = self.llexternal('clock', [], self.CLOCK_T, + threadsafe=False) if sys.platform == 'win32': # hacking to avoid LARGE_INTEGER which is a union... A = lltype.FixedSizeArray(lltype.SignedLongLong, 1) QueryPerformanceCounter = self.llexternal( - 'QueryPerformanceCounter', [lltype.Ptr(A)], lltype.Void) + 'QueryPerformanceCounter', [lltype.Ptr(A)], lltype.Void, + threadsafe=False) QueryPerformanceFrequency = self.llexternal( - 'QueryPerformanceFrequency', [lltype.Ptr(A)], rffi.INT) + 'QueryPerformanceFrequency', [lltype.Ptr(A)], rffi.INT, + threadsafe=False) class State(object): pass state = State() From fijal at codespeak.net Mon Oct 1 09:18:17 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 1 Oct 2007 09:18:17 +0200 (CEST) Subject: [pypy-svn] r47058 - pypy/dist/pypy/module/rctime Message-ID: <20071001071817.86AB18129@code0.codespeak.net> Author: fijal Date: Mon Oct 1 09:18:17 2007 New Revision: 47058 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: all externals defined here are not thread safe (sleep is defined somewhere else) Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Mon Oct 1 09:18:17 2007 @@ -48,7 +48,8 @@ def external(name, args, result): return rffi.llexternal(name, args, result, - includes=_includes, calling_conv=calling_conv) + includes=_includes, calling_conv=calling_conv, + threadsafe=False) if _POSIX: cConfig.timeval.__name__ = "_timeval" From cfbolz at codespeak.net Mon Oct 1 09:52:04 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 1 Oct 2007 09:52:04 +0200 (CEST) Subject: [pypy-svn] r47059 - pypy/dist/pypy/module/crypt Message-ID: <20071001075204.EC6798120@code0.codespeak.net> Author: cfbolz Date: Mon Oct 1 09:52:04 2007 New Revision: 47059 Modified: pypy/dist/pypy/module/crypt/interp_crypt.py Log: make crypt use rffi instead of rctypes. test on darwin still msissing. Modified: pypy/dist/pypy/module/crypt/interp_crypt.py ============================================================================== --- pypy/dist/pypy/module/crypt/interp_crypt.py (original) +++ pypy/dist/pypy/module/crypt/interp_crypt.py Mon Oct 1 09:52:04 2007 @@ -1,26 +1,19 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import ObjSpace, W_Root from pypy.rpython.rctypes.tool import ctypes_platform -from pypy.rpython.rctypes.tool.util import find_library, load_library +from pypy.rpython.tool import rffi_platform as platform +from pypy.rpython.rctypes.tool.util import find_library +from pypy.rpython.lltypesystem import rffi, lltype import sys -from ctypes import * -class CConfig: - _includes_ = ('unistd.h',) - if sys.platform != 'darwin': - cryptlib = ctypes_platform.Library('crypt') +#if sys.platform == 'darwin': +# dllname = find_library('c') +# assert dllname is not None +# cryptlib = cdll.LoadLibrary(dllname) -globals().update(ctypes_platform.configure(CConfig)) - -if sys.platform == 'darwin': - dllname = find_library('c') - assert dllname is not None - cryptlib = cdll.LoadLibrary(dllname) - -c_crypt = cryptlib.crypt -c_crypt.argtypes = [c_char_p, c_char_p] -c_crypt.restype = c_char_p +c_crypt = rffi.llexternal('crypt', [rffi.CCHARP, rffi.CCHARP], rffi.CCHARP, + libraries=["crypt"]) def crypt(space, word, salt): """word will usually be a user's password. salt is a 2-character string @@ -29,6 +22,9 @@ the hashed password as a string, which will be composed of characters from the same alphabet as the salt.""" res = c_crypt(word, salt) - return space.wrap(res) + if not res: + return space.w_None + str_res = rffi.charp2str(res) + return space.wrap(str_res) crypt.unwrap_spec = [ObjSpace, str, str] From cfbolz at codespeak.net Mon Oct 1 10:13:28 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 1 Oct 2007 10:13:28 +0200 (CEST) Subject: [pypy-svn] r47060 - pypy/dist/pypy/module/crypt Message-ID: <20071001081328.51D7F8124@code0.codespeak.net> Author: cfbolz Date: Mon Oct 1 10:13:27 2007 New Revision: 47060 Modified: pypy/dist/pypy/module/crypt/interp_crypt.py Log: it seems crypt is not threadsafe (if I interpret yesterdays IRC discussions right) Modified: pypy/dist/pypy/module/crypt/interp_crypt.py ============================================================================== --- pypy/dist/pypy/module/crypt/interp_crypt.py (original) +++ pypy/dist/pypy/module/crypt/interp_crypt.py Mon Oct 1 10:13:27 2007 @@ -13,7 +13,7 @@ # cryptlib = cdll.LoadLibrary(dllname) c_crypt = rffi.llexternal('crypt', [rffi.CCHARP, rffi.CCHARP], rffi.CCHARP, - libraries=["crypt"]) + libraries=["crypt"], threadsafe=False) def crypt(space, word, salt): """word will usually be a user's password. salt is a 2-character string From fijal at codespeak.net Mon Oct 1 10:41:44 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 1 Oct 2007 10:41:44 +0200 (CEST) Subject: [pypy-svn] r47061 - pypy/dist/pypy/module/rctime Message-ID: <20071001084144.E545780F8@code0.codespeak.net> Author: fijal Date: Mon Oct 1 10:41:44 2007 New Revision: 47061 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: Make annotator happier Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Mon Oct 1 10:41:44 2007 @@ -218,7 +218,10 @@ glob_buf.c_tm_wday = space.int_w(tup_w[6]) glob_buf.c_tm_yday = space.int_w(tup_w[7]) glob_buf.c_tm_isdst = space.int_w(tup_w[8]) - glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) + if _POSIX: + # actually never happens, but makes annotator happy + glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) + glob_buf.c_tm_gmtoff = 0 w_accept2dyear = _get_module_object(space, "accept2dyear") accept2dyear = space.int_w(w_accept2dyear) From antocuni at codespeak.net Mon Oct 1 10:48:19 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 1 Oct 2007 10:48:19 +0200 (CEST) Subject: [pypy-svn] r47062 - pypy/dist/pypy/module/rbench Message-ID: <20071001084819.E55D180F8@code0.codespeak.net> Author: antocuni Date: Mon Oct 1 10:48:19 2007 New Revision: 47062 Added: pypy/dist/pypy/module/rbench/ pypy/dist/pypy/module/rbench/__init__.py (contents, props changed) pypy/dist/pypy/module/rbench/app_bench.py (contents, props changed) Log: this module contains geninterpreted version of pystone and richards. Useful to measure the interpretation overhead of the various pypy-*. Added: pypy/dist/pypy/module/rbench/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/rbench/__init__.py Mon Oct 1 10:48:19 2007 @@ -0,0 +1,12 @@ +# Package initialisation +from pypy.interpreter.mixedmodule import MixedModule + +class Module(MixedModule): + """geninterpreted benchmarks""" + + appleveldefs = { + 'pystone': 'app_bench.pystone', + 'richards': 'app_bench.richards', + } + + interpleveldefs = {} Added: pypy/dist/pypy/module/rbench/app_bench.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/rbench/app_bench.py Mon Oct 1 10:48:19 2007 @@ -0,0 +1,2 @@ +from pypy.translator.test.rpystone import main as pystone +from pypy.translator.goal.richards import main as richards From fijal at codespeak.net Mon Oct 1 10:53:54 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 1 Oct 2007 10:53:54 +0200 (CEST) Subject: [pypy-svn] r47063 - pypy/dist/pypy/config Message-ID: <20071001085354.8EA7380FE@code0.codespeak.net> Author: fijal Date: Mon Oct 1 10:53:54 2007 New Revision: 47063 Modified: pypy/dist/pypy/config/pypyoption.py Log: Enable tproxy by default Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon Oct 1 10:53:54 2007 @@ -115,7 +115,7 @@ OptionDescription("std", "Standard Object Space Options", [ BoolOption("withtproxy", "support transparent proxies", - default=False), + default=True), BoolOption("withsmallint", "use tagged integers", default=False, From cfbolz at codespeak.net Mon Oct 1 10:56:47 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 1 Oct 2007 10:56:47 +0200 (CEST) Subject: [pypy-svn] r47064 - pypy/dist/pypy/doc Message-ID: <20071001085647.6673B80FE@code0.codespeak.net> Author: cfbolz Date: Mon Oct 1 10:56:47 2007 New Revision: 47064 Modified: pypy/dist/pypy/doc/cleanup-todo.txt Log: crypt uses rffi now Modified: pypy/dist/pypy/doc/cleanup-todo.txt ============================================================================== --- pypy/dist/pypy/doc/cleanup-todo.txt (original) +++ pypy/dist/pypy/doc/cleanup-todo.txt Mon Oct 1 10:56:47 2007 @@ -34,7 +34,6 @@ - rewrite the following rctypes modules using rffi: - bz2 - - crypt - _demo - _ssl - fcntl From cfbolz at codespeak.net Mon Oct 1 11:13:12 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 1 Oct 2007 11:13:12 +0200 (CEST) Subject: [pypy-svn] r47065 - pypy/dist/pypy/doc Message-ID: <20071001091312.CFB458124@code0.codespeak.net> Author: cfbolz Date: Mon Oct 1 11:13:10 2007 New Revision: 47065 Modified: pypy/dist/pypy/doc/cleanup-todo.txt Log: make valid rest Modified: pypy/dist/pypy/doc/cleanup-todo.txt ============================================================================== --- pypy/dist/pypy/doc/cleanup-todo.txt (original) +++ pypy/dist/pypy/doc/cleanup-todo.txt Mon Oct 1 11:13:10 2007 @@ -33,6 +33,7 @@ critical - rewrite the following rctypes modules using rffi: + - bz2 - _demo - _ssl From antocuni at codespeak.net Mon Oct 1 11:22:52 2007 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 1 Oct 2007 11:22:52 +0200 (CEST) Subject: [pypy-svn] r47066 - pypy/dist/pypy/doc/config Message-ID: <20071001092252.414AC812A@code0.codespeak.net> Author: antocuni Date: Mon Oct 1 11:22:51 2007 New Revision: 47066 Added: pypy/dist/pypy/doc/config/objspace.usemodules.rbench.txt (contents, props changed) Log: doc for rbench Added: pypy/dist/pypy/doc/config/objspace.usemodules.rbench.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/config/objspace.usemodules.rbench.txt Mon Oct 1 11:22:51 2007 @@ -0,0 +1,4 @@ +Use the built-in 'rbench' module. +This module contains geninterpreted versions of pystone and richards, +so it is useful to measure the interpretation overhead of the various +pypy-*. From fijal at codespeak.net Mon Oct 1 11:53:51 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 1 Oct 2007 11:53:51 +0200 (CEST) Subject: [pypy-svn] r47068 - pypy/dist/pypy/module/rctime Message-ID: <20071001095351.265A08131@code0.codespeak.net> Author: fijal Date: Mon Oct 1 11:53:50 2007 New Revision: 47068 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: typo. Windows machine needed! Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Mon Oct 1 11:53:50 2007 @@ -35,7 +35,7 @@ ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT), ("tm_gmtoff", rffi.LONG), ("tm_zone", rffi.CCHARP)]) elif _WIN: - calling_conf = 'win' + calling_conv = 'win' CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), From arigo at codespeak.net Mon Oct 1 13:37:41 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 1 Oct 2007 13:37:41 +0200 (CEST) Subject: [pypy-svn] r47070 - pypy/dist/pypy/module/rctime Message-ID: <20071001113741.84959810F@code0.codespeak.net> Author: arigo Date: Mon Oct 1 13:37:40 2007 New Revision: 47070 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: genc doesn't like the uninitialized content of this global structure. For now let's simply initialize it with zeroes. Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Mon Oct 1 13:37:40 2007 @@ -60,7 +60,7 @@ time_t = cConfig.time_t size_t = cConfig.size_t tm = cConfig.tm -glob_buf = lltype.malloc(tm, flavor='raw') +glob_buf = lltype.malloc(tm, flavor='raw', zero=True) if cConfig.has_gettimeofday: c_gettimeofday = external('gettimeofday', [rffi.VOIDP, rffi.VOIDP], rffi.INT) From fijal at codespeak.net Mon Oct 1 13:55:20 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 1 Oct 2007 13:55:20 +0200 (CEST) Subject: [pypy-svn] r47071 - pypy/dist/pypy/module/rctime Message-ID: <20071001115520.2ED2D810F@code0.codespeak.net> Author: fijal Date: Mon Oct 1 13:55:19 2007 New Revision: 47071 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: kill XXX. sleep is implemented on rpython-level by now Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Mon Oct 1 13:55:19 2007 @@ -75,18 +75,6 @@ c_localtime = external('localtime', [TIME_TP], TM_P) if _POSIX: c_tzset = external('tzset', [], lltype.Void) -elif _WIN: - XXX - #c_QueryPerformanceCounter = external( - #QueryPerformanceCounter = windll.kernel32.QueryPerformanceCounter - #QueryPerformanceCounter.argtypes = [POINTER(LARGE_INTEGER)] - #QueryPerformanceCounter.restype = BOOL - #QueryPerformanceFrequency = windll.kernel32.QueryPerformanceFrequency - #QueryPerformanceFrequency.argtypes = [POINTER(LARGE_INTEGER)] - #QueryPerformanceFrequency.restype = BOOL - #Sleep = windll.kernel32.Sleep - #Sleep.argtypes = [DWORD] - #Sleep.restype = None c_strftime = external('strftime', [rffi.CCHARP, size_t, rffi.CCHARP, TM_P], size_t) From fijal at codespeak.net Mon Oct 1 14:02:04 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 1 Oct 2007 14:02:04 +0200 (CEST) Subject: [pypy-svn] r47072 - pypy/dist/pypy/module/rctime Message-ID: <20071001120204.959A08119@code0.codespeak.net> Author: fijal Date: Mon Oct 1 14:02:04 2007 New Revision: 47072 Modified: pypy/dist/pypy/module/rctime/interp_time.py Log: uh. fix for stupid bug. Modified: pypy/dist/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/interp_time.py (original) +++ pypy/dist/pypy/module/rctime/interp_time.py Mon Oct 1 14:02:04 2007 @@ -114,6 +114,7 @@ t_ref[0] = tt p = c_localtime(t_ref) lltype.free(t_ref, flavor='raw') + tm_zone = rffi.charp2str(p.c_tm_zone) julyzone = -p.c_tm_gmtoff julyname = [" ", tm_zone][bool(tm_zone)] From arigo at codespeak.net Mon Oct 1 19:35:50 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 1 Oct 2007 19:35:50 +0200 (CEST) Subject: [pypy-svn] r47077 - pypy/dist/pypy/translator/js/examples/bnb Message-ID: <20071001173550.9130580FA@code0.codespeak.net> Author: arigo Date: Mon Oct 1 19:35:48 2007 New Revision: 47077 Modified: pypy/dist/pypy/translator/js/examples/bnb/bnb.py Log: Compute the port lazily as a quick workaround for the fact that this logic hangs forever if there is a non-responsive process listening on localhost:8000. Mostly untested, sorry if I break something. Modified: pypy/dist/pypy/translator/js/examples/bnb/bnb.py ============================================================================== --- pypy/dist/pypy/translator/js/examples/bnb/bnb.py (original) +++ pypy/dist/pypy/translator/js/examples/bnb/bnb.py Mon Oct 1 19:35:48 2007 @@ -70,15 +70,22 @@ _spriteManagers = {} host = 'localhost' - try: - port = re.findall('value=".*"', urllib.urlopen('http://%s:8000' % host).read())[0] - port = int(port[7:-1]) - except IOError: - log("ERROR: Can't connect to BnB server on %s:8000" % host) -# sys.exit() - except IndexError: - log("ERROR: Connected to BnB server but unable to detect a running game") -# sys.exit() + + def getport(self): + if hasattr(self, '_port'): + return self._port + try: + port = re.findall('value=".*"', urllib.urlopen('http://%s:8000' % host).read())[0] + port = int(port[7:-1]) + except IOError: + log("ERROR: Can't connect to BnB server on %s:8000" % host) + raise IOError + except IndexError: + log("ERROR: Connected to BnB server but unable to detect a running game") + raise IOError + self._port = port + return port + port = property(getport) #def _close(self, sessionid): # if sessionid in self._serverMessage: From pypy-svn at codespeak.net Mon Oct 1 21:15:28 2007 From: pypy-svn at codespeak.net (VIAGRA ® Official Site) Date: Mon, 1 Oct 2007 21:15:28 +0200 (CEST) Subject: [pypy-svn] October 71% OFF Message-ID: <20071001121712.39073.qmail@dsl.static8510550159.ttnet.net.tr> An HTML attachment was scrubbed... URL: http://codespeak.net/pipermail/pypy-svn/attachments/20071001/dced2316/attachment.htm From fijal at codespeak.net Tue Oct 2 08:59:34 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 2 Oct 2007 08:59:34 +0200 (CEST) Subject: [pypy-svn] r47080 - pypy/dist/demo/distribution Message-ID: <20071002065934.547C8813D@code0.codespeak.net> Author: fijal Date: Tue Oct 2 08:59:33 2007 New Revision: 47080 Added: pypy/dist/demo/distribution/ Log: Add a directory for distribution demos From fijal at codespeak.net Tue Oct 2 08:59:55 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 2 Oct 2007 08:59:55 +0200 (CEST) Subject: [pypy-svn] r47081 - in pypy/dist/demo: . tproxy Message-ID: <20071002065955.45CBE8140@code0.codespeak.net> Author: fijal Date: Tue Oct 2 08:59:54 2007 New Revision: 47081 Added: pypy/dist/demo/tproxy/ pypy/dist/demo/tproxy/persistance.py - copied unchanged from r47079, pypy/dist/demo/tp-persistence.py pypy/dist/demo/tproxy/print_operations.py - copied unchanged from r47079, pypy/dist/demo/tp-print-builtin-operation.py Removed: pypy/dist/demo/tp-persistence.py pypy/dist/demo/tp-print-builtin-operation.py Log: Move tproxy demos to it's own directory From arigo at codespeak.net Tue Oct 2 10:30:09 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 Oct 2007 10:30:09 +0200 (CEST) Subject: [pypy-svn] r47082 - pypy/dist/pypy/module/rctime/test Message-ID: <20071002083009.A523D813D@code0.codespeak.net> Author: arigo Date: Tue Oct 2 10:30:08 2007 New Revision: 47082 Modified: pypy/dist/pypy/module/rctime/test/test_rctime.py Log: A print to show progress when running with -s. I thought the test was hanging. Modified: pypy/dist/pypy/module/rctime/test/test_rctime.py ============================================================================== --- pypy/dist/pypy/module/rctime/test/test_rctime.py (original) +++ pypy/dist/pypy/module/rctime/test/test_rctime.py Tue Oct 2 10:30:08 2007 @@ -263,6 +263,7 @@ 'j', 'm', 'M', 'p', 'S', 'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'): format = ' %' + directive + print format rctime.strptime(rctime.strftime(format, tt), format) def test_pickle(self): From arigo at codespeak.net Tue Oct 2 10:30:25 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 Oct 2007 10:30:25 +0200 (CEST) Subject: [pypy-svn] r47083 - pypy/dist/pypy/module/crypt Message-ID: <20071002083025.BBDBA813D@code0.codespeak.net> Author: arigo Date: Tue Oct 2 10:30:25 2007 New Revision: 47083 Modified: pypy/dist/pypy/module/crypt/__init__.py pypy/dist/pypy/module/crypt/interp_crypt.py Log: Kill dead imports. Modified: pypy/dist/pypy/module/crypt/__init__.py ============================================================================== --- pypy/dist/pypy/module/crypt/__init__.py (original) +++ pypy/dist/pypy/module/crypt/__init__.py Tue Oct 2 10:30:25 2007 @@ -1,7 +1,7 @@ from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): - """A demo built-in module based on ctypes.""" + """A demo built-in module based on rffi.""" interpleveldefs = { 'crypt' : 'interp_crypt.crypt', Modified: pypy/dist/pypy/module/crypt/interp_crypt.py ============================================================================== --- pypy/dist/pypy/module/crypt/interp_crypt.py (original) +++ pypy/dist/pypy/module/crypt/interp_crypt.py Tue Oct 2 10:30:25 2007 @@ -1,16 +1,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import ObjSpace, W_Root -from pypy.rpython.rctypes.tool import ctypes_platform -from pypy.rpython.tool import rffi_platform as platform -from pypy.rpython.rctypes.tool.util import find_library from pypy.rpython.lltypesystem import rffi, lltype -import sys - -#if sys.platform == 'darwin': -# dllname = find_library('c') -# assert dllname is not None -# cryptlib = cdll.LoadLibrary(dllname) c_crypt = rffi.llexternal('crypt', [rffi.CCHARP, rffi.CCHARP], rffi.CCHARP, libraries=["crypt"], threadsafe=False) From arigo at codespeak.net Tue Oct 2 10:31:00 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 Oct 2007 10:31:00 +0200 (CEST) Subject: [pypy-svn] r47084 - in pypy/dist/pypy: module/zlib module/zlib/test rlib rlib/test Message-ID: <20071002083100.24A66813D@code0.codespeak.net> Author: arigo Date: Tue Oct 2 10:30:59 2007 New Revision: 47084 Modified: pypy/dist/pypy/module/zlib/interp_zlib.py pypy/dist/pypy/module/zlib/test/test_zlib.py pypy/dist/pypy/rlib/rzlib.py pypy/dist/pypy/rlib/test/test_rzlib.py Log: This mostly finishes the zlib module. Modified: pypy/dist/pypy/module/zlib/interp_zlib.py ============================================================================== --- pypy/dist/pypy/module/zlib/interp_zlib.py (original) +++ pypy/dist/pypy/module/zlib/interp_zlib.py Tue Oct 2 10:30:59 2007 @@ -1,6 +1,7 @@ +import sys from pypy.interpreter.gateway import ObjSpace, W_Root, interp2app from pypy.interpreter.baseobjspace import Wrappable -from pypy.interpreter.typedef import TypeDef +from pypy.interpreter.typedef import TypeDef, interp_attrproperty from pypy.interpreter.error import OperationError from pypy.rlib.rarithmetic import intmask @@ -61,8 +62,7 @@ try: stream = rzlib.deflateInit(level) except ValueError: - raise OperationError(space.w_ValueError, - space.wrap("Invalid initialization option")) + raise zlib_error(space, "Bad compression level") try: result = rzlib.compress(stream, string, rzlib.Z_FINISH) finally: @@ -78,16 +78,15 @@ decompress(string[, wbits[, bufsize]]) -- Return decompressed string. Optional arg wbits is the window buffer size. Optional arg bufsize is - the initial output buffer size. + only for compatibility with CPython and is ignored. """ try: try: stream = rzlib.inflateInit(wbits) except ValueError: - raise OperationError(space.w_ValueError, - space.wrap("Invalid initialization option")) + raise zlib_error(space, "Bad window buffer size") try: - result = rzlib.decompress(stream, string, rzlib.Z_FINISH) + result, _, _ = rzlib.decompress(stream, string, rzlib.Z_FINISH) finally: rzlib.inflateEnd(stream) except rzlib.RZlibError, e: @@ -114,6 +113,7 @@ except ValueError: raise OperationError(space.w_ValueError, space.wrap("Invalid initialization option")) + self.lock = space.allocate_lock() def __del__(self): """Automatically free the resources used by the stream.""" @@ -132,7 +132,12 @@ Call the flush() method to clear these buffers. """ try: - result = rzlib.compress(self.stream, data) + lock = self.lock + lock.acquire(True) + try: + result = rzlib.compress(self.stream, data) + finally: + lock.release() except rzlib.RZlibError, e: raise zlib_error(self.space, e.msg) return self.space.wrap(result) @@ -152,7 +157,12 @@ compressed. """ try: - result = rzlib.compress(self.stream, '', mode) + lock = self.lock + lock.acquire(True) + try: + result = rzlib.compress(self.stream, '', mode) + finally: + lock.release() except rzlib.RZlibError, e: raise zlib_error(self.space, e.msg) return self.space.wrap(result) @@ -198,6 +208,8 @@ inflateInit2. """ self.space = space + self.unused_data = '' + self.unconsumed_tail = '' try: self.stream = rzlib.inflateInit(wbits) except rzlib.RZlibError, e: @@ -205,6 +217,7 @@ except ValueError: raise OperationError(space.w_ValueError, space.wrap("Invalid initialization option")) + self.lock = space.allocate_lock() def __del__(self): """Automatically free the resources used by the stream.""" @@ -222,14 +235,33 @@ no longer than max_length. Unconsumed input data will be stored in the unconsumed_tail attribute. """ - if max_length != 0: # XXX - raise OperationError(self.space.w_NotImplementedError, - self.space.wrap("max_length != 0")) + if max_length == 0: + max_length = sys.maxint + elif max_length < 0: + raise OperationError(self.space.w_ValueError, + self.space.wrap("max_length must be " + "greater than zero")) try: - result = rzlib.decompress(self.stream, data) + lock = self.lock + lock.acquire(True) + try: + result = rzlib.decompress(self.stream, data, + max_length = max_length) + finally: + lock.release() except rzlib.RZlibError, e: raise zlib_error(self.space, e.msg) - return self.space.wrap(result) + + string, finished, unused_len = result + unused_start = len(data) - unused_len + assert unused_start >= 0 + tail = data[unused_start:] + if finished: + self.unconsumed_tail = '' + self.unused_data = tail + else: + self.unconsumed_tail = tail + return self.space.wrap(string) decompress.unwrap_spec = ['self', str, int] @@ -264,6 +296,8 @@ __new__ = interp2app(Decompress___new__), decompress = interp2app(Decompress.decompress), flush = interp2app(Decompress.flush), + unused_data = interp_attrproperty('unused_data', Decompress), + unconsumed_tail = interp_attrproperty('unconsumed_tail', Decompress), __doc__ = """decompressobj([wbits]) -- Return a decompressor object. Optional arg wbits is the window buffer size. Modified: pypy/dist/pypy/module/zlib/test/test_zlib.py ============================================================================== --- pypy/dist/pypy/module/zlib/test/test_zlib.py (original) +++ pypy/dist/pypy/module/zlib/test/test_zlib.py Tue Oct 2 10:30:59 2007 @@ -133,5 +133,45 @@ def test_decompress_invalid_input(self): + """ + Try to feed garbage to zlib.decompress(). + """ raises(self.zlib.error, self.zlib.decompress, self.compressed[:-2]) raises(self.zlib.error, self.zlib.decompress, 'foobar') + + + def test_unused_data(self): + """ + Try to feed too much data to zlib.decompress(). + It should show up in the unused_data attribute. + """ + d = self.zlib.decompressobj() + s = d.decompress(self.compressed + 'extrastuff') + assert s == self.expanded + assert d.unused_data == 'extrastuff' + # try again with several decompression steps + d = self.zlib.decompressobj() + s1 = d.decompress(self.compressed[:10]) + assert d.unused_data == '' + s2 = d.decompress(self.compressed[10:-3]) + assert d.unused_data == '' + s3 = d.decompress(self.compressed[-3:] + 'spam' * 100) + assert d.unused_data == 'spam' * 100 + assert s1 + s2 + s3 == self.expanded + s4 = d.decompress('egg' * 50) + assert d.unused_data == 'egg' * 50 + assert s4 == '' + + + def test_max_length(self): + """ + Test the max_length argument of the decompress() method + and the corresponding unconsumed_tail attribute. + """ + d = self.zlib.decompressobj() + data = self.compressed + for i in range(0, 100, 10): + s1 = d.decompress(data, 10) + assert s1 == self.expanded[i:i+10] + data = d.unconsumed_tail + assert not data Modified: pypy/dist/pypy/rlib/rzlib.py ============================================================================== --- pypy/dist/pypy/rlib/rzlib.py (original) +++ pypy/dist/pypy/rlib/rzlib.py Tue Oct 2 10:30:59 2007 @@ -1,3 +1,4 @@ +import sys from pypy.rpython.lltypesystem import rffi, lltype from pypy.rpython.tool import rffi_platform @@ -263,15 +264,24 @@ """ # Warning, reentrant calls to the zlib with a given stream can cause it # to crash. The caller of pypy.rlib.rzlib should use locks if needed. - return _operate(stream, data, flush, False, _deflate, "while compressing") - - -def decompress(stream, data, flush=Z_SYNC_FLUSH): - """ - Feed more data into an inflate stream. Returns a string containing - (a part of) the decompressed data. If flush != Z_NO_FLUSH, this also - flushes the output data; see zlib.h or the documentation of the - zlib module for the possible values of 'flush'. + data, _, avail_in = _operate(stream, data, flush, sys.maxint, _deflate, + "while compressing") + assert not avail_in, "not all input consumed by deflate" + return data + + +def decompress(stream, data, flush=Z_SYNC_FLUSH, max_length=sys.maxint): + """ + Feed more data into an inflate stream. Returns a tuple (string, + finished, unused_data_length). The string contains (a part of) the + decompressed data. If flush != Z_NO_FLUSH, this also flushes the + output data; see zlib.h or the documentation of the zlib module for + the possible values of 'flush'. + + The 'string' is never longer than 'max_length'. The + 'unused_data_length' is the number of unprocessed input characters, + either because they are after the end of the compressed stream or + because processing it would cause the 'max_length' to be exceeded. """ # Warning, reentrant calls to the zlib with a given stream can cause it # to crash. The caller of pypy.rlib.rzlib should use locks if needed. @@ -284,11 +294,18 @@ should_finish = True else: should_finish = False - return _operate(stream, data, flush, should_finish, _inflate, - "while decompressing") + result = _operate(stream, data, flush, max_length, _inflate, + "while decompressing") + if should_finish: + # detect incomplete input in the Z_FINISHED case + finished = result[1] + if not finished: + raise RZlibError("the input compressed stream of data is " + "incomplete") + return result -def _operate(stream, data, flush, should_finish, cfunc, while_doing): +def _operate(stream, data, flush, max_length, cfunc, while_doing): """Common code for compress() and decompress(). """ # Prepare the input buffer for the stream @@ -312,12 +329,19 @@ while True: stream.c_next_out = rffi.cast(Bytefp, outbuf) - rffi.setintfield(stream, 'c_avail_out', OUTPUT_BUFFER_SIZE) + bufsize = OUTPUT_BUFFER_SIZE + if max_length < bufsize: + if max_length <= 0: + err = Z_OK + break + bufsize = max_length + max_length -= bufsize + rffi.setintfield(stream, 'c_avail_out', bufsize) err = cfunc(stream, flush) if err == Z_OK or err == Z_STREAM_END: # accumulate data into 'result' avail_out = rffi.cast(lltype.Signed, stream.c_avail_out) - for i in xrange(OUTPUT_BUFFER_SIZE - avail_out): + for i in xrange(bufsize - avail_out): result.append(outbuf[i]) # if the output buffer is full, there might be more data # so we need to try again. Otherwise, we're done. @@ -335,7 +359,7 @@ # the output buffer was full but there wasn't more # output when we tried again, so it is not an error # condition. - if avail_out == OUTPUT_BUFFER_SIZE: + if avail_out == bufsize: break # fallback case: report this error @@ -347,10 +371,8 @@ lltype.free(inbuf, flavor='raw') # When decompressing, if the compressed stream of data was truncated, - # then the zlib simply returns Z_OK and waits for more. Let's detect - # this situation and complain. - if should_finish and err != Z_STREAM_END: - raise RZlibError("the input compressed stream of data is not complete") - - assert not stream.c_avail_in, "not all input consumed by deflate/inflate" - return ''.join(result) + # then the zlib simply returns Z_OK and waits for more. If it is + # complete it returns Z_STREAM_END. + return (''.join(result), + err == Z_STREAM_END, + rffi.cast(lltype.Signed, stream.c_avail_in)) Modified: pypy/dist/pypy/rlib/test/test_rzlib.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rzlib.py (original) +++ pypy/dist/pypy/rlib/test/test_rzlib.py Tue Oct 2 10:30:59 2007 @@ -121,10 +121,14 @@ should allow us to decompress bytes. """ stream = rzlib.inflateInit() - bytes = rzlib.decompress(stream, compressed) - bytes += rzlib.decompress(stream, "", rzlib.Z_FINISH) + bytes1, finished1, unused1 = rzlib.decompress(stream, compressed) + bytes2, finished2, unused2 = rzlib.decompress(stream, "", rzlib.Z_FINISH) rzlib.inflateEnd(stream) - assert bytes == expanded + assert bytes1 + bytes2 == expanded + assert finished1 is True + assert finished2 is True + assert unused1 == 0 + assert unused2 == 0 def test_decompression_lots_of_data(): @@ -135,9 +139,12 @@ compressed = zlib.compress(expanded) print len(compressed), '=>', len(expanded) stream = rzlib.inflateInit() - bytes = rzlib.decompress(stream, compressed, rzlib.Z_FINISH) + bytes, finished, unused = rzlib.decompress(stream, compressed, + rzlib.Z_FINISH) rzlib.inflateEnd(stream) assert bytes == expanded + assert finished is True + assert unused == 0 def test_decompression_truncated_input(): @@ -149,11 +156,75 @@ compressed = zlib.compress(expanded) print len(compressed), '=>', len(expanded) stream = rzlib.inflateInit() - data = rzlib.decompress(stream, compressed[:1000]) + data, finished1, unused1 = rzlib.decompress(stream, compressed[:1000]) assert expanded.startswith(data) - data += rzlib.decompress(stream, compressed[1000:2000]) + assert finished1 is False + assert unused1 == 0 + data2, finished2, unused2 = rzlib.decompress(stream, compressed[1000:2000]) + data += data2 + assert finished2 is False + assert unused2 == 0 assert expanded.startswith(data) py.test.raises(rzlib.RZlibError, rzlib.decompress, stream, compressed[2000:-500], rzlib.Z_FINISH) rzlib.inflateEnd(stream) + + +def test_decompression_too_much_input(): + """ + Check the case where we feed extra data to decompress(). + """ + stream = rzlib.inflateInit() + data1, finished1, unused1 = rzlib.decompress(stream, compressed[:-5]) + assert finished1 is False + assert unused1 == 0 + data2, finished2, unused2 = rzlib.decompress(stream, + compressed[-5:] + 'garbage') + assert finished2 is True + assert unused2 == len('garbage') + assert data1 + data2 == expanded + data3, finished3, unused3 = rzlib.decompress(stream, 'more_garbage') + assert finished3 is True + assert unused3 == len('more_garbage') + assert data3 == '' + + +def test_decompress_max_length(): + """ + Test the max_length argument of decompress(). + """ + stream = rzlib.inflateInit() + data1, finished1, unused1 = rzlib.decompress(stream, compressed, + max_length = 17) + assert data1 == expanded[:17] + assert finished1 is False + assert unused1 > 0 + data2, finished2, unused2 = rzlib.decompress(stream, compressed[-unused1:]) + assert data2 == expanded[17:] + assert finished2 is True + assert unused2 == 0 + + +def test_cornercases(): + """ + Test degenerate arguments. + """ + stream = rzlib.deflateInit() + bytes = rzlib.compress(stream, "") + bytes += rzlib.compress(stream, "") + bytes += rzlib.compress(stream, "", rzlib.Z_FINISH) + assert zlib.decompress(bytes) == "" + + stream = rzlib.inflateInit() + data, finished, unused = rzlib.decompress(stream, "") + assert data == "" + assert finished is False + assert unused == 0 + buf = compressed + for i in range(10): + data, finished, unused = rzlib.decompress(stream, buf, max_length=0) + assert data == "" + assert finished is False + assert unused > 0 + buf = buf[-unused:] From fijal at codespeak.net Tue Oct 2 10:31:40 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 2 Oct 2007 10:31:40 +0200 (CEST) Subject: [pypy-svn] r47085 - in pypy/dist: demo/distribution pypy/lib/distributed/demo Message-ID: <20071002083140.3D61E813D@code0.codespeak.net> Author: fijal Date: Tue Oct 2 10:31:39 2007 New Revision: 47085 Added: pypy/dist/demo/distribution/fileclient.py - copied unchanged from r47070, pypy/dist/pypy/lib/distributed/demo/fileclient.py pypy/dist/demo/distribution/fileserver.py - copied unchanged from r47070, pypy/dist/pypy/lib/distributed/demo/fileserver.py Removed: pypy/dist/pypy/lib/distributed/demo/fileclient.py pypy/dist/pypy/lib/distributed/demo/fileserver.py Log: Move distribution demos to it's own directory in demo From arigo at codespeak.net Tue Oct 2 10:36:02 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 Oct 2007 10:36:02 +0200 (CEST) Subject: [pypy-svn] r47086 - in pypy/dist/pypy/translator: cli/test js/test jvm/test Message-ID: <20071002083602.39B73813D@code0.codespeak.net> Author: arigo Date: Tue Oct 2 10:36:01 2007 New Revision: 47086 Modified: pypy/dist/pypy/translator/cli/test/test_float.py pypy/dist/pypy/translator/js/test/test_rfloat.py pypy/dist/pypy/translator/jvm/test/test_float.py Log: Skip the SingleFloat test on non-C backends for now. Modified: pypy/dist/pypy/translator/cli/test/test_float.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_float.py (original) +++ pypy/dist/pypy/translator/cli/test/test_float.py Tue Oct 2 10:36:01 2007 @@ -16,3 +16,6 @@ expected = fn(i) res = self.interpret(fn, [i]) assert res == expected + + def test_r_singlefloat(self): + py.test.skip("not implemented: single-precision floats") Modified: pypy/dist/pypy/translator/js/test/test_rfloat.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_rfloat.py (original) +++ pypy/dist/pypy/translator/js/test/test_rfloat.py Tue Oct 2 10:36:01 2007 @@ -22,3 +22,6 @@ assert x != big y = fn(x) assert fn(x) == 9223372026854775808 + + def test_r_singlefloat(self): + py.test.skip("not implemented: single-precision floats") Modified: pypy/dist/pypy/translator/jvm/test/test_float.py ============================================================================== --- pypy/dist/pypy/translator/jvm/test/test_float.py (original) +++ pypy/dist/pypy/translator/jvm/test/test_float.py Tue Oct 2 10:36:01 2007 @@ -19,3 +19,6 @@ expected = fn(i) res = self.interpret(fn, [i]) assert res == expected + + def test_r_singlefloat(self): + py.test.skip("not implemented: single-precision floats") From arigo at codespeak.net Tue Oct 2 10:57:43 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 Oct 2007 10:57:43 +0200 (CEST) Subject: [pypy-svn] r47087 - pypy/dist/pypy/translator/c Message-ID: <20071002085743.BD3068142@code0.codespeak.net> Author: arigo Date: Tue Oct 2 10:57:43 2007 New Revision: 47087 Modified: pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/support.py Log: Never use 'typedef' in generated C code. Just don't. You work like type macros in that we can always spell out the whole type instead whenever it's used - and they *don't* work like macros in that some C compilers don't like typedefs that involve arrays of not-yet-defined structures so you'd have to carefully order declarations. Don't bother. This fixes test_structarray_nolength which failed on gcc 4 (but not gcc 3). Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Tue Oct 2 10:57:43 2007 @@ -9,10 +9,10 @@ from pypy.translator.c.primitive import PrimitiveName, PrimitiveType from pypy.translator.c.primitive import PrimitiveErrorValue from pypy.translator.c.node import StructDefNode, ArrayDefNode -from pypy.translator.c.node import FixedSizeArrayDefNode +from pypy.translator.c.node import FixedSizeArrayDefNode, BareBoneArrayDefNode from pypy.translator.c.node import ContainerNodeFactory, ExtTypeOpaqueDefNode from pypy.translator.c.support import cdecl, CNameManager, ErrorValue -from pypy.translator.c.support import log +from pypy.translator.c.support import log, barebonearray from pypy.translator.c.extfunc import do_the_getting from pypy import conftest from pypy.translator.c import gc @@ -83,7 +83,10 @@ else: node = StructDefNode(self, T, varlength) elif isinstance(T, Array): - node = ArrayDefNode(self, T, varlength) + if barebonearray(T): + node = BareBoneArrayDefNode(self, T, varlength) + else: + node = ArrayDefNode(self, T, varlength) elif isinstance(T, OpaqueType) and hasattr(T, '_exttypeinfo'): node = ExtTypeOpaqueDefNode(self, T) elif T == WeakRef: Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Tue Oct 2 10:57:43 2007 @@ -214,15 +214,6 @@ self.name) = db.namespace.uniquename(basename, with_number=with_number, bare=True) self.dependencies = {} - # a non-gc array with no length doesn't need a 'struct' wrapper at - # all; rffi kind of expects such arrays to be "bare" C arrays. - self.barebone = barebonearray(ARRAY) - if self.barebone: - self.setup() # to get self.itemtypename - typename = self.itemtypename.replace('@', '(@)[%d]' % ( - self.varlength,)) - self.forward_decl = 'typedef %s;' % (cdecl(typename, self.name),) - self.typetag = '' def setup(self): if hasattr(self, 'itemtypename'): @@ -247,32 +238,22 @@ return '%s %s @' % (self.typetag, self.name) def getptrtype(self): - if self.barebone: - return self.itemtypename.replace('@', '*@') - else: - return '%s %s *@' % (self.typetag, self.name) + return '%s %s *@' % (self.typetag, self.name) def access_expr(self, baseexpr, index): - if self.barebone: - return '%s[%d]' % (baseexpr, index) - else: - return '%s.items[%d]' % (baseexpr, index) + return '%s.items[%d]' % (baseexpr, index) def ptr_access_expr(self, baseexpr, index): assert 0 <= index <= sys.maxint, "invalid constant index %r" % (index,) return self.itemindex_access_expr(baseexpr, index) def itemindex_access_expr(self, baseexpr, indexexpr): - if self.barebone: - return 'RPyBareItem(%s, %s)' % (baseexpr, indexexpr) - elif self.ARRAY._hints.get('nolength', False): + if self.ARRAY._hints.get('nolength', False): return 'RPyNLenItem(%s, %s)' % (baseexpr, indexexpr) else: return 'RPyItem(%s, %s)' % (baseexpr, indexexpr) def definition(self): - if self.barebone: - return gcpolicy = self.db.gcpolicy yield 'struct %s {' % self.name for fname, typename in self.gcfields: @@ -316,7 +297,7 @@ yield 'offsetof(struct %s, length)' % (self.name,) else: yield '-1' - if self.ARRAY.OF is not Void and not self.barebone: + if self.ARRAY.OF is not Void: yield 'offsetof(struct %s, items[0])' % (self.name,) yield 'offsetof(struct %s, items[1])' % (self.name,) else: @@ -324,6 +305,56 @@ yield '-1' +class BareBoneArrayDefNode: + """For 'simple' array types which don't need a length nor GC headers. + Implemented directly as a C array instead of a struct with an items field. + rffi kind of expects such arrays to be 'bare' C arrays. + """ + gcinfo = None + name = None + forward_decl = None + + def __init__(self, db, ARRAY, varlength=1): + self.db = db + self.ARRAY = ARRAY + self.LLTYPE = ARRAY + self.varlength = varlength + self.dependencies = {} + self.itemtypename = db.gettype(ARRAY.OF, who_asks=self) + + def setup(self): + """Array loops are forbidden by ForwardReference.become() because + there is no way to declare them in C.""" + + def gettype(self): + return self.itemtypename.replace('@', '(@)[%d]' % (self.varlength,)) + + def getptrtype(self): + return self.itemtypename.replace('@', '*@') + + def access_expr(self, baseexpr, index): + return '%s[%d]' % (baseexpr, index) + + def ptr_access_expr(self, baseexpr, index): + assert 0 <= index <= sys.maxint, "invalid constant index %r" % (index,) + return self.itemindex_access_expr(baseexpr, index) + + def itemindex_access_expr(self, baseexpr, indexexpr): + return 'RPyBareItem(%s, %s)' % (baseexpr, indexexpr) + + def definition(self): + return [] # no declaration is needed + + def visitor_lines(self, prefix, on_item): + raise Exception("cannot visit C arrays - don't know the length") + + def debug_offsets(self): + # generate three offsets for debugging inspection, + yield '-1' # no length + yield '0' # first element is immediately at the start of the array + yield 'sizeof(%s)' % (cdecl(self.itemtypename, ''),) + + class FixedSizeArrayDefNode: gcinfo = None name = None Modified: pypy/dist/pypy/translator/c/support.py ============================================================================== --- pypy/dist/pypy/translator/c/support.py (original) +++ pypy/dist/pypy/translator/c/support.py Tue Oct 2 10:57:43 2007 @@ -17,7 +17,8 @@ def barebonearray(ARRAY): """Check if ARRAY is a 'simple' array type, i.e. doesn't need a length nor GC headers.""" - return ARRAY._hints.get('nolength', False) and ARRAY._gckind != 'gc' + return (ARRAY._hints.get('nolength', False) and ARRAY._gckind != 'gc' + and ARRAY.OF is not lltype.Void) # From fijal at codespeak.net Tue Oct 2 11:54:37 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 2 Oct 2007 11:54:37 +0200 (CEST) Subject: [pypy-svn] r47090 - pypy/dist/pypy/translator/goal Message-ID: <20071002095437.BCB6A8143@code0.codespeak.net> Author: fijal Date: Tue Oct 2 11:54:37 2007 New Revision: 47090 Modified: pypy/dist/pypy/translator/goal/app_main.py Log: Use flag in pyrepl, not to clear main Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Tue Oct 2 11:54:37 2007 @@ -321,7 +321,7 @@ except ImportError: success = run_toplevel(interactive_console, mainmodule) else: - main(print_banner=False) + main(print_banner=False, clear_main=False) success = True except SystemExit, e: return e.code From fijal at codespeak.net Tue Oct 2 12:02:07 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 2 Oct 2007 12:02:07 +0200 (CEST) Subject: [pypy-svn] r47091 - pypy/dist/demo/distribution Message-ID: <20071002100207.289798143@code0.codespeak.net> Author: fijal Date: Tue Oct 2 12:02:06 2007 New Revision: 47091 Modified: pypy/dist/demo/distribution/fileclient.py pypy/dist/demo/distribution/fileserver.py Log: Improve docs, use code.interact as pypy-c -i might be buggy Modified: pypy/dist/demo/distribution/fileclient.py ============================================================================== --- pypy/dist/demo/distribution/fileclient.py (original) +++ pypy/dist/demo/distribution/fileclient.py Tue Oct 2 12:02:06 2007 @@ -1,14 +1,25 @@ """ This is sample client for a server based in fileserver.py, not counting -initialization and __doc__ has just 2 lines. Usage: +initialization, code.interact and __doc__ has just 2 lines! Usage: -pypy-c -i fileclient.py +pypy-c fileclient.py + +The file_opener is a proxy for remote file object. Which means you can +perform same operations as locally, like file_opener('/etc/passwd').read() +or file_opener('/tmp/x', 'w').write('x') + +pypy-c needs to be compiled with --allworkingmodules in order to have socket +working. """ + HOST = '127.0.0.1' PORT = 12221 from distributed.socklayer import connect file_opener = connect((HOST, PORT)).open -# now you can do for example file_opener('/etc/passwd').read() to -# read remote /etc/passwd +import code +code.interact(local=locals()) +# The file_opener is a proxy for remote file object. Which means you can +# perform same operations as locally, like file_opener('/etc/passwd').read() +# or file_opener('/tmp/x', 'w').write('x') Modified: pypy/dist/demo/distribution/fileserver.py ============================================================================== --- pypy/dist/demo/distribution/fileserver.py (original) +++ pypy/dist/demo/distribution/fileserver.py Tue Oct 2 12:02:06 2007 @@ -3,8 +3,11 @@ fully operational file server, sample client which is in fileclient.py is included as well. -Note that you must run it with pypy-c compiled with transparent proxy -and allworkingmodules (or at least socket and select) +run by: +pypy-c fileserver.py + +pypy-c needs to be compiled with --allworkingmodules in order to have socket +working. """ HOST = '127.0.0.1' # defaults to localhost, not to export your files From fijal at codespeak.net Tue Oct 2 12:06:52 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 2 Oct 2007 12:06:52 +0200 (CEST) Subject: [pypy-svn] r47092 - pypy/dist/demo/distribution Message-ID: <20071002100652.A249180A4@code0.codespeak.net> Author: fijal Date: Tue Oct 2 12:06:51 2007 New Revision: 47092 Modified: pypy/dist/demo/distribution/fileserver.py Log: Improve docstring Modified: pypy/dist/demo/distribution/fileserver.py ============================================================================== --- pypy/dist/demo/distribution/fileserver.py (original) +++ pypy/dist/demo/distribution/fileserver.py Tue Oct 2 12:06:51 2007 @@ -1,4 +1,6 @@ -""" This is sample demo about how flexible pypy distribution is. +""" This is a sample demo showcasing file server, done by the pypy +distriobution library. + Not counting __doc__ and initialization this is 2 line, fully operational file server, sample client which is in fileclient.py is included as well. From fijal at codespeak.net Tue Oct 2 12:40:23 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 2 Oct 2007 12:40:23 +0200 (CEST) Subject: [pypy-svn] r47095 - pypy/dist/pypy/lib/distributed Message-ID: <20071002104023.B1F6F80A7@code0.codespeak.net> Author: fijal Date: Tue Oct 2 12:40:22 2007 New Revision: 47095 Modified: pypy/dist/pypy/lib/distributed/socklayer.py pypy/dist/pypy/lib/distributed/support.py Log: unobfusticate support routines Modified: pypy/dist/pypy/lib/distributed/socklayer.py ============================================================================== --- pypy/dist/pypy/lib/distributed/socklayer.py (original) +++ pypy/dist/pypy/lib/distributed/socklayer.py Tue Oct 2 12:40:22 2007 @@ -64,9 +64,9 @@ return SenderWrapper(s).send, ReceiverWrapper(s).receive def connect(address, socket=socket): - from distributed.support import get_remote_view + from distributed.support import RemoteView from distributed import RemoteProtocol - return get_remote_view(RemoteProtocol(*socket_connecter(address, socket))) + return RemoteView(RemoteProtocol(*socket_connecter(address, socket))) def spawn_remote_side(code, gw): """ A very simple wrapper around greenexecnet to allow Modified: pypy/dist/pypy/lib/distributed/support.py ============================================================================== --- pypy/dist/pypy/lib/distributed/support.py (original) +++ pypy/dist/pypy/lib/distributed/support.py Tue Oct 2 12:40:22 2007 @@ -2,13 +2,16 @@ """ Some random support functions """ -def get_remote_view(protocol): - # this is dynamic to provide needed level of laziness - class RemoteView(object): - pass +from distributed.protocol import ObjectNotFound - for key in protocol.remote_keys(): - getter = lambda self: protocol.get_remote(key) - setattr(RemoteView, key, property(getter)) +class RemoteView(object): + def __init__(self, protocol): + self.__dict__['__protocol'] = protocol - return RemoteView() + def __getattr__(self, name): + if name == '__dict__': + return super(RemoteView, self).__getattr__(name) + try: + return self.__dict__['__protocol'].get_remote(name) + except ObjectNotFound: + raise AttributeError(name) From fijal at codespeak.net Tue Oct 2 12:41:04 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 2 Oct 2007 12:41:04 +0200 (CEST) Subject: [pypy-svn] r47096 - pypy/dist/demo/distribution Message-ID: <20071002104104.EA0FA80AA@code0.codespeak.net> Author: fijal Date: Tue Oct 2 12:41:04 2007 New Revision: 47096 Added: pypy/dist/demo/distribution/client.py (contents, props changed) pypy/dist/demo/distribution/server.py (contents, props changed) Log: Intermediate version of some demos, will fix later (battery dead) Added: pypy/dist/demo/distribution/client.py ============================================================================== --- (empty file) +++ pypy/dist/demo/distribution/client.py Tue Oct 2 12:41:04 2007 @@ -0,0 +1,16 @@ +""" This a sample client, suitable for use with server.py from this +directory + +run by: +pypy-c client.py +""" + +HOST = '127.0.0.1' +PORT = 12222 + +from distributed.socklayer import connect +remote_handle = connect((HOST, PORT)) + +import code +code.interact(local=locals()) + Added: pypy/dist/demo/distribution/server.py ============================================================================== --- (empty file) +++ pypy/dist/demo/distribution/server.py Tue Oct 2 12:41:04 2007 @@ -0,0 +1,35 @@ +""" This is a demo exposing all globals from the current process over +socket, to be accessible remotely. + +run by: +pypy-c server.py + +pypy-c needs to be compiled with --allworkingmodules in order to have socket +working. +""" + +# things to export +# function +def f(x): + return x + 3 + +# class +class X: + def __init__(self): + self.slot = 3 + + def meth(self, f, arg): + """ Method eating callable and calling it with an argument + """ + assert callable(f) + return f(arg) + +# object +x = X() + +# constants +HOST = '127.0.0.1' +PORT = 12222 + +from distributed.socklayer import socket_loop +socket_loop((HOST, PORT), globals()) From fijal at codespeak.net Tue Oct 2 12:51:02 2007 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 2 Oct 2007 12:51:02 +0200 (CEST) Subject: [pypy-svn] r47097 - pypy/dist/demo/distribution Message-ID: <20071002105102.51DE480AC@code0.codespeak.net> Author: fijal Date: Tue Oct 2 12:51:01 2007 New Revision: 47097 Modified: pypy/dist/demo/distribution/client.py pypy/dist/demo/distribution/server.py Log: Improve comments. Modified: pypy/dist/demo/distribution/client.py ============================================================================== --- pypy/dist/demo/distribution/client.py (original) +++ pypy/dist/demo/distribution/client.py Tue Oct 2 12:51:01 2007 @@ -14,3 +14,22 @@ import code code.interact(local=locals()) +""" Things that can be done: 1. remote object access + +x = remote_handle.x +assert type(x) is remote_handle.X # typecheck +x.meth(lambda x: x + 10, 6) # remote call, with callback localy +x.meth(remote_handle.f, 3) # remote call, remote callback +remote_handle.sys._getframe(2).f_locals['x'] # remote frame access +# XXX should be 'is x' and shouldn't need (2) argument + +# XXX next one does not work, while it should. Too much mangling with remote +# traceback frames probably +try: + x.meth() # wrong argument numbers +except: + import sys + e, c, tb = sys.exc_info() + import pdb + pdb.post_mortem(tb) +""" Modified: pypy/dist/demo/distribution/server.py ============================================================================== --- pypy/dist/demo/distribution/server.py (original) +++ pypy/dist/demo/distribution/server.py Tue Oct 2 12:51:01 2007 @@ -27,6 +27,9 @@ # object x = X() +# module +import sys + # constants HOST = '127.0.0.1' PORT = 12222 From arigo at codespeak.net Tue Oct 2 16:22:30 2007 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 Oct 2007 16:22:30 +0200 (CEST) Subject: [pypy-svn] r47101 - pypy/dist/demo Message-ID: <20071002142230.D0E6C8122@code0.codespeak.net> Author: arigo Date: Tue Oct 2 16:22:29 2007 New Revision: 47101 Modified: pypy/dist/demo/bpnn.py Log: Avoid float **. Modified: pypy/dist/demo/bpnn.py ============================================================================== --- pypy/dist/demo/bpnn.py (original) +++ pypy/dist/demo/bpnn.py Tue Oct 2 16:22:29 2007 @@ -131,7 +131,8 @@ # calculate error error = 0.0 for k in range(len(targets)): - error = error + 0.5*(targets[k]-self.ao[k])**2 + delta = targets[k]-self.ao[k] + error = error + 0.5*delta*delta return error From cfbolz at codespeak.net Tue Oct 2 20:38:21 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 2 Oct 2007 20:38:21 +0200 (CEST) Subject: [pypy-svn] r47102 - pypy/branch/rdict-index-based2 Message-ID: <20071002183821.57F528134@code0.codespeak.net> Author: cfbolz Date: Tue Oct 2 20:38:19 2007 New Revision: 47102 Added: pypy/branch/rdict-index-based2/ - copied from r47101, pypy/dist/ Log: create a new branch to merge in the work of the rdict-index-based branch. From cfbolz at codespeak.net Tue Oct 2 20:45:01 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 2 Oct 2007 20:45:01 +0200 (CEST) Subject: [pypy-svn] r47103 - in pypy/branch/rdict-index-based2/pypy/rpython: lltypesystem test Message-ID: <20071002184501.45DC88124@code0.codespeak.net> Author: cfbolz Date: Tue Oct 2 20:45:00 2007 New Revision: 47103 Modified: pypy/branch/rdict-index-based2/pypy/rpython/lltypesystem/rdict.py pypy/branch/rdict-index-based2/pypy/rpython/test/test_rdict.py Log: manually merge the changes of the rdict-index-based branch (which itself has the code from the more-gckinds branch, it seems). The work was mostly done by mwh, I only adapted it to todays rdict. The idea is to make rdict not use pointers to entries across function boundaries too much, as this makes the life of a moving GC very hard. Instead, the pair of (dict pointer, index) is used. Modified: pypy/branch/rdict-index-based2/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/branch/rdict-index-based2/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/branch/rdict-index-based2/pypy/rpython/lltypesystem/rdict.py Tue Oct 2 20:45:00 2007 @@ -75,7 +75,7 @@ # compute the shape of the DICTENTRY structure entryfields = [] - entrymeths = { + adtmeths = { 'must_clear_key': (isinstance(self.DICTKEY, lltype.Ptr) and self.DICTKEY._needsgc()), 'must_clear_value': (isinstance(self.DICTVALUE, lltype.Ptr) @@ -98,23 +98,25 @@ s_value) # * the state of the entry - trying to encode it as dummy objects + adtmeths['entry_has_f_everused'] = 0 + adtmeths['entry_has_f_valid'] = 0 if nullkeymarker and dummykeyobj: # all the state can be encoded in the key - entrymeths['everused'] = ll_everused_from_key - entrymeths['dummy_obj'] = dummykeyobj - entrymeths['valid'] = ll_valid_from_key - entrymeths['mark_deleted'] = ll_mark_deleted_in_key + adtmeths['entry_everused'] = ll_everused_from_key + adtmeths['dummy_obj'] = dummykeyobj + adtmeths['entry_valid'] = ll_valid_from_key + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_key # the key is overwritten by 'dummy' when the entry is deleted - entrymeths['must_clear_key'] = False + adtmeths['must_clear_key'] = False elif nullvaluemarker and dummyvalueobj: # all the state can be encoded in the value - entrymeths['everused'] = ll_everused_from_value - entrymeths['dummy_obj'] = dummyvalueobj - entrymeths['valid'] = ll_valid_from_value - entrymeths['mark_deleted'] = ll_mark_deleted_in_value + adtmeths['entry_everused'] = ll_everused_from_value + adtmeths['dummy_obj'] = dummyvalueobj + adtmeths['entry_valid'] = ll_valid_from_value + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_value # value is overwritten by 'dummy' when entry is deleted - entrymeths['must_clear_value'] = False + adtmeths['must_clear_value'] = False else: # we need a flag to know if the entry was ever used @@ -122,25 +124,27 @@ # the key and value will be reset to NULL to clear their # reference) entryfields.append(("f_everused", lltype.Bool)) - entrymeths['everused'] = ll_everused_from_flag + adtmeths['entry_everused'] = ll_everused_from_flag + adtmeths['entry_has_f_everused'] = 1 # can we still rely on a dummy obj to mark deleted entries? if dummykeyobj: - entrymeths['dummy_obj'] = dummykeyobj - entrymeths['valid'] = ll_valid_from_key - entrymeths['mark_deleted'] = ll_mark_deleted_in_key + adtmeths['dummy_obj'] = dummykeyobj + adtmeths['entry_valid'] = ll_valid_from_key + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_key # key is overwritten by 'dummy' when entry is deleted - entrymeths['must_clear_key'] = False + adtmeths['must_clear_key'] = False elif dummyvalueobj: - entrymeths['dummy_obj'] = dummyvalueobj - entrymeths['valid'] = ll_valid_from_value - entrymeths['mark_deleted'] = ll_mark_deleted_in_value + adtmeths['dummy_obj'] = dummyvalueobj + adtmeths['entry_valid'] = ll_valid_from_value + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_value # value is overwritten by 'dummy' when entry is deleted - entrymeths['must_clear_value'] = False + adtmeths['must_clear_value'] = False else: entryfields.append(("f_valid", lltype.Bool)) - entrymeths['valid'] = ll_valid_from_flag - entrymeths['mark_deleted'] = ll_mark_deleted_in_flag + adtmeths['entry_has_f_valid'] = 1 + adtmeths['entry_valid'] = ll_valid_from_flag + adtmeths['mark_entry_deleted'] = ll_mark_deleted_in_flag # * the value entryfields.append(("value", self.DICTVALUE)) @@ -150,15 +154,19 @@ fasthashfn = None else: fasthashfn = self.key_repr.get_ll_fasthash_function() + + adtmeths['entry_has_f_hash'] = 0 if fasthashfn is None: entryfields.append(("f_hash", lltype.Signed)) - entrymeths['hash'] = ll_hash_from_cache + adtmeths['entry_has_f_hash'] = 1 + # XXX entry_hash, maybe? + adtmeths['hash'] = ll_hash_from_cache else: - entrymeths['hash'] = ll_hash_recomputed - entrymeths['fasthashfn'] = fasthashfn + adtmeths['hash'] = ll_hash_recomputed + adtmeths['fasthashfn'] = fasthashfn # Build the lltype data structures - self.DICTENTRY = lltype.Struct("dictentry", adtmeths=entrymeths, + self.DICTENTRY = lltype.Struct("dictentry", *entryfields) self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY) fields = [ ("num_items", lltype.Signed), @@ -168,13 +176,13 @@ self.r_rdict_eqfn, self.r_rdict_hashfn = self._custom_eq_hash_repr() fields.extend([ ("fnkeyeq", self.r_rdict_eqfn.lowleveltype), ("fnkeyhash", self.r_rdict_hashfn.lowleveltype) ]) - adtmeths = { + adtmeths.update({ 'keyhash': ll_keyhash_custom, 'keyeq': ll_keyeq_custom, 'r_rdict_eqfn': self.r_rdict_eqfn, 'r_rdict_hashfn': self.r_rdict_hashfn, 'paranoia': True, - } + }) else: # figure out which functions must be used to hash and compare ll_keyhash = self.key_repr.get_ll_hash_function() @@ -182,11 +190,11 @@ ll_keyhash = lltype.staticAdtMethod(ll_keyhash) if ll_keyeq is not None: ll_keyeq = lltype.staticAdtMethod(ll_keyeq) - adtmeths = { + adtmeths.update({ 'keyhash': ll_keyhash, 'keyeq': ll_keyeq, 'paranoia': False, - } + }) adtmeths['KEY'] = self.DICTKEY adtmeths['VALUE'] = self.DICTVALUE self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths, @@ -350,47 +358,47 @@ # be direct_call'ed from rtyped flow graphs, which means that they will # get flowed and annotated, mostly with SomePtr. -def ll_everused_from_flag(entry): - return entry.f_everused +def ll_everused_from_flag(d, i): + return d.entries[i].f_everused + +def ll_everused_from_key(d, i): + return bool(d.entries[i].key) + +def ll_everused_from_value(d, i): + return bool(d.entries[i].value) + +def ll_valid_from_flag(d, i): + return d.entries[i].f_valid + +def ll_mark_deleted_in_flag(d, i): + d.entries[i].f_valid = False + +def ll_valid_from_key(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + return d.entry_everused(i) and d.entries[i].key != dummy + +def ll_mark_deleted_in_key(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + d.entries[i].key = dummy -def ll_everused_from_key(entry): - return bool(entry.key) +def ll_valid_from_value(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + return d.entry_everused(i) and d.entries[i].value != dummy -def ll_everused_from_value(entry): - return bool(entry.value) +def ll_mark_deleted_in_value(d, i): + DICT = lltype.typeOf(d).TO + dummy = DICT.dummy_obj.ll_dummy_value + d.entries[i].value = dummy -def ll_valid_from_flag(entry): - return entry.f_valid - -def ll_mark_deleted_in_flag(entry): - entry.f_valid = False - -def ll_valid_from_key(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - return entry.everused() and entry.key != dummy - -def ll_mark_deleted_in_key(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - entry.key = dummy - -def ll_valid_from_value(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - return entry.everused() and entry.value != dummy - -def ll_mark_deleted_in_value(entry): - ENTRY = lltype.typeOf(entry).TO - dummy = ENTRY.dummy_obj.ll_dummy_value - entry.value = dummy - -def ll_hash_from_cache(entry): - return entry.f_hash - -def ll_hash_recomputed(entry): - ENTRY = lltype.typeOf(entry).TO - return ENTRY.fasthashfn(entry.key) +def ll_hash_from_cache(d, i): + return d.entries[i].f_hash + +def ll_hash_recomputed(d, i): + DICT = lltype.typeOf(d).TO + return DICT.fasthashfn(d.entries[i].key) def ll_keyhash_custom(d, key): DICT = lltype.typeOf(d).TO @@ -408,9 +416,9 @@ return bool(d) and d.num_items != 0 def ll_dict_getitem(d, key): - entry = ll_dict_lookup(d, key, d.keyhash(key)) - if entry.valid(): - return entry.value + i = ll_dict_lookup(d, key, d.keyhash(key)) + if d.entry_valid(i): + return d.entries[i].value else: raise KeyError ll_dict_getitem.oopspec = 'dict.getitem(d, key)' @@ -418,20 +426,21 @@ def ll_dict_setitem(d, key, value): hash = d.keyhash(key) - entry = ll_dict_lookup(d, key, hash) - everused = entry.everused() - valid = entry.valid() + i = ll_dict_lookup(d, key, hash) + entry = d.entries[i] + everused = d.entry_everused(i) + valid = d.entry_valid(i) # set up the new entry - ENTRY = lltype.typeOf(entry).TO + DICT = lltype.typeOf(d).TO entry.value = value if valid: return entry.key = key - if hasattr(ENTRY, 'f_hash'): entry.f_hash = hash - if hasattr(ENTRY, 'f_valid'): entry.f_valid = True + if DICT.entry_has_f_hash: entry.f_hash = hash + if DICT.entry_has_f_valid: entry.f_valid = True d.num_items += 1 if not everused: - if hasattr(ENTRY, 'f_everused'): entry.f_everused = True + if DICT.entry_has_f_everused: entry.f_everused = True d.num_pristine_entries -= 1 if d.num_pristine_entries <= len(d.entries) / 3: ll_dict_resize(d) @@ -443,35 +452,38 @@ # the dict contains no deleted entries. This routine has the advantage # of never calling d.keyhash() and d.keyeq(), so it cannot call back # to user code. ll_dict_insertclean() doesn't resize the dict, either. - entry = ll_dict_lookup_clean(d, hash) - ENTRY = lltype.typeOf(entry).TO + i = ll_dict_lookup(d, key, hash) + entry = d.entries[i] + DICT = lltype.typeOf(d).TO entry.value = value entry.key = key - if hasattr(ENTRY, 'f_hash'): entry.f_hash = hash - if hasattr(ENTRY, 'f_valid'): entry.f_valid = True - if hasattr(ENTRY, 'f_everused'): entry.f_everused = True + if DICT.entry_has_f_hash: entry.f_hash = hash + if DICT.entry_has_f_valid: entry.f_valid = True + if DICT.entry_has_f_everused: entry.f_everused = True d.num_items += 1 d.num_pristine_entries -= 1 def ll_dict_delitem(d, key): - entry = ll_dict_lookup(d, key, d.keyhash(key)) - if not entry.valid(): + i = ll_dict_lookup(d, key, d.keyhash(key)) + if not d.entry_valid(i): raise KeyError - entry.mark_deleted() + d.mark_entry_deleted(i) d.num_items -= 1 # clear the key and the value if they are GC pointers - ENTRY = lltype.typeOf(entry).TO - if ENTRY.must_clear_key: + DICT = lltype.typeOf(d).TO + entry = d.entries[i] + if DICT.must_clear_key: key = entry.key # careful about destructor side effects: # keep key alive until entry.value has also # been zeroed (if it must be) - entry.key = lltype.nullptr(ENTRY.key.TO) - if ENTRY.must_clear_value: - entry.value = lltype.nullptr(ENTRY.value.TO) + entry.key = lltype.nullptr(DICT.entries.TO.OF.key.TO) + if DICT.must_clear_value: + entry.value = lltype.nullptr(DICT.entries.TO.OF.value.TO) num_entries = len(d.entries) if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4: ll_dict_resize(d) + def ll_dict_resize(d): old_entries = d.entries old_size = len(old_entries) @@ -480,15 +492,34 @@ new_size = old_size * 2 while new_size > DICT_INITSIZE and d.num_items < new_size / 4: new_size /= 2 - d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size, zero=True) - d.num_items = 0 - d.num_pristine_entries = new_size + new_entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size, zero=True) + new_num_items = 0 + new_num_pristine_entries = new_size i = 0 while i < old_size: entry = old_entries[i] - if entry.valid(): - ll_dict_insertclean(d, entry.key, entry.value, entry.hash()) + if d.entry_valid(i): + hash = d.hash(i) + # AAAAAAAAA XXX :-( + old_entries = d.entries + old_num_items = d.num_items + old_num_pristine_entries = d.num_pristine_entries + d.entries = new_entries + d.num_items = new_num_items + d.num_pristine_entries = new_num_pristine_entries + + ll_dict_insertclean(d, entry.key, entry.value, hash) + + new_entries = d.entries + new_num_items = d.num_items + new_num_pristine_entries = d.num_pristine_entries + d.entries = old_entries + d.num_items = old_num_items + d.num_pristine_entries = old_num_pristine_entries i += 1 + d.entries = new_entries + d.num_items = new_num_items + d.num_pristine_entries = new_num_pristine_entries # ------- a port of CPython's dictobject.c's lookdict implementation ------- PERTURB_SHIFT = 5 @@ -500,26 +531,28 @@ i = r_uint(hash & mask) # do the first try before any looping entry = entries[i] - if entry.valid(): + found_freeslot = False + freeslot_index = r_uint(0) + if d.entry_valid(i): checkingkey = entry.key if checkingkey == key: - return entry # found the entry - if d.keyeq is not None and entry.hash() == hash: + return i # found the entry + if d.keyeq is not None and d.hash(i) == hash: # correct hash, maybe the key is e.g. a different pointer to # an equal object found = d.keyeq(checkingkey, key) if DICT.paranoia: if (entries != d.entries or - not entry.valid() or entry.key != checkingkey): + not d.entry_valid(i) or entry.key != checkingkey): # the compare did major nasty stuff to the dict: start over return ll_dict_lookup(d, key, hash) if found: - return entry # found the entry - freeslot = lltype.nullptr(lltype.typeOf(entry).TO) - elif entry.everused(): - freeslot = entry + return i # found the entry + elif d.entry_everused(i): + freeslot_index = i + found_freeslot = True else: - return entry # pristine entry -- lookup failed + return i # pristine entry -- lookup failed # In the loop, a deleted entry (everused and not valid) is by far # (factor of 100s) the least likely outcome, so test for that last. @@ -527,26 +560,30 @@ while 1: i = ((i << 2) + i + perturb + 1) & mask entry = entries[i] - if not entry.everused(): - return freeslot or entry - elif entry.valid(): + if not d.entry_everused(i): + if found_freeslot: + return freeslot_index + else: + return i + elif d.entry_valid(i): checkingkey = entry.key if checkingkey == key: - return entry - if d.keyeq is not None and entry.hash() == hash: + return i + if d.keyeq is not None and d.hash(i) == hash: # correct hash, maybe the key is e.g. a different pointer to # an equal object found = d.keyeq(checkingkey, key) if DICT.paranoia: if (entries != d.entries or - not entry.valid() or entry.key != checkingkey): + not d.entry_valid(i) or entry.key != checkingkey): # the compare did major nasty stuff to the dict: # start over return ll_dict_lookup(d, key, hash) if found: - return entry # found the entry - elif not freeslot: - freeslot = entry + return i # found the entry + elif not found_freeslot: + freeslot_index = i + found_freeslot = True perturb >>= PERTURB_SHIFT def ll_dict_lookup_clean(d, hash): @@ -556,13 +593,11 @@ entries = d.entries mask = len(entries) - 1 i = r_uint(hash & mask) - entry = entries[i] perturb = r_uint(hash) - while entry.everused(): + while d.entry_everused(i): i = ((i << 2) + i + perturb + 1) & mask - entry = entries[i] perturb >>= PERTURB_SHIFT - return entry + return i # ____________________________________________________________ # @@ -638,8 +673,9 @@ entries_len = len(entries) while index < entries_len: entry = entries[index] + i = index index = index + 1 - if entry.valid(): + if dict.entry_valid(i): iter.index = index if RETURNTYPE is lltype.Void: return None @@ -660,16 +696,16 @@ # methods def ll_get(dict, key, default): - entry = ll_dict_lookup(dict, key, dict.keyhash(key)) - if entry.valid(): - return entry.value + i = ll_dict_lookup(dict, key, dict.keyhash(key)) + if dict.entry_valid(i): + return dict.entries[i].value else: return default def ll_setdefault(dict, key, default): - entry = ll_dict_lookup(dict, key, dict.keyhash(key)) - if entry.valid(): - return entry.value + i = ll_dict_lookup(dict, key, dict.keyhash(key)) + if dict.entry_valid(i): + return dict.entries[i].value else: ll_dict_setitem(dict, key, default) return default @@ -689,10 +725,10 @@ entry = dict.entries[i] ENTRY = lltype.typeOf(entry).TO d_entry.key = entry.key - if hasattr(ENTRY, 'f_valid'): d_entry.f_valid = entry.f_valid - if hasattr(ENTRY, 'f_everused'): d_entry.f_everused = entry.f_everused + if DICT.entry_has_f_valid : d_entry.f_valid = entry.f_valid + if DICT.entry_has_f_everused: d_entry.f_everused = entry.f_everused d_entry.value = entry.value - if hasattr(ENTRY, 'f_hash'): d_entry.f_hash = entry.f_hash + if DICT.entry_has_f_hash: d_entry.f_hash = entry.f_hash i += 1 return d @@ -709,8 +745,8 @@ d2len = len(entries) i = 0 while i < d2len: - entry = entries[i] - if entry.valid(): + if dic2.entry_valid(i): + entry = entries[i] ll_dict_setitem(dic1, entry.key, entry.value) i += 1 @@ -733,8 +769,8 @@ i = 0 p = 0 while i < dlen: - entry = entries[i] - if entry.valid(): + if dic.entry_valid(i): + entry = entries[i] ELEM = lltype.typeOf(items).TO.OF if ELEM is not lltype.Void: if func is dum_items: @@ -751,7 +787,7 @@ return res def ll_contains(d, key): - entry = ll_dict_lookup(d, key, d.keyhash(key)) - return entry.valid() + i = ll_dict_lookup(d, key, d.keyhash(key)) + return d.entry_valid(i) ll_contains.oopspec = 'dict.contains(d, key)' ll_contains.oopargcheck = lambda d, key: bool(d) Modified: pypy/branch/rdict-index-based2/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/branch/rdict-index-based2/pypy/rpython/test/test_rdict.py (original) +++ pypy/branch/rdict-index-based2/pypy/rpython/test/test_rdict.py Tue Oct 2 20:45:00 2007 @@ -548,7 +548,7 @@ res = self.interpret(func2, [ord(x), ord(y)]) for i in range(len(res.entries)): - assert not (res.entries[i].everused() and not res.entries[i].valid()) + assert not (res.entry_everused(i) and not res.entry_valid(i)) def func3(c0, c1, c2, c3, c4, c5, c6, c7): d = {} @@ -568,7 +568,7 @@ for i in range(rdict.DICT_INITSIZE)]) count_frees = 0 for i in range(len(res.entries)): - if not res.entries[i].everused(): + if not res.entry_everused(i): count_frees += 1 assert count_frees >= 3 @@ -610,8 +610,8 @@ res = self.interpret(f, []) assert res.item0 == True DICT = lltype.typeOf(res.item1).TO - assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None string keys - assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strings have a dummy + assert not DICT.entry_has_f_everused# non-None string keys + assert not DICT.entry_has_f_valid # strings have a dummy def test_opt_nullvaluemarker(self): def f(n): @@ -621,8 +621,8 @@ res = self.interpret(f, [-5]) assert res.item0 == 4 DICT = lltype.typeOf(res.item1).TO - assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None str values - assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strs have a dummy + assert not DICT.entry_has_f_everused# non-None string keys + assert not DICT.entry_has_f_valid # strings have a dummy def test_opt_nonullmarker(self): class A: @@ -638,8 +638,8 @@ res = self.interpret(f, [-5]) assert res.item0 == -5441 DICT = lltype.typeOf(res.item1).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # can-be-None A instances - assert not hasattr(DICT.entries.TO.OF, 'f_valid')# with a dummy A instance + assert DICT.entry_has_f_everused # can-be-None A instances + assert not DICT.entry_has_f_valid# with a dummy A instance res = self.interpret(f, [6]) assert res.item0 == -5441 @@ -654,8 +654,8 @@ assert res.item0 == 1 assert res.item1 == 24 DICT = lltype.typeOf(res.item2).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero - assert not hasattr(DICT.entries.TO.OF, 'f_valid')# nonneg int: dummy -1 + assert DICT.entry_has_f_everused # all ints can be zero + assert not DICT.entry_has_f_valid# nonneg int: dummy -1 def test_opt_no_dummy(self): def f(n): @@ -667,8 +667,8 @@ assert res.item0 == 1 assert res.item1 == -24 DICT = lltype.typeOf(res.item2).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero - assert hasattr(DICT.entries.TO.OF, 'f_valid') # no dummy available + assert DICT.entry_has_f_everused # all ints can be zero + assert DICT.entry_has_f_valid # no dummy available def test_opt_multiple_identical_dicts(self): def f(n): From cfbolz at codespeak.net Tue Oct 2 20:47:45 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 2 Oct 2007 20:47:45 +0200 (CEST) Subject: [pypy-svn] r47104 - pypy/branch/rdict-index-based Message-ID: <20071002184745.44D838124@code0.codespeak.net> Author: cfbolz Date: Tue Oct 2 20:47:44 2007 New Revision: 47104 Removed: pypy/branch/rdict-index-based/ Log: kill the rdict-index-based branch, since its ideas were put into the rdict-index-based2 branch. From cfbolz at codespeak.net Tue Oct 2 22:48:53 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 2 Oct 2007 22:48:53 +0200 (CEST) Subject: [pypy-svn] r47107 - pypy/branch/kill-keepalives-again Message-ID: <20071002204853.513738144@code0.codespeak.net> Author: cfbolz Date: Tue Oct 2 22:48:53 2007 New Revision: 47107 Added: pypy/branch/kill-keepalives-again/ - copied from r47106, pypy/dist/ Log: an experimental branch (that will probably be scrapped) to experiment with the stuff from the old kill-keepalive branch. From cfbolz at codespeak.net Wed Oct 3 00:51:41 2007 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 3 Oct 2007 00:51:41 +0200 (CEST) Subject: [pypy-svn] r47109 - in pypy/branch/kill-keepalives-again/pypy: annotation rpython rpython/lltypesystem rpython/test Message-ID: <20071002225141.73C1F813B@code0.codespeak.net> Author: cfbolz Date: Wed Oct 3 00:51:40 2007 New Revision: 47109 Modified: pypy/branch/kill-keepalives-again/pypy/annotation/bookkeeper.py pypy/branch/kill-keepalives-again/pypy/annotation/builtin.py pypy/branch/kill-keepalives-again/pypy/annotation/model.py pypy/branch/kill-keepalives-again/pypy/annotation/unaryop.py pypy/branch/kill-keepalives-again/pypy/rpython/llinterp.py pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lloperation.py pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/opimpl.py pypy/branch/kill-keepalives-again/pypy/rpython/rptr.py pypy/branch/kill-keepalives-again/pypy/rpython/test/test_rptr.py Log: first step in reviving the kill-keepalive branch: make the new way of rtyping the access of interior pointers work again. rptr tests pass. Modified: pypy/branch/kill-keepalives-again/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/branch/kill-keepalives-again/pypy/annotation/bookkeeper.py (original) +++ pypy/branch/kill-keepalives-again/pypy/annotation/bookkeeper.py Wed Oct 3 00:51:40 2007 @@ -11,7 +11,7 @@ SomeInteger, SomeExternalObject, SomeOOInstance, TLS, SomeAddress, \ SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, s_ImpossibleValue, \ SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \ - SomeList, SomeObject, HarmlesslyBlocked, SomeWeakRef + SomeList, SomeObject, HarmlesslyBlocked, SomeWeakRef, lltype_to_annotation from pypy.annotation.classdef import ClassDef, InstanceSource from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF @@ -239,7 +239,7 @@ if isinstance(s_callable, SomeLLADTMeth): adtmeth = s_callable s_callable = self.immutablevalue(adtmeth.func) - args_s = [SomePtr(adtmeth.ll_ptrtype)] + args_s + args_s = [lltype_to_annotation(adtmeth.ll_ptrtype)] + args_s if isinstance(s_callable, SomePBC): s_result = binding(call_op.result, s_ImpossibleValue) self.consider_call_site_for_pbc(s_callable, Modified: pypy/branch/kill-keepalives-again/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/kill-keepalives-again/pypy/annotation/builtin.py (original) +++ pypy/branch/kill-keepalives-again/pypy/annotation/builtin.py Wed Oct 3 00:51:40 2007 @@ -628,7 +628,6 @@ # memory address from pypy.rpython.memory import lladdress -from pypy.rpython.lltypesystem import llmemory def raw_malloc(s_size): assert isinstance(s_size, SomeInteger) #XXX add noneg...? @@ -669,7 +668,6 @@ #_________________________________ # offsetof/sizeof -from pypy.rpython.lltypesystem import llmemory def offsetof(TYPE, fldname): return SomeInteger() Modified: pypy/branch/kill-keepalives-again/pypy/annotation/model.py ============================================================================== --- pypy/branch/kill-keepalives-again/pypy/annotation/model.py (original) +++ pypy/branch/kill-keepalives-again/pypy/annotation/model.py Wed Oct 3 00:51:40 2007 @@ -551,6 +551,11 @@ def can_be_none(self): return False +class SomeInteriorPtr(SomePtr): + def __init__(self, ll_ptrtype): + assert isinstance(ll_ptrtype, lltype.InteriorPtr) + self.ll_ptrtype = ll_ptrtype + class SomeLLADTMeth(SomeObject): immutable = True def __init__(self, ll_ptrtype, func): @@ -597,6 +602,13 @@ return s_val.ootype if isinstance(s_val, SomeOOStaticMeth): return s_val.method + if isinstance(s_val, SomeInteriorPtr): + p = s_val.ll_ptrtype + if 0 in p.offsets: + assert list(p.offsets).count(0) == 1 + return lltype.Ptr(lltype.Ptr(p.PARENTTYPE)._interior_ptr_type_with_index(p.TO)) + else: + return lltype.Ptr(p.PARENTTYPE) if isinstance(s_val, SomePtr): return s_val.ll_ptrtype for witness, T in annotation_to_ll_map: @@ -630,6 +642,8 @@ return SomeOOClass(ootype.ROOT) elif isinstance(T, ExternalType): return SomeExternalInstance(T._class_) + elif isinstance(T, lltype.InteriorPtr): + return SomeInteriorPtr(T) else: return SomePtr(T) else: @@ -642,13 +656,19 @@ return s_None if isinstance(v, MethodType): ll_ptrtype = lltype.typeOf(v.im_self) - assert isinstance(ll_ptrtype, lltype.Ptr) + assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr)) return SomeLLADTMeth(ll_ptrtype, v.im_func) if isinstance(v, FunctionType): # this case should only be for staticmethod instances used in # adtmeths: the getattr() result is then a plain FunctionType object. from pypy.annotation.bookkeeper import getbookkeeper return getbookkeeper().immutablevalue(v) + if isinstance(v, lltype._interior_ptr): + ob = v._parent + if ob is None: + raise RuntimeError + T = lltype.InteriorPtr(lltype.typeOf(ob), v._T, v._offsets) + return SomeInteriorPtr(T) return lltype_to_annotation(lltype.typeOf(v)) # ____________________________________________________________ Modified: pypy/branch/kill-keepalives-again/pypy/annotation/unaryop.py ============================================================================== --- pypy/branch/kill-keepalives-again/pypy/annotation/unaryop.py (original) +++ pypy/branch/kill-keepalives-again/pypy/annotation/unaryop.py Wed Oct 3 00:51:40 2007 @@ -691,7 +691,7 @@ def call(adtmeth, args): bookkeeper = getbookkeeper() s_func = bookkeeper.immutablevalue(adtmeth.func) - return s_func.call(args.prepend(SomePtr(adtmeth.ll_ptrtype))) + return s_func.call(args.prepend(lltype_to_annotation(adtmeth.ll_ptrtype))) from pypy.rpython.ootypesystem import ootype class __extend__(SomeOOInstance): Modified: pypy/branch/kill-keepalives-again/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/kill-keepalives-again/pypy/rpython/llinterp.py (original) +++ pypy/branch/kill-keepalives-again/pypy/rpython/llinterp.py Wed Oct 3 00:51:40 2007 @@ -558,6 +558,31 @@ result = self.op_direct_call(write_barrier, *args) op_bare_setfield = op_setfield + def op_getinteriorfield(self, obj, *offsets): + checkptr(obj) + ob = obj + for o in offsets: + if isinstance(o, str): + ob = getattr(ob, o) + else: + ob = ob[o] + assert not isinstance(ob, lltype._interior_ptr) + return ob + + def op_setinteriorfield(self, obj, *fieldnamesval): + prefields, finalfield, fieldvalue = ( + fieldnamesval[:-2], fieldnamesval[-2], fieldnamesval[-1]) + for o in prefields: + if isinstance(o, str): + obj = getattr(obj, o) + else: + obj = obj[o] + if isinstance(finalfield, str): + setattr(obj, finalfield, fieldvalue) + else: + obj[finalfield] = fieldvalue + op_bare_setinteriorfield = op_setinteriorfield + def op_getarrayitem(self, array, index): return array[index] Modified: pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lloperation.py Wed Oct 3 00:51:40 2007 @@ -320,6 +320,9 @@ 'getarrayitem': LLOp(sideeffects=False, canrun=True), 'getarraysize': LLOp(canfold=True), 'getsubstruct': LLOp(canfold=True), + 'getinteriorfield': LLOp(sideeffects=False, canrun=True), + 'getinteriorarraysize': LLOp(canfold=True), + 'setinteriorfield': LLOp(), 'getarraysubstruct': LLOp(canfold=True), 'setfield': LLOp(), 'bare_setfield': LLOp(), Modified: pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py Wed Oct 3 00:51:40 2007 @@ -631,6 +631,34 @@ o = self.TO._container_example() return _ptr(self, o, solid=True) + def _interior_ptr_type_with_index(self, TO): + assert self.TO._gckind == 'gc' + if isinstance(TO, Struct): + R = GcStruct("Interior", ('ptr', self), ('index', Signed), + hints={'interior_ptr_type':True}, + adtmeths=TO._adtmeths) + else: + R = GcStruct("Interior", ('ptr', self), ('index', Signed), + hints={'interior_ptr_type':True}) + return R + +class InteriorPtr(LowLevelType): + def __init__(self, PARENTTYPE, TO, offsets): + self.PARENTTYPE = PARENTTYPE + self.TO = TO + self.offsets = tuple(offsets) + def __str__(self): + return '%s (%s).%s'%(self.__class__.__name__, + self.PARENTTYPE._short_name(), + '.'.join(map(str, self.offsets))) + def _example(self): + ob = Ptr(self.PARENTTYPE)._example() + for o in self.offsets: + if isinstance(o, str): + ob = getattr(ob, o) + else: + ob = ob[0] + return ob # ____________________________________________________________ @@ -667,6 +695,12 @@ return val.lltype() raise TypeError("typeOf(%r object)" % (tp.__name__,)) +def rawTypeOf(val): + if isinstance(val, _interior_ptr): + return Ptr(val._T) + else: + return typeOf(val) + _to_primitive = { Char: chr, UniChar: unichr, @@ -850,13 +884,6 @@ parent, base = parentlink(ptr._obj) return _subarray._makeptr(parent, base + n, ptr._solid) -def _expose(val, solid=False): - """XXX A nice docstring here""" - T = typeOf(val) - if isinstance(T, ContainerType): - val = _ptr(Ptr(T), val, solid=solid) - return val - def parentlink(container): parent = container._parentstructure() if parent is not None: @@ -903,26 +930,14 @@ class UninitializedMemoryAccess(Exception): pass -class _ptr(object): - __slots__ = ('_TYPE', '_T', - '_weak', '_solid', - '_obj0', '__weakref__') +class _abstract_ptr(object): + __slots__ = ('_T',) - def _set_TYPE(self, TYPE): - _ptr._TYPE.__set__(self, TYPE) + # assumes one can access _TYPE, _expose and _obj def _set_T(self, T): _ptr._T.__set__(self, T) - def _set_weak(self, weak): - _ptr._weak.__set__(self, weak) - - def _set_solid(self, solid): - _ptr._solid.__set__(self, solid) - - def _set_obj0(self, obj): - _ptr._obj0.__set__(self, obj) - def _togckind(self): return self._T._gckind @@ -930,19 +945,8 @@ # XXX deprecated interface return self._TYPE._needsgc() # xxx other rules? - def __init__(self, TYPE, pointing_to, solid=False): - self._set_TYPE(TYPE) - self._set_T(TYPE.TO) - self._set_weak(False) - self._setobj(pointing_to, solid) - - def _become(self, other): - assert self._TYPE == other._TYPE - assert not self._weak - self._setobj(other._obj, other._solid) -