Codebase list pypy / bfb21f2
Merge tag 'upstream/5.4.0+dfsg' into debian Upstream version 5.4.0+dfsg Stefano Rivera 7 years ago
447 changed file(s) with 10287 addition(s) and 3803 deletion(s). Raw diff Collapse all Expand all
8484 pass
8585
8686 def splitline(line, re_word = re.compile(r'[^\s"]\S*|["]["]|["].*?[^\\]["]')):
87 import ast
8788 result = []
8889 for word in re_word.findall(line):
8990 if word.startswith('"'):
90 word = eval(word)
91 word = ast.literal_eval(word)
9192 result.append(word)
9293 return result
9394
11 #define _PYPY_H_
22
33 /* This header is meant to be included in programs that use PyPy as an
4 embedded library. */
4 embedded library.
5
6 NOTE: this is deprecated. Instead, use cffi's embedding support:
7 http://cffi.readthedocs.org/en/latest/embedding.html
8 */
59
610 #ifdef __cplusplus
711 extern "C" {
173173
174174 class StringlikeHashRandomizationTests(HashRandomizationTests):
175175 if check_impl_detail(pypy=True):
176 EMPTY_STRING_HASH = -1
176 EMPTY_STRING_HASH = -2
177177 else:
178178 EMPTY_STRING_HASH = 0
179179
166166 else:
167167 return self.value
168168
169 def __buffer__(self):
169 def __buffer__(self, flags):
170170 return buffer(self._buffer)
171171
172172 def _get_b_base(self):
198198 return tp._alignmentofinstances()
199199
200200 @builtinify
201 def byref(cdata):
201 def byref(cdata, offset=0):
202202 # "pointer" is imported at the end of this module to avoid circular
203203 # imports
204 return pointer(cdata)
204 ptr = pointer(cdata)
205 if offset != 0:
206 ptr._buffer[0] += offset
207 return ptr
205208
206209 def cdata_from_address(self, address):
207210 # fix the address: turn it into as unsigned, in case it's a negative number
0 # Note: uses the CFFI out-of-line ABI mode. We can't use the API
1 # mode because ffi.compile() needs to run the compiler, which
2 # needs 'subprocess', which needs 'msvcrt' and '_subprocess',
3 # which depend on '_pypy_winbase_cffi' already.
4 #
5 # Note that if you need to regenerate _pypy_winbase_cffi and
6 # can't use a preexisting PyPy to do that, then running this
7 # file should work as long as 'subprocess' is not imported
8 # by cffi. I had to hack in 'cffi._pycparser' to move an
9 #'import subprocess' to the inside of a function. (Also,
10 # CPython+CFFI should work as well.)
11 #
12 # This module supports both msvcrt.py and _subprocess.py.
13
14 from cffi import FFI
15
16 ffi = FFI()
17
18 ffi.set_source("_pypy_winbase_cffi", None)
19
20 # ---------- MSVCRT ----------
21
22 ffi.cdef("""
23 typedef unsigned short wint_t;
24
25 int _open_osfhandle(intptr_t osfhandle, int flags);
26 intptr_t _get_osfhandle(int fd);
27 int _setmode(int fd, int mode);
28 int _locking(int fd, int mode, long nbytes);
29
30 int _kbhit(void);
31 int _getch(void);
32 wint_t _getwch(void);
33 int _getche(void);
34 wint_t _getwche(void);
35 int _putch(int);
36 wint_t _putwch(wchar_t);
37 int _ungetch(int);
38 wint_t _ungetwch(wint_t);
39 """)
40
41 # ---------- SUBPROCESS ----------
42
43 ffi.cdef("""
44 typedef struct {
45 DWORD cb;
46 char * lpReserved;
47 char * lpDesktop;
48 char * lpTitle;
49 DWORD dwX;
50 DWORD dwY;
51 DWORD dwXSize;
52 DWORD dwYSize;
53 DWORD dwXCountChars;
54 DWORD dwYCountChars;
55 DWORD dwFillAttribute;
56 DWORD dwFlags;
57 WORD wShowWindow;
58 WORD cbReserved2;
59 LPBYTE lpReserved2;
60 HANDLE hStdInput;
61 HANDLE hStdOutput;
62 HANDLE hStdError;
63 } STARTUPINFO, *LPSTARTUPINFO;
64
65 typedef struct {
66 HANDLE hProcess;
67 HANDLE hThread;
68 DWORD dwProcessId;
69 DWORD dwThreadId;
70 } PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
71
72 DWORD WINAPI GetVersion(void);
73 BOOL WINAPI CreatePipe(PHANDLE, PHANDLE, void *, DWORD);
74 BOOL WINAPI CloseHandle(HANDLE);
75 HANDLE WINAPI GetCurrentProcess(void);
76 BOOL WINAPI DuplicateHandle(HANDLE, HANDLE, HANDLE, LPHANDLE,
77 DWORD, BOOL, DWORD);
78 BOOL WINAPI CreateProcessA(char *, char *, void *,
79 void *, BOOL, DWORD, char *,
80 char *, LPSTARTUPINFO, LPPROCESS_INFORMATION);
81 DWORD WINAPI WaitForSingleObject(HANDLE, DWORD);
82 BOOL WINAPI GetExitCodeProcess(HANDLE, LPDWORD);
83 BOOL WINAPI TerminateProcess(HANDLE, UINT);
84 HANDLE WINAPI GetStdHandle(DWORD);
85 """)
86
87 # --------------------
88
89 if __name__ == "__main__":
90 ffi.compile()
0 # auto-generated file
1 import _cffi_backend
2
3 ffi = _cffi_backend.FFI('_pypy_winbase_cffi',
4 _version = 0x2601,
5 _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x07\x01\x00\x00\x09\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x19\x01\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x50\x03\x00\x00\x13\x11\x00\x00\x53\x03\x00\x00\x15\x11\x00\x00\x07\x01\x00\x00\x0A\x01\x00\x00\x13\x11\x00\x00\x13\x11\x00\x00\x4F\x03\x00\x00\x4E\x03\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x03\x00\x00\x1F\x11\x00\x00\x15\x11\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x08\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x18\x03\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x1F\x11\x00\x00\x0A\x01\x00\x00\x07\x01\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x0D\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x18\x0D\x00\x00\x15\x11\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x18\x0D\x00\x00\x02\x0F\x00\x00\x42\x0D\x00\x00\x06\x01\x00\x00\x00\x0F\x00\x00\x42\x0D\x00\x00\x00\x0F\x00\x00\x42\x0D\x00\x00\x10\x01\x00\x00\x00\x0F\x00\x00\x15\x0D\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x15\x0D\x00\x00\x02\x0F\x00\x00\x00\x09\x00\x00\x01\x09\x00\x00\x02\x01\x00\x00\x52\x03\x00\x00\x04\x01\x00\x00\x00\x01',
6 _globals = (b'\x00\x00\x24\x23CloseHandle',0,b'\x00\x00\x1E\x23CreatePipe',0,b'\x00\x00\x12\x23CreateProcessA',0,b'\x00\x00\x2F\x23DuplicateHandle',0,b'\x00\x00\x4C\x23GetCurrentProcess',0,b'\x00\x00\x2B\x23GetExitCodeProcess',0,b'\x00\x00\x49\x23GetStdHandle',0,b'\x00\x00\x3F\x23GetVersion',0,b'\x00\x00\x27\x23TerminateProcess',0,b'\x00\x00\x3B\x23WaitForSingleObject',0,b'\x00\x00\x38\x23_get_osfhandle',0,b'\x00\x00\x10\x23_getch',0,b'\x00\x00\x10\x23_getche',0,b'\x00\x00\x44\x23_getwch',0,b'\x00\x00\x44\x23_getwche',0,b'\x00\x00\x10\x23_kbhit',0,b'\x00\x00\x07\x23_locking',0,b'\x00\x00\x0C\x23_open_osfhandle',0,b'\x00\x00\x00\x23_putch',0,b'\x00\x00\x46\x23_putwch',0,b'\x00\x00\x03\x23_setmode',0,b'\x00\x00\x00\x23_ungetch',0,b'\x00\x00\x41\x23_ungetwch',0),
7 _struct_unions = ((b'\x00\x00\x00\x4E\x00\x00\x00\x02$PROCESS_INFORMATION',b'\x00\x00\x15\x11hProcess',b'\x00\x00\x15\x11hThread',b'\x00\x00\x18\x11dwProcessId',b'\x00\x00\x18\x11dwThreadId'),(b'\x00\x00\x00\x4F\x00\x00\x00\x02$STARTUPINFO',b'\x00\x00\x18\x11cb',b'\x00\x00\x13\x11lpReserved',b'\x00\x00\x13\x11lpDesktop',b'\x00\x00\x13\x11lpTitle',b'\x00\x00\x18\x11dwX',b'\x00\x00\x18\x11dwY',b'\x00\x00\x18\x11dwXSize',b'\x00\x00\x18\x11dwYSize',b'\x00\x00\x18\x11dwXCountChars',b'\x00\x00\x18\x11dwYCountChars',b'\x00\x00\x18\x11dwFillAttribute',b'\x00\x00\x18\x11dwFlags',b'\x00\x00\x42\x11wShowWindow',b'\x00\x00\x42\x11cbReserved2',b'\x00\x00\x51\x11lpReserved2',b'\x00\x00\x15\x11hStdInput',b'\x00\x00\x15\x11hStdOutput',b'\x00\x00\x15\x11hStdError')),
8 _typenames = (b'\x00\x00\x00\x1CLPPROCESS_INFORMATION',b'\x00\x00\x00\x1BLPSTARTUPINFO',b'\x00\x00\x00\x4EPROCESS_INFORMATION',b'\x00\x00\x00\x4FSTARTUPINFO',b'\x00\x00\x00\x42wint_t'),
9 )
99
1010 # Declare external Win32 functions
1111
12 import ctypes
13
14 _kernel32 = ctypes.WinDLL('kernel32')
15
16 _CloseHandle = _kernel32.CloseHandle
17 _CloseHandle.argtypes = [ctypes.c_int]
18 _CloseHandle.restype = ctypes.c_int
19
20 _CreatePipe = _kernel32.CreatePipe
21 _CreatePipe.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int),
22 ctypes.c_void_p, ctypes.c_int]
23 _CreatePipe.restype = ctypes.c_int
24
25 _GetCurrentProcess = _kernel32.GetCurrentProcess
26 _GetCurrentProcess.argtypes = []
27 _GetCurrentProcess.restype = ctypes.c_int
12 from _pypy_winbase_cffi import ffi as _ffi
13 _kernel32 = _ffi.dlopen('kernel32')
2814
2915 GetVersion = _kernel32.GetVersion
30 GetVersion.argtypes = []
31 GetVersion.restype = ctypes.c_int
3216
33 _DuplicateHandle = _kernel32.DuplicateHandle
34 _DuplicateHandle.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int,
35 ctypes.POINTER(ctypes.c_int),
36 ctypes.c_int, ctypes.c_int, ctypes.c_int]
37 _DuplicateHandle.restype = ctypes.c_int
38
39 _WaitForSingleObject = _kernel32.WaitForSingleObject
40 _WaitForSingleObject.argtypes = [ctypes.c_int, ctypes.c_uint]
41 _WaitForSingleObject.restype = ctypes.c_int
42
43 _GetExitCodeProcess = _kernel32.GetExitCodeProcess
44 _GetExitCodeProcess.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_int)]
45 _GetExitCodeProcess.restype = ctypes.c_int
46
47 _TerminateProcess = _kernel32.TerminateProcess
48 _TerminateProcess.argtypes = [ctypes.c_int, ctypes.c_int]
49 _TerminateProcess.restype = ctypes.c_int
50
51 _GetStdHandle = _kernel32.GetStdHandle
52 _GetStdHandle.argtypes = [ctypes.c_int]
53 _GetStdHandle.restype = ctypes.c_int
54
55 class _STARTUPINFO(ctypes.Structure):
56 _fields_ = [('cb', ctypes.c_int),
57 ('lpReserved', ctypes.c_void_p),
58 ('lpDesktop', ctypes.c_char_p),
59 ('lpTitle', ctypes.c_char_p),
60 ('dwX', ctypes.c_int),
61 ('dwY', ctypes.c_int),
62 ('dwXSize', ctypes.c_int),
63 ('dwYSize', ctypes.c_int),
64 ('dwXCountChars', ctypes.c_int),
65 ('dwYCountChars', ctypes.c_int),
66 ("dwFillAttribute", ctypes.c_int),
67 ("dwFlags", ctypes.c_int),
68 ("wShowWindow", ctypes.c_short),
69 ("cbReserved2", ctypes.c_short),
70 ("lpReserved2", ctypes.c_void_p),
71 ("hStdInput", ctypes.c_int),
72 ("hStdOutput", ctypes.c_int),
73 ("hStdError", ctypes.c_int)
74 ]
75
76 class _PROCESS_INFORMATION(ctypes.Structure):
77 _fields_ = [("hProcess", ctypes.c_int),
78 ("hThread", ctypes.c_int),
79 ("dwProcessID", ctypes.c_int),
80 ("dwThreadID", ctypes.c_int)]
81
82 _CreateProcess = _kernel32.CreateProcessA
83 _CreateProcess.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_void_p,
84 ctypes.c_int, ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
85 ctypes.POINTER(_STARTUPINFO), ctypes.POINTER(_PROCESS_INFORMATION)]
86 _CreateProcess.restype = ctypes.c_int
87
88 del ctypes
8917
9018 # Now the _subprocess module implementation
9119
92 from ctypes import c_int as _c_int, byref as _byref, WinError as _WinError
20 def _WinError():
21 code, message = _ffi.getwinerror()
22 raise WindowsError(code, message)
9323
94 class _handle:
95 def __init__(self, handle):
96 self.handle = handle
24 _INVALID_HANDLE_VALUE = _ffi.cast("HANDLE", -1)
25
26 class _handle(object):
27 def __init__(self, c_handle):
28 # 'c_handle' is a cffi cdata of type HANDLE, which is basically 'void *'
29 self.c_handle = c_handle
30 if int(self) != -1:
31 self.c_handle = _ffi.gc(self.c_handle, _kernel32.CloseHandle)
9732
9833 def __int__(self):
99 return self.handle
34 return int(_ffi.cast("intptr_t", self.c_handle))
10035
101 def __del__(self):
102 if self.handle is not None:
103 _CloseHandle(self.handle)
36 def __repr__(self):
37 return '<_subprocess.handle %d at 0x%x>' % (int(self), id(self))
10438
10539 def Detach(self):
106 handle, self.handle = self.handle, None
107 return handle
40 h = int(self)
41 if h != -1:
42 c_handle = self.c_handle
43 self.c_handle = _INVALID_HANDLE_VALUE
44 _ffi.gc(c_handle, None)
45 return h
10846
10947 def Close(self):
110 if self.handle not in (-1, None):
111 _CloseHandle(self.handle)
112 self.handle = None
48 if int(self) != -1:
49 c_handle = self.c_handle
50 self.c_handle = _INVALID_HANDLE_VALUE
51 _ffi.gc(c_handle, None)
52 _kernel32.CloseHandle(c_handle)
11353
11454 def CreatePipe(attributes, size):
115 read = _c_int()
116 write = _c_int()
55 handles = _ffi.new("HANDLE[2]")
11756
118 res = _CreatePipe(_byref(read), _byref(write), None, size)
57 res = _kernel32.CreatePipe(handles, handles + 1, _ffi.NULL, size)
11958
12059 if not res:
12160 raise _WinError()
12261
123 return _handle(read.value), _handle(write.value)
62 return _handle(handles[0]), _handle(handles[1])
12463
12564 def GetCurrentProcess():
126 return _handle(_GetCurrentProcess())
65 return _handle(_kernel32.GetCurrentProcess())
12766
12867 def DuplicateHandle(source_process, source, target_process, access, inherit, options=0):
129 target = _c_int()
68 # CPython: the first three arguments are expected to be integers
69 target = _ffi.new("HANDLE[1]")
13070
131 res = _DuplicateHandle(int(source_process), int(source), int(target_process),
132 _byref(target),
133 access, inherit, options)
71 res = _kernel32.DuplicateHandle(
72 _ffi.cast("HANDLE", source_process),
73 _ffi.cast("HANDLE", source),
74 _ffi.cast("HANDLE", target_process),
75 target, access, inherit, options)
13476
13577 if not res:
13678 raise _WinError()
13779
138 return _handle(target.value)
80 return _handle(target[0])
81
82 def _z(input):
83 if input is None:
84 return _ffi.NULL
85 if isinstance(input, basestring):
86 return str(input)
87 raise TypeError("string/unicode/None expected, got %r" % (
88 type(input).__name__,))
13989
14090 def CreateProcess(name, command_line, process_attr, thread_attr,
14191 inherit, flags, env, start_dir, startup_info):
142 si = _STARTUPINFO()
92 si = _ffi.new("STARTUPINFO *")
14393 if startup_info is not None:
14494 si.dwFlags = startup_info.dwFlags
14595 si.wShowWindow = startup_info.wShowWindow
96 # CPython: these three handles are expected to be _handle objects
14697 if startup_info.hStdInput:
147 si.hStdInput = int(startup_info.hStdInput)
98 si.hStdInput = startup_info.hStdInput.c_handle
14899 if startup_info.hStdOutput:
149 si.hStdOutput = int(startup_info.hStdOutput)
100 si.hStdOutput = startup_info.hStdOutput.c_handle
150101 if startup_info.hStdError:
151 si.hStdError = int(startup_info.hStdError)
102 si.hStdError = startup_info.hStdError.c_handle
152103
153 pi = _PROCESS_INFORMATION()
104 pi = _ffi.new("PROCESS_INFORMATION *")
154105
155106 if env is not None:
156107 envbuf = ""
158109 envbuf += "%s=%s\0" % (k, v)
159110 envbuf += '\0'
160111 else:
161 envbuf = None
112 envbuf = _ffi.NULL
162113
163 res = _CreateProcess(name, command_line, None, None, inherit, flags, envbuf,
164 start_dir, _byref(si), _byref(pi))
114 res = _kernel32.CreateProcessA(_z(name), _z(command_line), _ffi.NULL,
115 _ffi.NULL, inherit, flags, envbuf,
116 _z(start_dir), si, pi)
165117
166118 if not res:
167119 raise _WinError()
168120
169 return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessID, pi.dwThreadID
121 return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessId, pi.dwThreadId
170122
171123 def WaitForSingleObject(handle, milliseconds):
172 res = _WaitForSingleObject(int(handle), milliseconds)
173
124 # CPython: the first argument is expected to be an integer.
125 res = _kernel32.WaitForSingleObject(_ffi.cast("HANDLE", handle),
126 milliseconds)
174127 if res < 0:
175128 raise _WinError()
176129
177130 return res
178131
179132 def GetExitCodeProcess(handle):
180 code = _c_int()
133 # CPython: the first argument is expected to be an integer.
134 code = _ffi.new("DWORD[1]")
181135
182 res = _GetExitCodeProcess(int(handle), _byref(code))
136 res = _kernel32.GetExitCodeProcess(_ffi.cast("HANDLE", handle), code)
183137
184138 if not res:
185139 raise _WinError()
186140
187 return code.value
141 return code[0]
188142
189143 def TerminateProcess(handle, exitcode):
190 res = _TerminateProcess(int(handle), exitcode)
144 # CPython: the first argument is expected to be an integer.
145 # The second argument is silently wrapped in a UINT.
146 res = _kernel32.TerminateProcess(_ffi.cast("HANDLE", handle),
147 _ffi.cast("UINT", exitcode))
191148
192149 if not res:
193150 raise _WinError()
194151
195152 def GetStdHandle(stdhandle):
196 res = _GetStdHandle(stdhandle)
153 stdhandle = _ffi.cast("DWORD", stdhandle)
154 res = _kernel32.GetStdHandle(stdhandle)
197155
198156 if not res:
199157 return None
200158 else:
201 return res
159 # note: returns integer, not handle object
160 return int(_ffi.cast("intptr_t", res))
202161
203162 STD_INPUT_HANDLE = -10
204163 STD_OUTPUT_HANDLE = -11
33 from .api import FFI, CDefError, FFIError
44 from .ffiplatform import VerificationError, VerificationMissing
55
6 __version__ = "1.7.0"
7 __version_info__ = (1, 7, 0)
6 __version__ = "1.8.0"
7 __version_info__ = (1, 8, 0)
88
99 # The verifier module file names are based on the CRC32 of a string that
1010 # contains the following version number. It may be older than __version__
4141 # include <stdint.h>
4242 # endif
4343 # if _MSC_VER < 1800 /* MSVC < 2013 */
44 typedef unsigned char _Bool;
44 # ifndef __cplusplus
45 typedef unsigned char _Bool;
46 # endif
4547 # endif
4648 #else
4749 # include <stdint.h>
5860
5961 #ifdef __cplusplus
6062 # ifndef _Bool
61 # define _Bool bool /* semi-hackish: C++ has no _Bool; bool is builtin */
63 typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */
6264 # endif
6365 #endif
6466
195197 return NULL;
196198 }
197199
198 _CFFI_UNUSED_FN
199 static PyObject **_cffi_unpack_args(PyObject *args_tuple, Py_ssize_t expected,
200 const char *fnname)
201 {
202 if (PyTuple_GET_SIZE(args_tuple) != expected) {
203 PyErr_Format(PyExc_TypeError,
204 "%.150s() takes exactly %zd arguments (%zd given)",
205 fnname, expected, PyTuple_GET_SIZE(args_tuple));
206 return NULL;
207 }
208 return &PyTuple_GET_ITEM(args_tuple, 0); /* pointer to the first item,
209 the others follow */
210 }
211
212200 /********** end CPython-specific section **********/
213201 #else
214202 _CFFI_UNUSED_FN
232232 f = PySys_GetObject((char *)"stderr");
233233 if (f != NULL && f != Py_None) {
234234 PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
235 "\ncompiled with cffi version: 1.7.0"
235 "\ncompiled with cffi version: 1.8.0"
236236 "\n_cffi_backend module: ", f);
237237 modules = PyImport_GetModuleDict();
238238 mod = PyDict_GetItemString(modules, "_cffi_backend");
99 __all__ = ['c_lexer', 'c_parser', 'c_ast']
1010 __version__ = '2.14'
1111
12 from subprocess import Popen, PIPE
1312 from .c_parser import CParser
1413
1514
2726 When successful, returns the preprocessed file's contents.
2827 Errors from cpp will be printed out.
2928 """
29 from subprocess import Popen, PIPE
3030 path_list = [cpp_path]
3131 if isinstance(cpp_args, list):
3232 path_list += cpp_args
518518 smallest_value = min(self.enumvalues)
519519 largest_value = max(self.enumvalues)
520520 else:
521 import warnings
522 warnings.warn("%r has no values explicitly defined; next version "
523 "will refuse to guess which integer type it is "
524 "meant to be (unsigned/signed, int/long)"
525 % self._get_c_name())
526 smallest_value = largest_value = 0
521 raise api.CDefError("%r has no values explicitly defined: "
522 "refusing to guess which integer type it is "
523 "meant to be (unsigned/signed, int/long)"
524 % self._get_c_name())
527525 if smallest_value < 0: # needs a signed type
528526 sign = 1
529527 candidate1 = PrimitiveType("int")
274274 def write_c_source_to_f(self, f, preamble):
275275 self._f = f
276276 prnt = self._prnt
277 if self.ffi._embedding is None:
278 prnt('#define Py_LIMITED_API')
277279 #
278280 # first the '#include' (actually done by inlining the file's content)
279281 lines = self._rel_readlines('_cffi_include.h')
512514 tovar, errcode)
513515 return
514516 #
515 elif isinstance(tp, (model.StructOrUnion, model.EnumType)):
517 elif isinstance(tp, model.StructOrUnionOrEnum):
516518 # a struct (not a struct pointer) as a function argument
517519 self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
518520 % (tovar, self._gettypenum(tp), fromvar))
569571 elif isinstance(tp, model.ArrayType):
570572 return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
571573 var, self._gettypenum(model.PointerType(tp.item)))
572 elif isinstance(tp, model.StructType):
574 elif isinstance(tp, model.StructOrUnion):
573575 if tp.fldnames is None:
574576 raise TypeError("'%s' is used as %s, but is opaque" % (
575577 tp._get_c_name(), context))
682684 rng = range(len(tp.args))
683685 for i in rng:
684686 prnt(' PyObject *arg%d;' % i)
685 prnt(' PyObject **aa;')
686687 prnt()
687 prnt(' aa = _cffi_unpack_args(args, %d, "%s");' % (len(rng), name))
688 prnt(' if (aa == NULL)')
688 prnt(' if (!PyArg_UnpackTuple(args, "%s", %d, %d, %s))' % (
689 name, len(rng), len(rng),
690 ', '.join(['&arg%d' % i for i in rng])))
689691 prnt(' return NULL;')
690 for i in rng:
691 prnt(' arg%d = aa[%d];' % (i, i))
692692 prnt()
693693 #
694694 for i, type in enumerate(tp.args):
861861 enumfields = list(tp.enumfields())
862862 for fldname, fldtype, fbitsize, fqual in enumfields:
863863 fldtype = self._field_type(tp, fldname, fldtype)
864 self._check_not_opaque(fldtype,
865 "field '%s.%s'" % (tp.name, fldname))
864866 # cname is None for _add_missing_struct_unions() only
865867 op = OP_NOOP
866868 if fbitsize >= 0:
910912 first_field_index, c_fields))
911913 self._seen_struct_unions.add(tp)
912914
915 def _check_not_opaque(self, tp, location):
916 while isinstance(tp, model.ArrayType):
917 tp = tp.item
918 if isinstance(tp, model.StructOrUnion) and tp.fldtypes is None:
919 raise TypeError(
920 "%s is of an opaque type (not declared in cdef())" % location)
921
913922 def _add_missing_struct_unions(self):
914923 # not very nice, but some struct declarations might be missing
915924 # because they don't have any known C name. Check that they are
307307 elif isinstance(tp, model.ArrayType):
308308 return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
309309 var, self._gettypenum(model.PointerType(tp.item)))
310 elif isinstance(tp, model.StructType):
310 elif isinstance(tp, model.StructOrUnion):
311311 if tp.fldnames is None:
312312 raise TypeError("'%s' is used as %s, but is opaque" % (
313313 tp._get_c_name(), context))
00 Metadata-Version: 1.1
11 Name: cffi
2 Version: 1.7.0
2 Version: 1.8.0
33 Summary: Foreign Function Interface for Python calling C code.
44 Home-page: http://cffi.readthedocs.org
55 Author: Armin Rigo, Maciej Fijalkowski
838838 month = self._month
839839 if day is None:
840840 day = self._day
841 return date(year, month, day)
841 return date.__new__(type(self), year, month, day)
842842
843843 # Comparisons of date objects with other.
844844
13551355 microsecond = self.microsecond
13561356 if tzinfo is True:
13571357 tzinfo = self.tzinfo
1358 return time(hour, minute, second, microsecond, tzinfo)
1358 return time.__new__(type(self),
1359 hour, minute, second, microsecond, tzinfo)
13591360
13601361 def __nonzero__(self):
13611362 if self.second or self.microsecond:
15651566 microsecond = self.microsecond
15661567 if tzinfo is True:
15671568 tzinfo = self.tzinfo
1568 return datetime(year, month, day, hour, minute, second, microsecond,
1569 tzinfo)
1569 return datetime.__new__(type(self),
1570 year, month, day, hour, minute, second,
1571 microsecond, tzinfo)
15701572
15711573 def astimezone(self, tz):
15721574 if not isinstance(tz, tzinfo):
136136 lib.gdbm_sync(self.__ll_dbm)
137137
138138 def open(filename, flags='r', mode=0666):
139 if isinstance(filename, unicode):
140 filename = filename.encode()
139141 if flags[0] == 'r':
140142 iflags = lib.GDBM_READER
141143 elif flags[0] == 'w':
00 Metadata-Version: 1.0
11 Name: greenlet
2 Version: 0.4.9
2 Version: 0.4.10
33 Summary: Lightweight in-process concurrent programming
44 Home-page: https://github.com/python-greenlet/greenlet
55 Author: Ralf Schmitt (for CPython), PyPy team
00 import sys
11 import _continuation
22
3 __version__ = "0.4.9"
3 __version__ = "0.4.10"
44
55 # ____________________________________________________________
66 # Exceptions
66 # XXX incomplete: implemented only functions needed by subprocess.py
77 # PAC: 2010/08 added MS locking for Whoosh
88
9 import ctypes
9 # 07/2016: rewrote in CFFI
10
11 import sys
12 if sys.platform != 'win32':
13 raise ImportError("The 'msvcrt' module is only available on Windows")
14
15 import _rawffi
16 from _pypy_winbase_cffi import ffi as _ffi
17 _lib = _ffi.dlopen(_rawffi.get_libc().name)
18
1019 import errno
11 from ctypes_support import standard_c_lib as _c
12 from ctypes_support import get_errno
13
14 try:
15 open_osfhandle = _c._open_osfhandle
16 except AttributeError: # we are not on windows
17 raise ImportError
1820
1921 try: from __pypy__ import builtinify, validate_fd
2022 except ImportError: builtinify = validate_fd = lambda f: f
2123
2224
23 open_osfhandle.argtypes = [ctypes.c_int, ctypes.c_int]
24 open_osfhandle.restype = ctypes.c_int
25 def _ioerr():
26 e = _ffi.errno
27 raise IOError(e, errno.errorcode[e])
2528
26 _get_osfhandle = _c._get_osfhandle
27 _get_osfhandle.argtypes = [ctypes.c_int]
28 _get_osfhandle.restype = ctypes.c_int
29
30 @builtinify
31 def open_osfhandle(fd, flags):
32 """"open_osfhandle(handle, flags) -> file descriptor
33
34 Create a C runtime file descriptor from the file handle handle. The
35 flags parameter should be a bitwise OR of os.O_APPEND, os.O_RDONLY,
36 and os.O_TEXT. The returned file descriptor may be used as a parameter
37 to os.fdopen() to create a file object."""
38 fd = _lib._open_osfhandle(fd, flags)
39 if fd == -1:
40 _ioerr()
41 return fd
2942
3043 @builtinify
3144 def get_osfhandle(fd):
3750 validate_fd(fd)
3851 except OSError as e:
3952 raise IOError(*e.args)
40 return _get_osfhandle(fd)
53 result = _lib._get_osfhandle(fd)
54 if result == -1:
55 _ioerr()
56 return result
4157
42 setmode = _c._setmode
43 setmode.argtypes = [ctypes.c_int, ctypes.c_int]
44 setmode.restype = ctypes.c_int
58 @builtinify
59 def setmode(fd, flags):
60 """setmode(fd, mode) -> Previous mode
61
62 Set the line-end translation mode for the file descriptor fd. To set
63 it to text mode, flags should be os.O_TEXT; for binary, it should be
64 os.O_BINARY."""
65 flags = _lib._setmode(fd, flags)
66 if flags == -1:
67 _ioerr()
68 return flags
4569
4670 LK_UNLCK, LK_LOCK, LK_NBLCK, LK_RLCK, LK_NBRLCK = range(5)
4771
48 _locking = _c._locking
49 _locking.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int]
50 _locking.restype = ctypes.c_int
51
5272 @builtinify
5373 def locking(fd, mode, nbytes):
54 '''lock or unlock a number of bytes in a file.'''
55 rv = _locking(fd, mode, nbytes)
74 """"locking(fd, mode, nbytes) -> None
75
76 Lock part of a file based on file descriptor fd from the C runtime.
77 Raises IOError on failure. The locked region of the file extends from
78 the current file position for nbytes bytes, and may continue beyond
79 the end of the file. mode must be one of the LK_* constants listed
80 below. Multiple regions in a file may be locked at the same time, but
81 may not overlap. Adjacent regions are not merged; they must be unlocked
82 individually."""
83 rv = _lib._locking(fd, mode, nbytes)
5684 if rv != 0:
57 e = get_errno()
58 raise IOError(e, errno.errorcode[e])
85 _ioerr()
5986
6087 # Console I/O routines
6188
62 kbhit = _c._kbhit
63 kbhit.argtypes = []
64 kbhit.restype = ctypes.c_int
89 kbhit = _lib._kbhit
6590
66 getch = _c._getch
67 getch.argtypes = []
68 getch.restype = ctypes.c_char
91 @builtinify
92 def getch():
93 return chr(_lib._getch())
6994
70 getwch = _c._getwch
71 getwch.argtypes = []
72 getwch.restype = ctypes.c_wchar
95 @builtinify
96 def getwch():
97 return unichr(_lib._getwch())
7398
74 getche = _c._getche
75 getche.argtypes = []
76 getche.restype = ctypes.c_char
99 @builtinify
100 def getche():
101 return chr(_lib._getche())
77102
78 getwche = _c._getwche
79 getwche.argtypes = []
80 getwche.restype = ctypes.c_wchar
103 @builtinify
104 def getwche():
105 return unichr(_lib._getwche())
81106
82 putch = _c._putch
83 putch.argtypes = [ctypes.c_char]
84 putch.restype = None
107 @builtinify
108 def putch(ch):
109 _lib._putch(ord(ch))
85110
86 putwch = _c._putwch
87 putwch.argtypes = [ctypes.c_wchar]
88 putwch.restype = None
111 @builtinify
112 def putwch(ch):
113 _lib._putwch(ord(ch))
89114
90 ungetch = _c._ungetch
91 ungetch.argtypes = [ctypes.c_char]
92 ungetch.restype = None
115 @builtinify
116 def ungetch(ch):
117 if _lib._ungetch(ord(ch)) == -1: # EOF
118 _ioerr()
93119
94 ungetwch = _c._ungetwch
95 ungetwch.argtypes = [ctypes.c_wchar]
96 ungetwch.restype = None
97
98 del ctypes
120 @builtinify
121 def ungetwch(ch):
122 if _lib._ungetwch(ord(ch)) == -1: # EOF
123 _ioerr()
8585 if len(limits) != 2:
8686 raise ValueError("expected a tuple of 2 integers")
8787
88 if lib.my_setrlimit(resource, limits[0], limits[1]) == -1:
88 # accept and round down floats, like CPython does
89 limit0 = int(limits[0])
90 limit1 = int(limits[1])
91
92 if lib.my_setrlimit(resource, limit0, limit1) == -1:
8993 if ffi.errno == EINVAL:
9094 raise ValueError("current limit exceeds maximum limit")
9195 elif ffi.errno == EPERM:
3535 "cStringIO", "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
3636 "binascii", "_multiprocessing", '_warnings', "_collections",
3737 "_multibytecodec", "micronumpy", "_continuation", "_cffi_backend",
38 "_csv", "cppyy", "_pypyjson",
38 "_csv", "cppyy", "_pypyjson", "_jitlog"
3939 ])
4040
4141 from rpython.jit.backend import detect_cpu
7575 def pytest_pycollect_makemodule(path, parent):
7676 return PyPyModule(path, parent)
7777
78 def is_applevel(item):
79 from pypy.tool.pytest.apptest import AppTestFunction
80 return isinstance(item, AppTestFunction)
81
82 def pytest_collection_modifyitems(config, items):
83 if config.option.runappdirect:
84 return
85 for item in items:
86 if isinstance(item, py.test.Function):
87 if is_applevel(item):
88 item.add_marker('applevel')
89 else:
90 item.add_marker('interplevel')
91
7892 class PyPyModule(py.test.collect.Module):
7993 """ we take care of collecting classes both at app level
8094 and at interp-level (because we need to stick a space
109123 if name.startswith('AppTest'):
110124 from pypy.tool.pytest.apptest import AppClassCollector
111125 return AppClassCollector(name, parent=self)
112 else:
113 from pypy.tool.pytest.inttest import IntClassCollector
114 return IntClassCollector(name, parent=self)
115126
116127 elif hasattr(obj, 'func_code') and self.funcnamefilter(name):
117128 if name.startswith('app_test_'):
119130 "generator app level functions? you must be joking"
120131 from pypy.tool.pytest.apptest import AppTestFunction
121132 return AppTestFunction(name, parent=self)
122 elif obj.func_code.co_flags & 32: # generator function
123 return pytest.Generator(name, parent=self)
124 else:
125 from pypy.tool.pytest.inttest import IntTestFunction
126 return IntTestFunction(name, parent=self)
133 return super(PyPyModule, self).makeitem(name, obj)
127134
128135 def skip_on_missing_buildoption(**ropts):
129136 __tracebackhide__ = True
152159
153160 def pytest_runtest_setup(__multicall__, item):
154161 if isinstance(item, py.test.collect.Function):
155 appclass = item.getparent(PyPyClassCollector)
162 appclass = item.getparent(py.test.Class)
156163 if appclass is not None:
157164 # Make cls.space and cls.runappdirect available in tests.
158165 spaceconfig = getattr(appclass.obj, 'spaceconfig', None)
159166 if spaceconfig is not None:
160167 from pypy.tool.pytest.objspace import gettestobjspace
161168 appclass.obj.space = gettestobjspace(**spaceconfig)
169 else:
170 appclass.obj.space = LazyObjSpaceGetter()
162171 appclass.obj.runappdirect = option.runappdirect
163172
164173 __multicall__.execute()
165174
166 def pytest_runtest_teardown(__multicall__, item):
167 __multicall__.execute()
168
169 if 'pygame' in sys.modules:
170 assert option.view, ("should not invoke Pygame "
171 "if conftest.option.view is False")
172
173
174 class PyPyClassCollector(py.test.collect.Class):
175 # All pypy Test classes have a "space" member.
176 def setup(self):
177 cls = self.obj
178 if not hasattr(cls, 'spaceconfig'):
179 cls.space = LazyObjSpaceGetter()
180 else:
181 assert hasattr(cls, 'space') # set by pytest_runtest_setup
182 super(PyPyClassCollector, self).setup()
183
184175
185176 def pytest_ignore_collect(path):
186177 return path.check(link=1)
103103
104104 apt-get install gcc make libffi-dev pkg-config libz-dev libbz2-dev \
105105 libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev libgdbm-dev \
106 tk-dev libgc-dev liblzma-dev
107
108 For the optional lzma module on PyPy3 you will also need ``liblzma-dev``.
106 tk-dev libgc-dev \
107 liblzma-dev # For lzma on PyPy3.
109108
110109 On Fedora::
111110
112111 dnf install gcc make libffi-devel pkgconfig zlib-devel bzip2-devel \
113112 lib-sqlite3-devel ncurses-devel expat-devel openssl-devel tk-devel \
114 gdbm-devel
115
116 For the optional lzma module on PyPy3 you will also need ``xz-devel``.
113 gdbm-devel \
114 xz-devel # For lzma on PyPy3.
117115
118116 On SLES11::
119117
120118 zypper install gcc make python-devel pkg-config \
121119 zlib-devel libopenssl-devel libbz2-devel sqlite3-devel \
122 libexpat-devel libffi-devel python-curses
120 libexpat-devel libffi-devel python-curses \
121 xz-devel # For lzma on PyPy3.
123122 (XXX plus the SLES11 version of libgdbm-dev and tk-dev)
124
125 For the optional lzma module on PyPy3 you will also need ``xz-devel``.
126123
127124 On Mac OS X, most of these build-time dependencies are installed alongside
128125 the Developer Tools. However, note that in order for the installation to
5757
5858 # General information about the project.
5959 project = u'PyPy'
60 copyright = u'2015, The PyPy Project'
60 copyright = u'2016, The PyPy Project'
6161
6262 # The version info for the project you're documenting, acts as replacement for
6363 # |version| and |release|, also used in various other places throughout the
6464 # built documents.
6565 #
6666 # The short X.Y version.
67 version = '4.0'
67 version = '5.4'
6868 # The full version, including alpha/beta/rc tags.
69 release = '4.0.0'
69 release = '5.4.0'
7070
7171 # The language for content autogenerated by Sphinx. Refer to documentation
7272 # for a list of supported languages.
88 PyPy Python interpreter options
99 -------------------------------
1010
11 The following options can be used after ``translate.py
11 The following options can be used after ``rpython
1212 targetpypystandalone`` or as options to ``py.py``.
1313
1414 .. GENERATE: objspace
2121 General translation options
2222 ---------------------------
2323
24 The following are options of ``translate.py``. They must be
24 The following are options of ``bin/rpython``. They must be
2525 given before the ``targetxxx`` on the command line.
2626
2727 * `--opt -O:`__ set the optimization level `[0, 1, size, mem, 2, 3]`
1414
1515 ./py.py <`objspace options`_>
1616
17 and the ``translate.py`` translation entry
17 and the ``rpython/bin/rpython`` translation entry
1818 point which takes arguments of this form:
1919
2020 .. parsed-literal::
2121
22 ./translate.py <`translation options`_> <target>
22 ./rpython/bin/rpython <`translation options`_> <target>
2323
2424 For the common case of ``<target>`` being ``targetpypystandalone.py``,
2525 you can then pass the `object space options`_ after
2727
2828 .. parsed-literal::
2929
30 ./translate.py <`translation options`_> targetpypystandalone.py <`objspace options`_>
30 ./rpython/bin/rpython <`translation options`_> targetpypystandalone.py <`objspace options`_>
3131
3232 There is an `overview`_ of all command line arguments that can be
3333 passed in either position.
33 This meta-option selects a default set of optimization
44 settings to use during a translation. Usage::
55
6 translate.py --opt=#
7 translate.py -O#
6 bin/rpython --opt=#
7 bin/rpython -O#
88
99 where ``#`` is the desired optimization level. The valid choices are:
1010
00 write the generated C files to ``/dev/null`` instead of to the disk. Useful if
1 you want to use translate.py as a benchmark and don't want to access the disk.
1 you want to use translation as a benchmark and don't want to access the disk.
22
33 .. _`translation documentation`: ../translation.html
00 This is an option mostly useful when working on the PyPy toolchain. If you use
1 it, translate.py will fork before the specified phase. If the translation
1 it, translation will fork before the specified phase. If the translation
22 crashes after that fork, you can fix the bug in the toolchain, and continue
33 translation at the fork-point.
121121 $ hg up reflex-support # optional
122122
123123 # This example shows python, but using pypy-c is faster and uses less memory
124 $ python rpython/translator/goal/translate.py --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy
124 $ python rpython/bin/rpython --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy
125125
126126 This will build a ``pypy-c`` that includes the cppyy module, and through that,
127127 Reflex support.
9898
9999 The garbage collectors used or implemented by PyPy are not based on
100100 reference counting, so the objects are not freed instantly when they are no
101 longer reachable. The most obvious effect of this is that files are not
101 longer reachable. The most obvious effect of this is that files (and sockets, etc) are not
102102 promptly closed when they go out of scope. For files that are opened for
103103 writing, data can be left sitting in their output buffers for a while, making
104104 the on-disk file appear empty or truncated. Moreover, you might reach your
105105 OS's limit on the number of concurrently opened files.
106106
107 Fixing this is essentially impossible without forcing a
107 If you are debugging a case where a file in your program is not closed
108 properly, you can use the ``-X track-resources`` command line option. If it is
109 given, a ``ResourceWarning`` is produced for every file and socket that the
110 garbage collector closes. The warning will contain the stack trace of the
111 position where the file or socket was created, to make it easier to see which
112 parts of the program don't close files explicitly.
113
114 Fixing this difference to CPython is essentially impossible without forcing a
108115 reference-counting approach to garbage collection. The effect that you
109116 get in CPython has clearly been described as a side-effect of the
110117 implementation and not a language design decision: programs relying on
111 this are basically bogus. It would anyway be insane to try to enforce
118 this are basically bogus. It would be a too strong restriction to try to enforce
112119 CPython's behavior in a language spec, given that it has no chance to be
113120 adopted by Jython or IronPython (or any other port of Python to Java or
114121 .NET).
133140
134141 Here are some more technical details. This issue affects the precise
135142 time at which ``__del__`` methods are called, which
136 is not reliable in PyPy (nor Jython nor IronPython). It also means that
143 is not reliable or timely in PyPy (nor Jython nor IronPython). It also means that
137144 **weak references** may stay alive for a bit longer than expected. This
138145 makes "weak proxies" (as returned by ``weakref.proxy()``) somewhat less
139146 useful: they will appear to stay alive for a bit longer in PyPy, and
314321
315322 - ``complex``
316323
324 - ``str`` (empty or single-character strings only)
325
326 - ``unicode`` (empty or single-character strings only)
327
328 - ``tuple`` (empty tuples only)
329
330 - ``frozenset`` (empty frozenset only)
331
317332 This change requires some changes to ``id`` as well. ``id`` fulfills the
318333 following condition: ``x is y <=> id(x) == id(y)``. Therefore ``id`` of the
319334 above types will return a value that is computed from the argument, and can
320335 thus be larger than ``sys.maxint`` (i.e. it can be an arbitrary long).
321336
322 Notably missing from the list above are ``str`` and ``unicode``. If your
323 code relies on comparing strings with ``is``, then it might break in PyPy.
337 Note that strings of length 2 or greater can be equal without being
338 identical. Similarly, ``x is (2,)`` is not necessarily true even if
339 ``x`` contains a tuple and ``x == (2,)``. The uniqueness rules apply
340 only to the particular cases described above. The ``str``, ``unicode``,
341 ``tuple`` and ``frozenset`` rules were added in PyPy 5.4; before that, a
342 test like ``if x is "?"`` or ``if x is ()`` could fail even if ``x`` was
343 equal to ``"?"`` or ``()``. The new behavior added in PyPy 5.4 is
344 closer to CPython's, which caches precisely the empty tuple/frozenset,
345 and (generally but not always) the strings and unicodes of length <= 1.
324346
325347 Note that for floats there "``is``" only one object per "bit pattern"
326348 of the float. So ``float('nan') is float('nan')`` is true on PyPy,
334334
335335 This will disable SELinux's protection and allow PyPy to configure correctly.
336336 Be sure to enable it again if you need it!
337
338
339 How should I report a bug?
340 --------------------------
341
342 Our bug tracker is here: https://bitbucket.org/pypy/pypy/issues/
343
344 Missing features or incompatibilities with CPython are considered
345 bugs, and they are welcome. (See also our list of `known
346 incompatibilities`__.)
347
348 .. __: http://pypy.org/compat.html
349
350 For bugs of the kind "I'm getting a PyPy crash or a strange
351 exception", please note that: **We can't do anything without
352 reproducing the bug ourselves**. We cannot do anything with
353 tracebacks from gdb, or core dumps. This is not only because the
354 standard PyPy is compiled without debug symbols. The real reason is
355 that a C-level traceback is usually of no help at all in PyPy.
356 Debugging PyPy can be annoying.
357
358 `This is a clear and useful bug report.`__ (Admittedly, sometimes
359 the problem is really hard to reproduce, but please try to.)
360
361 .. __: https://bitbucket.org/pypy/pypy/issues/2363/segfault-in-gc-pinned-object-in
362
363 In more details:
364
365 * First, please give the exact PyPy version, and the OS.
366
367 * It might help focus our search if we know if the bug can be
368 reproduced on a "``pypy --jit off``" or not. If "``pypy --jit
369 off``" always works, then the problem might be in the JIT.
370 Otherwise, we know we can ignore that part.
371
372 * If you got the bug using only Open Source components, please give a
373 step-by-step guide that we can follow to reproduce the problem
374 ourselves. Don't assume we know anything about any program other
375 than PyPy. We would like a guide that we can follow point by point
376 (without guessing or having to figure things out)
377 on a machine similar to yours, starting from a bare PyPy, until we
378 see the same problem. (If you can, you can try to reduce the number
379 of steps and the time it needs to run, but that is not mandatory.)
380
381 * If the bug involves Closed Source components, or just too many Open
382 Source components to install them all ourselves, then maybe you can
383 give us some temporary ssh access to a machine where the bug can be
384 reproduced. Or, maybe we can download a VirtualBox or VMWare
385 virtual machine where the problem occurs.
386
387 * If giving us access would require us to use tools other than ssh,
388 make appointments, or sign a NDA, then we can consider a commerical
389 support contract for a small sum of money.
390
391 * If even that is not possible for you, then sorry, we can't help.
392
393 Of course, you can try to debug the problem yourself, and we can help
394 you get started if you ask on the #pypy IRC channel, but be prepared:
395 debugging an annoying PyPy problem usually involves quite a lot of gdb
396 in auto-generated C code, and at least some knowledge about the
397 various components involved, from PyPy's own RPython source code to
398 the GC and possibly the JIT.
1313 Defaults to 1/2 of your cache or ``4M``.
1414 Small values (like 1 or 1KB) are useful for debugging.
1515
16 ``PYPY_GC_NURSERY_CLEANUP``
17 The interval at which nursery is cleaned up. Must
18 be smaller than the nursery size and bigger than the
19 biggest object we can allotate in the nursery.
16 ``PYPY_GC_NURSERY_DEBUG``
17 If set to non-zero, will fill nursery with garbage, to help
18 debugging.
2019
2120 ``PYPY_GC_INCREMENT_STEP``
2221 The size of memory marked during the marking step. Default is size of
6160 use.
6261 Values are ``0`` (off), ``1`` (on major collections) or ``2`` (also
6362 on minor collections).
63
64 ``PYPY_GC_MAX_PINNED``
65 The maximal number of pinned objects at any point in time. Defaults
66 to a conservative value depending on nursery size and maximum object
67 size inside the nursery. Useful for debugging by setting it to 0.
55
66 .. toctree::
77
8 release-pypy2.7-v5.4.0.rst
9 release-pypy2.7-v5.3.1.rst
810 release-pypy2.7-v5.3.0.rst
911 release-5.1.1.rst
1012 release-5.1.0.rst
66 .. toctree::
77
88 whatsnew-head.rst
9 whatsnew-pypy2-5.4.0.rst
10 whatsnew-pypy2-5.3.1.rst
911 whatsnew-pypy2-5.3.0.rst
1012 whatsnew-5.1.0.rst
1113 whatsnew-5.0.0.rst
3838 library.
3939
4040 If you want to install 3rd party libraries, the most convenient way is
41 to install pip_ (unless you want to install virtualenv as explained
42 below; then you can directly use pip inside virtualenvs):
41 to install pip_ using ensurepip_ (unless you want to install virtualenv as
42 explained below; then you can directly use pip inside virtualenvs):
4343
4444 .. code-block:: console
4545
46 $ curl -O https://bootstrap.pypa.io/get-pip.py
47 $ ./pypy-2.1/bin/pypy get-pip.py
48 $ ./pypy-2.1/bin/pip install pygments # for example
46 $ ./pypy-xxx/bin/pypy -m ensurepip
47 $ ./pypy-xxx/bin/pip install pygments # for example
4948
50 Third party libraries will be installed in ``pypy-2.1/site-packages``, and
51 the scripts in ``pypy-2.1/bin``.
49 Third party libraries will be installed in ``pypy-xxx/site-packages``, and
50 the scripts in ``pypy-xxx/bin``.
5251
5352
5453 Installing using virtualenv
6059 checkout::
6160
6261 # from a tarball
63 $ virtualenv -p /opt/pypy-c-jit-41718-3fb486695f20-linux/bin/pypy my-pypy-env
62 $ virtualenv -p /opt/pypy-xxx/bin/pypy my-pypy-env
6463
6564 # from the mercurial checkout
6665 $ virtualenv -p /path/to/pypy/pypy/translator/goal/pypy-c my-pypy-env
6867 Note that bin/python is now a symlink to bin/pypy.
6968
7069 .. _pip: http://pypi.python.org/pypi/pip
71
70 .. _ensurepip: https://docs.python.org/2.7/library/ensurepip.html
7271
7372 Building PyPy yourself
7473 ~~~~~~~~~~~~~~~~~~~~~~
00 ======
11 pypy
22 ======
3
4 .. note: this is turned into a regular man page "pypy.1" by
5 doing "make man" in pypy/doc/
36
47 SYNOPSIS
58 ========
4649
4750 -B
4851 Disable writing bytecode (``.pyc``) files.
52
53 -X track-resources
54 Produce a ``ResourceWarning`` whenever a file or socket is closed by the
55 garbage collector.
4956
5057 --version
5158 Print the PyPy version.
5656 --------------
5757
5858 Our cpyext C-API compatiblity layer can now run upstream NumPy unmodified.
59 Release PyPy2.7-v5.3 still fails about 200 of the ~6000 test in the NumPy
59 Release PyPy2.7-v5.4 still fails about 60 of the ~6000 test in the NumPy
6060 test suite. We could use help analyzing the failures and fixing them either
6161 as patches to upstream NumPy, or as fixes to PyPy.
6262
175175 * Reduce the size of generated code by using the same function objects in
176176 all generated subclasses
177177
178 * Share cpyext Py* function wrappers according to the signature, shrining the
179 translated libpypy.so by about
178 * Share cpyext Py* function wrappers according to the signature, shrinking the
179 translated libpypy.so by about 10% (measured without the JIT)
180180
181181 * Compile c snippets with -Werror, and fix warnings it exposed
182182
0 ==========
1 PyPy 5.3.1
2 ==========
3
4 We have released a bugfix for PyPy2.7-v5.3.0, released last week,
5 due to issues_ reported by users.
6
7 Thanks to those who reported the issues.
8
9 .. _issues: http://doc.pypy.org/en/latest/whatsnew-pypy2-5.3.1.html
10
11 What is PyPy?
12 =============
13
14 PyPy is a very compliant Python interpreter, almost a drop-in replacement for
15 CPython 2.7. It's fast (`PyPy and CPython 2.7.x`_ performance comparison)
16 due to its integrated tracing JIT compiler.
17
18 We also welcome developers of other
19 `dynamic languages`_ to see what RPython can do for them.
20
21 This release supports:
22
23 * **x86** machines on most common operating systems
24 (Linux 32/64, Mac OS X 64, Windows 32, OpenBSD, FreeBSD),
25
26 * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
27
28 * big- and little-endian variants of **PPC64** running Linux,
29
30 * **s390x** running Linux
31
32 .. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
33 .. _`dynamic languages`: http://pypyjs.org
34
35 Please update, and continue to help us make PyPy better.
36
37 Cheers
38
39 The PyPy Team
40
0 ============
1 PyPy2.7 v5.4
2 ============
3
4 We have released PyPy2.7 v5.4, a little under two months after PyPy2.7 v5.3.
5 This new PyPy2.7 release includes further improvements to our C-API compatability layer (cpyext), enabling us to pass over 99% of the upstream
6 numpy `test suite`_. We updated built-in cffi_ support to version 1.8,
7 which now supports the "limited API" mode for c-extensions on
8 CPython >=3.2.
9
10 We improved tooling for the PyPy JIT_, and expanded VMProf
11 support to OpenBSD and Dragon Fly BSD
12
13 As always, this release fixed many issues and bugs raised by the
14 growing community of PyPy users.
15
16 XXXXX MORE ???
17
18 You can download the PyPy2.7 v5.4 release here:
19
20 http://pypy.org/download.html
21
22 We would like to thank our donors for the continued support of the PyPy
23 project.
24
25 We would also like to thank our contributors and
26 encourage new people to join the project. PyPy has many
27 layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation
28 improvements, tweaking popular `modules`_ to run on pypy, or general `help`_
29 with making RPython's JIT even better.
30
31 .. _`test suite`: https://bitbucket.org/pypy/pypy/wiki/Adventures%20in%20cpyext%20compatibility
32 .. _cffi: https://cffi.readthedocs.org
33 .. _JIT: https://morepypy.blogspot.com.au/2016/08/pypy-tooling-upgrade-jitviewer-and.html
34 .. _`PyPy`: http://doc.pypy.org
35 .. _`RPython`: https://rpython.readthedocs.org
36 .. _`modules`: http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly
37 .. _`help`: http://doc.pypy.org/en/latest/project-ideas.html
38
39 What is PyPy?
40 =============
41
42 PyPy is a very compliant Python interpreter, almost a drop-in replacement for
43 CPython 2.7. It's fast (`PyPy and CPython 2.7.x`_ performance comparison)
44 due to its integrated tracing JIT compiler.
45
46 We also welcome developers of other `dynamic languages`_ to see what RPython
47 can do for them.
48
49 This release supports:
50
51 * **x86** machines on most common operating systems
52 (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD)
53
54 * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
55
56 * big- and little-endian variants of **PPC64** running Linux,
57
58 * **s390x** running Linux
59
60 .. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
61 .. _`dynamic languages`: http://pypyjs.org
62
63 Other Highlights (since 5.3 released in June 2016)
64 =========================================================
65
66 * New features:
67
68 * Add `sys.{get,set}dlopenflags`
69
70 * Improve CPython compatibility of 'is' for small and empty strings
71
72 * Support for rgc.FinalizerQueue in the Boehm garbage collector
73
74 * (RPython) support spawnv() if it is called in C `_spawnv` on windows
75
76 * Fill in more slots when creating a PyTypeObject from a W_TypeObject,
77 like `__hex__`, `__sub__`, `__pow__`
78
79 * Copy CPython's logic more closely for `isinstance()` and
80 `issubclass()` as well as `type.__instancecheck__()` and
81 `type.__subclasscheck__()`
82
83 * Expose the name of CDLL objects
84
85 * Rewrite the win32 dependencies of `subprocess` to use cffi
86 instead of ctypes
87
88 * Improve the `JIT logging`_ facitilities
89
90 * (RPython) make int * string work
91
92 * Allocate all RPython strings with one extra byte, normally
93 unused. This now allows `ffi.from_buffer(string)` in CFFI with
94 no copy
95
96 * Adds a new commandline option `-X track-resources` that will
97 produce a `ResourceWarning` when the GC closes a file or socket.
98 The traceback for the place where the file or socket was allocated
99 is given as well, which aids finding places where `close()` is
100 missing
101
102 * Add missing `PyObject_Realloc`, `PySequence_GetSlice`
103
104 * `type.__dict__` now returns a `dict_proxy` object, like on CPython.
105 Previously it returned what looked like a regular dict object (but
106 it was already read-only)
107
108 * (RPython) add `rposix.{get,set}_inheritable()`, needed by Python 3.5
109
110 * (RPython) add `rposix_scandir` portably, needed for Python 3.5
111
112 * Support for memoryview attributes (format, itemsize, ...) which also
113 adds support for `PyMemoryView_FromObject`
114
115 * Bug Fixes
116
117 * Reject `mkdir()` in read-only sandbox filesystems
118
119 * Add include guards to pymem.h to enable c++ compilation
120
121 * Fix build breakage on OpenBSD and FreeBSD
122
123 * Support OpenBSD, Dragon Fly BSD in VMProf
124
125 * Fix for `bytearray('').replace('a', 'ab')` for empty strings
126
127 * Sync internal state before calling `PyFile_AsFile()`
128
129 * Allow writing to a char* from `PyString_AsString()` until it is
130 forced, also refactor `PyStringObject` to look like CPython's
131 and allow subclassing `PyString_Type` and `PyUnicode_Type`
132
133 * Rpython rffi's socket(2) wrapper did not preserve errno
134
135 * Refactor `PyTupleObject` to look like CPython's and allow
136 subclassing `PyTuple_Type`
137
138 * Allow c-level assignment to a function pointer in a C-API
139 user-defined type after calling PyTypeReady by retrieving
140 a pointer to the function via offsets
141 rather than storing the function pointer itself
142
143 * Use `madvise(MADV_FREE)`, or if that doesn't exist
144 `MADV_DONTNEED` on freed arenas to release memory back to the
145 OS for resource monitoring
146
147 * Fix overflow detection in conversion of float to 64-bit integer
148 in timeout argument to various thread/threading primitives
149
150 * Fix win32 outputting `\r\r\n` in some cases
151
152 * Make `hash(-1)` return -2, as CPython does, and fix all the
153 ancilary places this matters
154
155 * Issues reported with our previous release were resolved_ after
156 reports from users on our issue tracker at
157 https://bitbucket.org/pypy/pypy/issues or on IRC at #pypy
158
159 * Fix `PyNumber_Check()` to behave more like CPython
160
161 * (VMProf) Try hard to not miss any Python-level frame in the
162 captured stacks, even if there is metainterp or blackhole interp
163 involved. Also fix the stacklet (greenlet) support
164
165 * Fix a critical JIT bug where `raw_malloc` -equivalent functions
166 lost the additional flags
167
168 * Fix the mapdict cache for subclasses of builtin types that
169 provide a dict
170
171 * Performance improvements:
172
173 * Add a before_call()-like equivalent before a few operations like
174 `malloc_nursery`, to move values from registers into other registers
175 instead of to the stack.
176
177 * More tightly pack the stack when calling with `release gil`
178
179 * Support `int_floordiv()`, `int_mod()` in the JIT more efficiently
180 and add `rarithmetic.int_c_div()`, `rarithmetic.int_c_mod()` as
181 explicit interfaces. Clarify that `int_floordiv()` does python-style
182 rounding, unlike `llop.int_floordiv()`.
183
184 * Use `ll_assert` (more often) in incminimark
185
186 * (Testing) Simplify handling of interp-level tests and make it
187 more forward-compatible. Don't use interp-level RPython
188 machinery to test building app-level extensions in cpyext
189
190 * Constant-fold `ffi.offsetof("structname", "fieldname")` in cffi
191 backend
192
193 * Avoid a case in the JIT, where successive guard failures in
194 the same Python function end up as successive levels of
195 RPython functions, eventually exhausting the stack, while at
196 app-level the traceback is very short
197
198 * Check for NULL returns from calls to the raw-malloc and raise,
199 rather than a guard
200
201 * Improve `socket.recvfrom()` so that it copies less if possible
202
203 * When generating C code, inline `goto` to blocks with only one
204 predecessor, generating less lines of code
205
206 * When running the final backend-optimization phase before emitting
207 C code, constant-fold calls to we_are_jitted to return False. This
208 makes the generated C code a few percent smaller
209
210 * Refactor the `uid_t/gid_t` handling in `rlib.rposix` and in
211 `interp_posix.py`, based on the clean-up of CPython 2.7.x
212
213 .. _`JIT logging`: https://morepypy.blogspot.com/2016/08/pypy-tooling-upgrade-jitviewer-and.html
214 .. _resolved: http://doc.pypy.org/en/latest/whatsnew-5.4.0.html
215
216 Please update, and continue to help us make PyPy better.
217
218 Cheers
0 =========================
1 What's new in PyPy2.7 5.3+
2 =========================
0 ==========================
1 What's new in PyPy2.7 5.4+
2 ==========================
33
4 .. this is a revision shortly after release-pypy2.7-v5.3
5 .. startrev: 873218a739f1
4 .. this is a revision shortly after release-pypy2.7-v5.4
5 .. startrev: 522736f816dc
66
7
0 ===========================
1 What's new in PyPy2.7 5.3.1
2 ===========================
3
4 .. this is a revision shortly after release-pypy2.7-v5.3.0
5 .. startrev: f4d726d1a010
6
7
8 A bug-fix release, merging these changes:
9
10 * Add include guards to pymem.h, fixes issue #2321
11
12 * Make vmprof build on OpenBSD, from pull request #456
13
14 * Fix ``bytearray('').replace('a', 'ab')``, issue #2324
0 =========================
1 What's new in PyPy2.7 5.4
2 =========================
3
4 .. this is a revision shortly after release-pypy2.7-v5.3
5 .. startrev: 873218a739f1
6
7 .. 418b05f95db5
8 Improve CPython compatibility for ``is``. Now code like ``if x is ():``
9 works the same way as it does on CPython. See http://pypy.readthedocs.io/en/latest/cpython_differences.html#object-identity-of-primitive-values-is-and-id .
10
11 .. pull request #455
12 Add sys.{get,set}dlopenflags, for cpyext extensions.
13
14 .. branch: fix-gen-dfa
15
16 Resolves an issue with the generator script to build the dfa for Python syntax.
17
18 .. branch: z196-support
19
20 Fixes a critical issue in the register allocator and extends support on s390x.
21 PyPy runs and translates on the s390x revisions z10 (released February 2008, experimental)
22 and z196 (released August 2010) in addition to zEC12 and z13.
23 To target e.g. z196 on a zEC12 machine supply CFLAGS="-march=z196" to your shell environment.
24
25 .. branch: s390x-5.3-catchup
26
27 Implement the backend related changes for s390x.
28
29 .. branch: incminimark-ll_assert
30 .. branch: vmprof-openbsd
31
32 .. branch: testing-cleanup
33
34 Simplify handling of interp-level tests and make it more forward-
35 compatible.
36
37 .. branch: pyfile-tell
38 Sync w_file with the c-level FILE* before returning FILE* in PyFile_AsFile
39
40 .. branch: rw-PyString_AS_STRING
41 Allow rw access to the char* returned from PyString_AS_STRING, also refactor
42 PyStringObject to look like cpython's and allow subclassing PyString_Type and
43 PyUnicode_Type
44
45 .. branch: save_socket_errno
46
47 Bug fix: if ``socket.socket()`` failed, the ``socket.error`` did not show
48 the errno of the failing system call, but instead some random previous
49 errno.
50
51 .. branch: PyTuple_Type-subclass
52
53 Refactor PyTupleObject to look like cpython's and allow subclassing
54 PyTuple_Type
55
56 .. branch: call-via-pyobj
57
58 Use offsets from PyTypeObject to find actual c function to call rather than
59 fixed functions, allows function override after PyType_Ready is called
60
61 .. branch: issue2335
62
63 Avoid exhausting the stack in the JIT due to successive guard
64 failures in the same Python function ending up as successive levels of
65 RPython functions, while at app-level the traceback is very short
66
67 .. branch: use-madv-free
68
69 Try harder to memory to the OS. See e.g. issue #2336. Note that it does
70 not show up as a reduction of the VIRT column in ``top``, and the RES
71 column might also not show the reduction, particularly on Linux >= 4.5 or
72 on OS/X: it uses MADV_FREE, which only marks the pages as returnable to
73 the OS if the memory is low.
74
75 .. branch: cpyext-slotdefs2
76
77 Fill in more slots when creating a PyTypeObject from a W_TypeObject
78 More slots are still TBD, like tp_print and richcmp
79
80 .. branch: json-surrogates
81
82 Align json module decode with the cpython's impl, fixes issue 2345
83
84 .. branch: issue2343
85
86 Copy CPython's logic more closely for handling of ``__instancecheck__()``
87 and ``__subclasscheck__()``. Fixes issue 2343.
88
89 .. branch: msvcrt-cffi
90
91 Rewrite the Win32 dependencies of 'subprocess' to use cffi instead
92 of ctypes. This avoids importing ctypes in many small programs and
93 scripts, which in turn avoids enabling threads (because ctypes
94 creates callbacks at import time, and callbacks need threads).
95
96 .. branch: new-jit-log
97
98 The new logging facility that integrates with and adds features to vmprof.com.
99
100 .. branch: jitlog-32bit
101
102 Resolve issues to use the new logging facility on a 32bit system
103
104 .. branch: ep2016sprint
105
106 Trying harder to make hash(-1) return -2, like it does on CPython
107
108 .. branch: jitlog-exact-source-lines
109
110 Log exact line positions in debug merge points.
111
112 .. branch: null_byte_after_str
113
114 Allocate all RPython strings with one extra byte, normally unused.
115 It is used to hold a final zero in case we need some ``char *``
116 representation of the string, together with checks like ``not
117 can_move()`` or object pinning. Main new thing that this allows:
118 ``ffi.from_buffer(string)`` in CFFI. Additionally, and most
119 importantly, CFFI calls that take directly a string as argument don't
120 copy the string any more---this is like CFFI on CPython.
121
122 .. branch: resource_warning
123
124 Add a new command line option -X track-resources which will produce
125 ResourceWarnings when the GC closes unclosed files and sockets.
126
127 .. branch: cpyext-realloc
128
129 Implement PyObject_Realloc
130
131 .. branch: inline-blocks
132
133 Improve a little bit the readability of the generated C code
134
135 .. branch: improve-vmprof-testing
136
137 Improved vmprof support: now tries hard to not miss any Python-level
138 frame in the captured stacks, even if there is the metainterp or
139 blackhole interp involved. Also fix the stacklet (greenlet) support.
140
141 .. branch: py2-mappingproxy
142
143 ``type.__dict__`` now returns a ``dict_proxy`` object, like on CPython.
144 Previously it returned what looked like a regular dict object (but it
145 was already read-only).
146
147
148 .. branch: const-fold-we-are-jitted
149
150 Reduce the size of the generated C code by constant-folding ``we_are_jitted``
151 in non-jitcode.
152
153 .. branch: memoryview-attributes
154
155 Support for memoryview attributes (format, itemsize, ...).
156 Extends the cpyext emulation layer.
157
158 .. branch: redirect-assembler-jitlog
159
160 Log more information to properly rebuild the redirected traces in jitviewer.
161
162 .. branch: cpyext-subclass
163
164 Copy Py_TPFLAGS_CHECKTYPES, Py_TPFLAGS_HAVE_INPLACEOPS when inheriting
2323 -V : print the Python version number and exit (also --version)
2424 -W arg : warning control; arg is action:message:category:module:lineno
2525 also PYTHONWARNINGS=arg
26 -X arg : set implementation-specific option
2627 file : program read from script file
2728 - : program read from stdin (default; interactive mode if a tty)
2829 arg ...: arguments passed to program in sys.argv[1:]
30
2931 PyPy options and arguments:
3032 --info : print translation information about this PyPy executable
33 -X track-resources : track the creation of files and sockets and display
34 a warning if they are not closed explicitly
3135 """
3236 # Missing vs CPython: PYTHONHOME, PYTHONCASEOK
3337 USAGE2 = """
227231 else:
228232 import pypyjit
229233 pypyjit.set_param(jitparam)
234
235 def set_runtime_options(options, Xparam, *args):
236 if Xparam == 'track-resources':
237 sys.pypy_set_track_resources(True)
238 else:
239 print >> sys.stderr, 'usage: %s -X [options]' % (get_sys_executable(),)
240 print >> sys.stderr, '[options] can be: track-resources'
241 raise SystemExit
230242
231243 class CommandLineError(Exception):
232244 pass
403415 '--info': (print_info, None),
404416 '--jit': (set_jit_option, Ellipsis),
405417 '-funroll-loops': (funroll_loops, None),
418 '-X': (set_runtime_options, Ellipsis),
406419 '--': (end_options, None),
407420 }
408421
386386 def _stacksize(self, blocks):
387387 """Compute co_stacksize."""
388388 for block in blocks:
389 block.initial_depth = 0
389 block.initial_depth = -99
390 blocks[0].initial_depth = 0
390391 # Assumes that it is sufficient to walk the blocks in 'post-order'.
391392 # This means we ignore all back-edges, but apart from that, we only
392393 # look into a block when all the previous blocks have been done.
405406
406407 def _do_stack_depth_walk(self, block):
407408 depth = block.initial_depth
409 if depth == -99: # this block is never reached, skip
410 return 0
408411 for instr in block.instructions:
409412 depth += _opcode_stack_effect(instr.opcode, instr.arg)
413 assert depth >= 0
410414 if depth >= self._max_depth:
411415 self._max_depth = depth
412416 jump_op = instr.opcode
107107 return getattr(space, name)(operand)
108108 return do_fold
109109
110 def _fold_pow(space, left, right):
111 return space.pow(left, right, space.w_None)
110 def _fold_pow(space, w_left, w_right):
111 # don't constant-fold if "w_left" and "w_right" are integers and
112 # the estimated bit length of the power is unreasonably large
113 space.appexec([w_left, w_right], """(left, right):
114 if isinstance(left, (int, long)) and isinstance(right, (int, long)):
115 if left.bit_length() * right > 5000:
116 raise OverflowError
117 """)
118 return space.pow(w_left, w_right, space.w_None)
112119
113120 def _fold_not(space, operand):
114121 return space.wrap(not space.is_true(operand))
457457 decl = str(decl) + "\n"
458458 yield self.st, decl, 'x', (1, 2, 3, 4)
459459
460 def test_closure_error(self):
460461 source = """if 1:
461462 def f(a):
462463 del a
463464 def x():
464465 a
465466 """
466 exc = py.test.raises(SyntaxError, self.run, source).value
467 assert exc.msg == "Can't delete variable used in nested scopes: 'a'"
467 with py.test.raises(SyntaxError) as excinfo:
468 self.run(source)
469 msg = excinfo.value.msg
470 assert msg == "Can't delete variable used in nested scopes: 'a'"
468471
469472 def test_try_except_finally(self):
470473 yield self.simple_test, """
878881 """
879882 self.simple_test(source, 'ok', 1)
880883
881 def test_remove_docstring(self):
884 @py.test.mark.parametrize('expr, result', [
885 ("f1.__doc__", None),
886 ("f2.__doc__", 'docstring'),
887 ("f2()", 'docstring'),
888 ("f3.__doc__", None),
889 ("f3()", 'bar'),
890 ("C1.__doc__", None),
891 ("C2.__doc__", 'docstring'),
892 ("C3.field", 'not docstring'),
893 ("C4.field", 'docstring'),
894 ("C4.__doc__", 'docstring'),
895 ("C4.__doc__", 'docstring'),
896 ("__doc__", None),])
897 def test_remove_docstring(self, expr, result):
882898 source = '"module_docstring"\n' + """if 1:
883899 def f1():
884900 'docstring'
902918 code_w.remove_docstrings(self.space)
903919 dict_w = self.space.newdict();
904920 code_w.exec_code(self.space, dict_w, dict_w)
905
906 yield self.check, dict_w, "f1.__doc__", None
907 yield self.check, dict_w, "f2.__doc__", 'docstring'
908 yield self.check, dict_w, "f2()", 'docstring'
909 yield self.check, dict_w, "f3.__doc__", None
910 yield self.check, dict_w, "f3()", 'bar'
911 yield self.check, dict_w, "C1.__doc__", None
912 yield self.check, dict_w, "C2.__doc__", 'docstring'
913 yield self.check, dict_w, "C3.field", 'not docstring'
914 yield self.check, dict_w, "C4.field", 'docstring'
915 yield self.check, dict_w, "C4.__doc__", 'docstring'
916 yield self.check, dict_w, "C4.__doc__", 'docstring'
917 yield self.check, dict_w, "__doc__", None
921 self.check(dict_w, expr, result)
918922
919923 def test_assert_skipping(self):
920924 space = self.space
11101114 return d['f'](5)
11111115 """)
11121116 assert 'generator' in space.str_w(space.repr(w_generator))
1113
1117
11141118 def test_list_comprehension(self):
11151119 source = "def f(): [i for i in l]"
11161120 source2 = "def f(): [i for i in l for j in l]"
11511155 counts = self.count_instructions(source)
11521156 assert ops.BUILD_SET not in counts
11531157 assert ops.LOAD_CONST in counts
1158
1159 def test_dont_fold_huge_powers(self):
1160 for source in (
1161 "2 ** 3000", # not constant-folded: too big
1162 "(-2) ** 3000",
1163 ):
1164 source = 'def f(): %s' % source
1165 counts = self.count_instructions(source)
1166 assert ops.BINARY_POWER in counts
1167
1168 for source in (
1169 "2 ** 2000", # constant-folded
1170 "2 ** -3000",
1171 "1.001 ** 3000",
1172 "1 ** 3000.0",
1173 ):
1174 source = 'def f(): %s' % source
1175 counts = self.count_instructions(source)
1176 assert ops.BINARY_POWER not in counts
399399 if not (space.isinstance_w(w_obj, space.w_str) or
400400 space.isinstance_w(w_obj, space.w_unicode)):
401401 raise oefmt(space.w_TypeError,
402 "AST string must be of type str or unicode")
402 "AST string must be of type str or unicode")
403403 return w_obj
404404
405405 def get_field(space, w_node, name, optional):
207207 def buffer_w(self, space, flags):
208208 w_impl = space.lookup(self, '__buffer__')
209209 if w_impl is not None:
210 w_result = space.get_and_call_function(w_impl, self)
210 w_result = space.get_and_call_function(w_impl, self,
211 space.newint(flags))
211212 if space.isinstance_w(w_result, space.w_buffer):
212213 return w_result.buffer_w(space, flags)
213214 raise BufferInterfaceNotFound
215216 def readbuf_w(self, space):
216217 w_impl = space.lookup(self, '__buffer__')
217218 if w_impl is not None:
218 w_result = space.get_and_call_function(w_impl, self)
219 w_result = space.get_and_call_function(w_impl, self,
220 space.newint(space.BUF_FULL_RO))
219221 if space.isinstance_w(w_result, space.w_buffer):
220222 return w_result.readbuf_w(space)
221223 raise BufferInterfaceNotFound
223225 def writebuf_w(self, space):
224226 w_impl = space.lookup(self, '__buffer__')
225227 if w_impl is not None:
226 w_result = space.get_and_call_function(w_impl, self)
228 w_result = space.get_and_call_function(w_impl, self,
229 space.newint(space.BUF_FULL))
227230 if space.isinstance_w(w_result, space.w_buffer):
228231 return w_result.writebuf_w(space)
229232 raise BufferInterfaceNotFound
231234 def charbuf_w(self, space):
232235 w_impl = space.lookup(self, '__buffer__')
233236 if w_impl is not None:
234 w_result = space.get_and_call_function(w_impl, self)
237 w_result = space.get_and_call_function(w_impl, self,
238 space.newint(space.BUF_FULL_RO))
235239 if space.isinstance_w(w_result, space.w_buffer):
236240 return w_result.charbuf_w(space)
237241 raise BufferInterfaceNotFound
10331037 return (None, None)
10341038
10351039 def newlist_bytes(self, list_s):
1036 return self.newlist([self.wrap(s) for s in list_s])
1040 return self.newlist([self.newbytes(s) for s in list_s])
10371041
10381042 def newlist_unicode(self, list_u):
10391043 return self.newlist([self.wrap(u) for u in list_u])
15321536 # unclear if there is any use at all for getting the bytes in
15331537 # the unicode buffer.)
15341538 try:
1535 return self.str_w(w_obj)
1539 return self.bytes_w(w_obj)
15361540 except OperationError as e:
15371541 if not e.match(self, self.w_TypeError):
15381542 raise
17011705 raise oefmt(self.w_OverflowError,
17021706 "Python int too large for C unsigned short")
17031707 return value
1708
1709 def c_uid_t_w(self, w_obj):
1710 # xxx assumes that uid_t and gid_t are a C unsigned int.
1711 # Equivalent to space.c_uint_w(), with the exception that
1712 # it also accepts -1 and converts that to UINT_MAX, which
1713 # is (uid_t)-1. And values smaller than -1 raise
1714 # OverflowError, not ValueError.
1715 try:
1716 return self.c_uint_w(w_obj)
1717 except OperationError as e:
1718 if e.match(self, self.w_ValueError):
1719 # ValueError: cannot convert negative integer to unsigned
1720 if self.int_w(w_obj) == -1:
1721 return UINT_MAX
1722 raise oefmt(self.w_OverflowError,
1723 "user/group id smaller than minimum (-1)")
1724 raise
17041725
17051726 def truncatedint_w(self, w_obj, allow_conversion=True):
17061727 # Like space.gateway_int_w(), but return the integer truncated
17621783 import _warnings
17631784 _warnings.warn(msg, warningcls, stacklevel=stacklevel)
17641785 """)
1786
1787 def resource_warning(self, w_msg, w_tb):
1788 self.appexec([w_msg, w_tb],
1789 """(msg, tb):
1790 import sys
1791 print >> sys.stderr, msg
1792 if tb:
1793 print >> sys.stderr, "Created at (most recent call last):"
1794 print >> sys.stderr, tb
1795 """)
1796
1797 def format_traceback(self):
1798 # we need to disable track_resources before calling the traceback
1799 # module. Else, it tries to open more files to format the traceback,
1800 # the file constructor will call space.format_traceback etc., in an
1801 # inifite recursion
1802 flag = self.sys.track_resources
1803 self.sys.track_resources = False
1804 try:
1805 return self.appexec([],
1806 """():
1807 import sys, traceback
1808 # the "1" is because we don't want to show THIS code
1809 # object in the traceback
1810 try:
1811 f = sys._getframe(1)
1812 except ValueError:
1813 # this happens if you call format_traceback at the very beginning
1814 # of startup, when there is no bottom code object
1815 return '<no stacktrace available>'
1816 return "".join(traceback.format_stack(f))
1817 """)
1818 finally:
1819 self.sys.track_resources = flag
17651820
17661821
17671822 class AppExecCache(SpaceCache):
166166 def visit_c_ushort(self, el, app_sig):
167167 self.checked_space_method(el, app_sig)
168168
169 def visit_c_uid_t(self, el, app_sig):
170 self.checked_space_method(el, app_sig)
171
169172 def visit_truncatedint_w(self, el, app_sig):
170173 self.checked_space_method(el, app_sig)
171174
292295
293296 def visit_c_ushort(self, typ):
294297 self.run_args.append("space.c_ushort_w(%s)" % (self.scopenext(),))
298
299 def visit_c_uid_t(self, typ):
300 self.run_args.append("space.c_uid_t_w(%s)" % (self.scopenext(),))
295301
296302 def visit_truncatedint_w(self, typ):
297303 self.run_args.append("space.truncatedint_w(%s)" % (self.scopenext(),))
438444
439445 def visit_c_ushort(self, typ):
440446 self.unwrap.append("space.c_ushort_w(%s)" % (self.nextarg(),))
447
448 def visit_c_uid_t(self, typ):
449 self.unwrap.append("space.c_uid_t_w(%s)" % (self.nextarg(),))
441450
442451 def visit_truncatedint_w(self, typ):
443452 self.unwrap.append("space.truncatedint_w(%s)" % (self.nextarg(),))
586595
587596 # First extract the signature from the (CPython-level) code object
588597 from pypy.interpreter import pycode
589 argnames, varargname, kwargname = pycode.cpython_code_signature(func.func_code)
598 sig = pycode.cpython_code_signature(func.func_code)
599 argnames = sig.argnames
600 varargname = sig.varargname
601 kwargname = sig.kwargname
590602 self._argnames = argnames
591603
592604 if unwrap_spec is None:
610622 app_sig = SignatureBuilder(func)
611623
612624 UnwrapSpec_Check(orig_sig).apply_over(unwrap_spec, app_sig)
613 self.sig = argnames, varargname, kwargname = app_sig.signature()
625 self.sig = app_sig.signature()
626 argnames = self.sig.argnames
627 varargname = self.sig.varargname
614628
615629 self.minargs = len(argnames)
616630 if varargname:
941955 defs_w.append(space.wrap(defaultval))
942956 if self._code._unwrap_spec:
943957 UNDEFINED = object()
944 alldefs_w = [UNDEFINED] * len(self._code.sig[0])
958 alldefs_w = [UNDEFINED] * len(self._code.sig.argnames)
945959 if defs_w:
946960 alldefs_w[-len(defs_w):] = defs_w
947961 code = self._code
958972 assert isinstance(w_default, W_Root)
959973 assert argname.startswith('w_')
960974 argname = argname[2:]
961 j = self._code.sig[0].index(argname)
975 j = self._code.sig.argnames.index(argname)
962976 assert alldefs_w[j] in (UNDEFINED, None)
963977 alldefs_w[j] = w_default
964978 first_defined = 0
3636
3737 # cpython_code_signature helper
3838 def cpython_code_signature(code):
39 "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
39 """Return a Signature instance."""
4040 argcount = code.co_argcount
4141 varnames = code.co_varnames
4242 assert argcount >= 0 # annotator hint
407407 w(self.co_nlocals),
408408 w(self.co_stacksize),
409409 w(self.co_flags),
410 w(self.co_code),
410 space.newbytes(self.co_code),
411411 space.newtuple(self.co_consts_w),
412412 space.newtuple(self.co_names_w),
413413 space.newtuple([w(v) for v in self.co_varnames]),
414414 w(self.co_filename),
415415 w(self.co_name),
416416 w(self.co_firstlineno),
417 w(self.co_lnotab),
417 space.newbytes(self.co_lnotab),
418418 space.newtuple([w(v) for v in self.co_freevars]),
419419 space.newtuple([w(v) for v in self.co_cellvars]),
420420 w(self.magic),
1212 # PYPY Modification: removed the EMPTY class as it's not needed here
1313
1414
15 # PYPY Modification: we don't need a particuliar DEFAULT class here
16 # a simple None works fine.
17 # (Having a DefaultClass inheriting from str makes
18 # the annotator crash)
19 DEFAULT = "\00default" # XXX hack, the rtyper does not support dict of with str|None keys
20 # anyway using dicts doesn't seem the best final way to store these char indexed tables
15 # PYPY Modification: DEFAULT is a singleton, used only in the pre-RPython
16 # dicts (see pytokenize.py). Then DFA.__init__() turns these dicts into
17 # more compact strings.
18 DEFAULT = object()
19
2120 # PYPY Modification : removed all automata functions (any, maybe,
2221 # newArcPair, etc.)
2322
190190 newArcPair(states, EMPTY),
191191 pseudoExtras, number, funny, contStr, name))
192192 dfaStates, dfaAccepts = nfaToDfa(states, *pseudoToken)
193 return DFA(dfaStates, dfaAccepts)
193 return DFA(dfaStates, dfaAccepts), dfaStates
194194
195195 # ______________________________________________________________________
196196
204204 newArcPair(states, DEFAULT),
205205 any(states, notGroupStr(states, "'\\")))),
206206 newArcPair(states, "'"))
207 singleDFA = DFA(*nfaToDfa(states, *single))
207 states, accepts = nfaToDfa(states, *single)
208 singleDFA = DFA(states, accepts)
209 states_singleDFA = states
208210 states = []
209211 double = chain(states,
210212 any(states, notGroupStr(states, '"\\')),
214216 newArcPair(states, DEFAULT),
215217 any(states, notGroupStr(states, '"\\')))),
216218 newArcPair(states, '"'))
217 doubleDFA = DFA(*nfaToDfa(states, *double))
219 states, accepts = nfaToDfa(states, *double)
220 doubleDFA = DFA(states, accepts)
221 states_doubleDFA = states
218222 states = []
219223 single3 = chain(states,
220224 any(states, notGroupStr(states, "'\\")),
229233 notChainStr(states, "''"))),
230234 any(states, notGroupStr(states, "'\\")))),
231235 chainStr(states, "'''"))
232 single3DFA = NonGreedyDFA(*nfaToDfa(states, *single3))
236 states, accepts = nfaToDfa(states, *single3)
237 single3DFA = NonGreedyDFA(states, accepts)
238 states_single3DFA = states
233239 states = []
234240 double3 = chain(states,
235241 any(states, notGroupStr(states, '"\\')),
244250 notChainStr(states, '""'))),
245251 any(states, notGroupStr(states, '"\\')))),
246252 chainStr(states, '"""'))
247 double3DFA = NonGreedyDFA(*nfaToDfa(states, *double3))
248 map = {"'" : singleDFA,
249 '"' : doubleDFA,
253 states, accepts = nfaToDfa(states, *double3)
254 double3DFA = NonGreedyDFA(states, accepts)
255 states_double3DFA = states
256 map = {"'" : (singleDFA, states_singleDFA),
257 '"' : (doubleDFA, states_doubleDFA),
250258 "r" : None,
251259 "R" : None,
252260 "u" : None,
256264 for uniPrefix in ("", "u", "U", "b", "B", ):
257265 for rawPrefix in ("", "r", "R"):
258266 prefix = uniPrefix + rawPrefix
259 map[prefix + "'''"] = single3DFA
260 map[prefix + '"""'] = double3DFA
267 map[prefix + "'''"] = (single3DFA, states_single3DFA)
268 map[prefix + '"""'] = (double3DFA, states_double3DFA)
261269 return map
262270
263271 # ______________________________________________________________________
264272
265 def output(name, dfa_class, dfa):
273 def output(name, dfa_class, dfa, states):
266274 import textwrap
275 lines = []
267276 i = 0
268277 for line in textwrap.wrap(repr(dfa.accepts), width = 50):
269278 if i == 0:
270 print "accepts =", line
279 lines.append("accepts = ")
271280 else:
272 print " ", line
281 lines.append(" ")
282 lines.append(line)
283 lines.append("\n")
273284 i += 1
274285 import StringIO
275 print "states = ["
276 for numstate, state in enumerate(dfa.states):
277 print " #", numstate
286 lines.append("states = [\n")
287 for numstate, state in enumerate(states):
288 lines.append(" # ")
289 lines.append(str(numstate))
290 lines.append('\n')
278291 s = StringIO.StringIO()
279292 i = 0
280293 for k, v in sorted(state.items()):
281294 i += 1
282 if k == '\x00default':
295 if k == DEFAULT:
283296 k = "automata.DEFAULT"
284297 else:
285298 k = repr(k)
297310 for line in text:
298311 line = line.replace('::', ': ')
299312 if i == 0:
300 print ' {' + line
313 lines.append(' {')
301314 else:
302 print ' ' + line
315 lines.append(' ')
316 lines.append(line)
317 lines.append('\n')
303318 i += 1
304 print " ]"
305 print "%s = automata.%s(states, accepts)" % (name, dfa_class)
306 print
319 lines.append(" ]\n")
320 lines.append("%s = automata.%s(states, accepts)\n" % (name, dfa_class))
321 return ''.join(lines)
307322
308323 def main ():
309 pseudoDFA = makePyPseudoDFA()
310 output("pseudoDFA", "DFA", pseudoDFA)
324 pseudoDFA, states_pseudoDFA = makePyPseudoDFA()
325 print output("pseudoDFA", "DFA", pseudoDFA, states_pseudoDFA)
311326 endDFAMap = makePyEndDFAMap()
312 output("double3DFA", "NonGreedyDFA", endDFAMap['"""'])
313 output("single3DFA", "NonGreedyDFA", endDFAMap["'''"])
314 output("singleDFA", "DFA", endDFAMap["'"])
315 output("doubleDFA", "DFA", endDFAMap['"'])
327 dfa, states = endDFAMap['"""']
328 print output("double3DFA", "NonGreedyDFA", dfa, states)
329 dfa, states = endDFAMap["'''"]
330 print output("single3DFA", "NonGreedyDFA", dfa, states)
331 dfa, states = endDFAMap["'"]
332 print output("singleDFA", "DFA", dfa, states)
333 dfa, states = endDFAMap["\""]
334 print output("doubleDFA", "DFA", dfa, states)
316335
317336 # ______________________________________________________________________
318337
8080 if need_encoding:
8181 enc = encoding
8282 v = PyString_DecodeEscape(space, substr, 'strict', enc)
83 return space.wrap(v)
83 return space.newbytes(v)
8484
8585 def decode_unicode_utf8(space, s, ps, q):
8686 # ****The Python 2.7 version, producing UTF-32 escapes****
0 from pypy.interpreter.pyparser.automata import DFA, DEFAULT
1 from pypy.interpreter.pyparser.genpytokenize import output
2
3 def test_states():
4 states = [{"\x00": 1}, {"\x01": 0}]
5 d = DFA(states[:], [False, True])
6 assert output('test', DFA, d, states) == """\
7 accepts = [False, True]
8 states = [
9 # 0
10 {'\\x00': 1},
11 # 1
12 {'\\x01': 0},
13 ]
14 test = automata.pypy.interpreter.pyparser.automata.DFA(states, accepts)
15 """
5454 if not isinstance(other, Signature):
5555 return NotImplemented
5656 return not self == other
57
58
59 # make it look tuply for its use in the annotator
60
61 def __len__(self):
62 return 3
63
64 def __getitem__(self, i):
65 if i == 0:
66 return self.argnames
67 if i == 1:
68 return self.varargname
69 if i == 2:
70 return self.kwargname
71 raise IndexError
219219 expected = {"no_user_site": True}
220220 self.check(['-c', 'pass'], {}, sys_argv=['-c'], run_command='pass', **expected)
221221
222 def test_track_resources(self, monkeypatch):
223 myflag = [False]
224 def pypy_set_track_resources(flag):
225 myflag[0] = flag
226 monkeypatch.setattr(sys, 'pypy_set_track_resources', pypy_set_track_resources, raising=False)
227 self.check(['-X', 'track-resources'], {}, sys_argv=[''], run_stdin=True)
228 assert myflag[0] == True
222229
223230 class TestInteraction:
224231 """
10731080 # assert it did not crash
10741081 finally:
10751082 sys.path[:] = old_sys_path
1076
4444 assert sig.find_argname("b") == 1
4545 assert sig.find_argname("c") == 2
4646 assert sig.find_argname("d") == -1
47
48 def test_tuply(self):
49 sig = Signature(["a", "b", "c"], "d", "e")
50 x, y, z = sig
51 assert x == ["a", "b", "c"]
52 assert y == "d"
53 assert z == "e"
5447
5548 class dummy_wrapped_dict(dict):
5649 def __nonzero__(self):
426426 space.finish()
427427 # assert that we reach this point without getting interrupted
428428 # by the OperationError(NameError)
429
430 def test_format_traceback(self):
431 from pypy.tool.pytest.objspace import maketestobjspace
432 from pypy.interpreter.gateway import interp2app
433 #
434 def format_traceback(space):
435 return space.format_traceback()
436 #
437 space = maketestobjspace()
438 w_format_traceback = space.wrap(interp2app(format_traceback))
439 w_tb = space.appexec([w_format_traceback], """(format_traceback):
440 def foo():
441 return bar()
442 def bar():
443 return format_traceback()
444 return foo()
445 """)
446 tb = space.str_w(w_tb)
447 expected = '\n'.join([
448 ' File "?", line 6, in anonymous', # this is the appexec code object
449 ' File "?", line 3, in foo',
450 ' File "?", line 5, in bar',
451 ''
452 ])
453 assert tb == expected
202202 name = func.__name__
203203 extra = ', '.join(extraargs)
204204 from pypy.interpreter import pycode
205 argnames, _, _ = pycode.cpython_code_signature(func.func_code)
205 sig = pycode.cpython_code_signature(func.func_code)
206 argnames = sig.argnames
206207 if use_closure:
207208 if argnames[1] == 'space':
208209 args = "closure, space, obj"
4545 raise # propagate other errors
4646 return space.type(w_obj)
4747
48
49 # ---------- isinstance ----------
50
51
52 def p_recursive_isinstance_w(space, w_inst, w_cls):
53 # Copied straight from CPython 2.7. Does not handle 'cls' being a tuple.
54 if (isinstance(w_cls, W_ClassObject) and
55 isinstance(w_inst, W_InstanceObject)):
56 return w_inst.w_class.is_subclass_of(w_cls)
57
58 if space.isinstance_w(w_cls, space.w_type):
59 return p_recursive_isinstance_type_w(space, w_inst, w_cls)
60
61 check_class(space, w_cls, "isinstance() arg 2 must be a class, type,"
62 " or tuple of classes and types")
63 try:
64 w_abstractclass = space.getattr(w_inst, space.wrap('__class__'))
65 except OperationError as e:
66 if e.async(space): # ignore most exceptions
67 raise
68 return False
69 else:
70 return p_abstract_issubclass_w(space, w_abstractclass, w_cls)
71
72
73 def p_recursive_isinstance_type_w(space, w_inst, w_type):
74 # subfunctionality of p_recursive_isinstance_w(): assumes that w_type is
75 # a type object. Copied straight from CPython 2.7.
76 if space.isinstance_w(w_inst, w_type):
77 return True
78 try:
79 w_abstractclass = space.getattr(w_inst, space.wrap('__class__'))
80 except OperationError as e:
81 if e.async(space): # ignore most exceptions
82 raise
83 else:
84 if w_abstractclass is not space.type(w_inst):
85 if space.isinstance_w(w_abstractclass, space.w_type):
86 return space.issubtype_w(w_abstractclass, w_type)
87 return False
88
89
4890 @jit.unroll_safe
4991 def abstract_isinstance_w(space, w_obj, w_klass_or_tuple, allow_override=False):
5092 """Implementation for the full 'isinstance(obj, klass_or_tuple)'."""
93 # Copied from CPython 2.7's PyObject_Isinstance(). Additionally,
94 # if 'allow_override' is False (the default), then don't try to
95 # use a custom __instancecheck__ method.
96
97 # WARNING: backward compatibility function name here. CPython
98 # uses the name "abstract" to refer to the logic of handling
99 # class-like objects, with a "__bases__" attribute. This function
100 # here is not related to that and implements the full
101 # PyObject_IsInstance() logic.
102
103 # Quick test for an exact match
104 if space.type(w_obj) is w_klass_or_tuple:
105 return True
106
51107 # -- case (anything, tuple)
52108 # XXX it might be risky that the JIT sees this
53109 if space.isinstance_w(w_klass_or_tuple, space.w_tuple):
57113 return False
58114
59115 # -- case (anything, type)
60 try:
61 if allow_override:
62 w_result = space.isinstance_allow_override(w_obj, w_klass_or_tuple)
63 else:
64 w_result = space.isinstance(w_obj, w_klass_or_tuple)
65 except OperationError as e: # if w_klass_or_tuple was not a type, ignore it
66 if not e.match(space, space.w_TypeError):
67 raise # propagate other errors
68 else:
69 if space.is_true(w_result):
116 if allow_override:
117 w_check = space.lookup(w_klass_or_tuple, "__instancecheck__")
118 if w_check is not None:
119 # this is the common case: all type objects have a method
120 # __instancecheck__. The one in the base 'type' type calls
121 # back p_recursive_isinstance_type_w() from the present module.
122 return space.is_true(space.get_and_call_function(
123 w_check, w_klass_or_tuple, w_obj))
124
125 return p_recursive_isinstance_w(space, w_obj, w_klass_or_tuple)
126
127
128 # ---------- issubclass ----------
129
130
131 @jit.unroll_safe
132 def p_abstract_issubclass_w(space, w_derived, w_cls):
133 # Copied straight from CPython 2.7, function abstract_issubclass().
134 # Don't confuse this with the function abstract_issubclass_w() below.
135 # Here, w_cls cannot be a tuple.
136 while True:
137 if space.is_w(w_derived, w_cls):
70138 return True
71 # From now on we know that w_klass_or_tuple is indeed a type.
72 # Try also to compare it with obj.__class__, if this is not
73 # the same as type(obj).
74 try:
75 w_pretendtype = space.getattr(w_obj, space.wrap('__class__'))
76 if space.is_w(w_pretendtype, space.type(w_obj)):
77 return False # common case: obj.__class__ is type(obj)
78 if not allow_override:
79 return space.issubtype_w(w_pretendtype, w_klass_or_tuple)
80 w_result = space.issubtype_allow_override(w_pretendtype,
81 w_klass_or_tuple)
82 except OperationError as e:
83 if e.async(space):
84 raise
85 return False # ignore most exceptions
86 else:
87 return space.is_true(w_result)
88
89 # -- case (old-style instance, old-style class)
90 if isinstance(w_klass_or_tuple, W_ClassObject):
91 if isinstance(w_obj, W_InstanceObject):
92 return w_obj.w_class.is_subclass_of(w_klass_or_tuple)
93 return _abstract_isinstance_w_helper(space, w_obj, w_klass_or_tuple)
94
95
96 def _abstract_isinstance_w_helper(space, w_obj, w_klass_or_tuple):
97 # -- case (anything, abstract-class)
98 check_class(space, w_klass_or_tuple,
99 "isinstance() arg 2 must be a class, type,"
100 " or tuple of classes and types")
101 try:
102 w_abstractclass = space.getattr(w_obj, space.wrap('__class__'))
103 except OperationError as e:
104 if e.async(space): # ignore most exceptions
105 raise
106 return False
107 else:
108 return _issubclass_recurse(space, w_abstractclass, w_klass_or_tuple)
109
110
111 @jit.unroll_safe
112 def _issubclass_recurse(space, w_derived, w_top):
113 """Internal helper for abstract cases. Here, w_top cannot be a tuple."""
114 if space.is_w(w_derived, w_top):
115 return True
116 w_bases = _get_bases(space, w_derived)
117 if w_bases is not None:
118 for w_base in space.fixedview(w_bases):
119 if _issubclass_recurse(space, w_base, w_top):
139 w_bases = _get_bases(space, w_derived)
140 if w_bases is None:
141 return False
142 bases_w = space.fixedview(w_bases)
143 last_index = len(bases_w) - 1
144 if last_index < 0:
145 return False
146 # Avoid recursivity in the single inheritance case; in general,
147 # don't recurse on the last item in the tuple (loop instead).
148 for i in range(last_index):
149 if p_abstract_issubclass_w(space, bases_w[i], w_cls):
120150 return True
121 return False
151 w_derived = bases_w[last_index]
152
153
154 def p_recursive_issubclass_w(space, w_derived, w_cls):
155 # From CPython's function of the same name (which as far as I can tell
156 # is not recursive). Copied straight from CPython 2.7.
157 if (space.isinstance_w(w_cls, space.w_type) and
158 space.isinstance_w(w_derived, space.w_type)):
159 return space.issubtype_w(w_derived, w_cls)
160 #
161 if (isinstance(w_derived, W_ClassObject) and
162 isinstance(w_cls, W_ClassObject)):
163 return w_derived.is_subclass_of(w_cls)
164 #
165 check_class(space, w_derived, "issubclass() arg 1 must be a class")
166 check_class(space, w_cls, "issubclass() arg 2 must be a class"
167 " or tuple of classes")
168 return p_abstract_issubclass_w(space, w_derived, w_cls)
122169
123170
124171 @jit.unroll_safe
126173 allow_override=False):
127174 """Implementation for the full 'issubclass(derived, klass_or_tuple)'."""
128175
129 # -- case (class-like-object, tuple-of-classes)
176 # WARNING: backward compatibility function name here. CPython
177 # uses the name "abstract" to refer to the logic of handling
178 # class-like objects, with a "__bases__" attribute. This function
179 # here is not related to that and implements the full
180 # PyObject_IsSubclass() logic. There is also p_abstract_issubclass_w().
181
182 # -- case (anything, tuple-of-classes)
130183 if space.isinstance_w(w_klass_or_tuple, space.w_tuple):
131184 for w_klass in space.fixedview(w_klass_or_tuple):
132185 if abstract_issubclass_w(space, w_derived, w_klass, allow_override):
133186 return True
134187 return False
135188
136 # -- case (type, type)
137 try:
138 if not allow_override:
139 return space.issubtype_w(w_derived, w_klass_or_tuple)
140 w_result = space.issubtype_allow_override(w_derived, w_klass_or_tuple)
141 except OperationError as e: # if one of the args was not a type, ignore it
142 if not e.match(space, space.w_TypeError):
143 raise # propagate other errors
144 else:
145 return space.is_true(w_result)
146
147 # -- case (old-style class, old-style class)
148 if isinstance(w_derived, W_ClassObject):
149 if isinstance(w_klass_or_tuple, W_ClassObject):
150 return w_derived.is_subclass_of(w_klass_or_tuple)
151 else:
152 check_class(space, w_derived, "issubclass() arg 1 must be a class")
153 # from here on, we are sure that w_derived is a class-like object
154
155 # -- case (class-like-object, abstract-class)
156 check_class(space, w_klass_or_tuple,
157 "issubclass() arg 2 must be a class, type,"
158 " or tuple of classes and types")
159 return _issubclass_recurse(space, w_derived, w_klass_or_tuple)
189 # -- case (anything, type)
190 if allow_override:
191 w_check = space.lookup(w_klass_or_tuple, "__subclasscheck__")
192 if w_check is not None:
193 # this is the common case: all type objects have a method
194 # __subclasscheck__. The one in the base 'type' type calls
195 # back p_recursive_issubclass_w() from the present module.
196 return space.is_true(space.get_and_call_function(
197 w_check, w_klass_or_tuple, w_derived))
198
199 return p_recursive_issubclass_w(space, w_derived, w_klass_or_tuple)
200
160201
161202 # ------------------------------------------------------------
162203 # Exception helpers
215215 c = C()
216216 assert isinstance(c, C)
217217 assert not called
218
219 def test_instancecheck_exception_not_eaten(self):
220 class M(object):
221 def __instancecheck__(self, obj):
222 raise TypeError("foobar")
223
224 e = raises(TypeError, isinstance, 42, M())
225 assert str(e.value) == "foobar"
226
227 def test_issubclass_exception_not_eaten(self):
228 class M(object):
229 def __subclasscheck__(self, subcls):
230 raise TypeError("foobar")
231
232 e = raises(TypeError, issubclass, 42, M())
233 assert str(e.value) == "foobar"
234
235 def test_issubclass_no_fallback(self):
236 class M(object):
237 def __subclasscheck__(self, subcls):
238 return False
239
240 assert issubclass(42, M()) is False
11 from rpython.rtyper.lltypesystem import lltype
22 from rpython.rtyper.lltypesystem.lloperation import llop
33 from rpython.rlib.rarithmetic import r_uint, intmask
4 from rpython.rlib.rarithmetic import int_c_div, int_c_mod
45 from rpython.rlib import jit
5
6
7 # XXX maybe temporary: hide llop.int_{floordiv,mod} from the JIT,
8 # because now it expects only Python-style divisions, not the
9 # C-style divisions of these two ll operations
10 @jit.dont_look_inside
11 def _int_floordiv(n, m):
12 return llop.int_floordiv(lltype.Signed, n, m)
13
14 @jit.dont_look_inside
15 def _int_mod(n, m):
16 return llop.int_mod(lltype.Signed, n, m)
176
187
198 @unwrap_spec(n=int, m=int)
3019
3120 @unwrap_spec(n=int, m=int)
3221 def int_floordiv(space, n, m):
33 return space.wrap(_int_floordiv(n, m))
22 return space.wrap(int_c_div(n, m))
3423
3524 @unwrap_spec(n=int, m=int)
3625 def int_mod(space, n, m):
37 return space.wrap(_int_mod(n, m))
26 return space.wrap(int_c_mod(n, m))
3827
3928 @unwrap_spec(n=int, m=int)
4029 def int_lshift(space, n, m):
22 from rpython.rlib import rdynload, clibffi, entrypoint
33 from rpython.rtyper.lltypesystem import rffi
44
5 VERSION = "1.7.0"
5 VERSION = "1.8.0"
66
77 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
88 try:
219219 if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK:
220220 raise oefmt(space.w_SystemError,
221221 "libffi failed to build this callback")
222 if closure_ptr.c_user_data != unique_id:
223 raise oefmt(space.w_SystemError,
224 "ffi_prep_closure(): bad user_data (it seems that the "
225 "version of the libffi library seen at runtime is "
226 "different from the 'ffi.h' file seen at compile-time)")
222227
223228 def py_invoke(self, ll_res, ll_args):
224229 jitdriver1.jit_merge_point(callback=self,
309309 self.ctype.name, ct.name)
310310 #
311311 itemsize = ct.ctitem.size
312 if itemsize <= 0:
313 itemsize = 1
314312 with self as ptr1, w_other as ptr2:
315313 diff = (rffi.cast(lltype.Signed, ptr1) -
316 rffi.cast(lltype.Signed, ptr2)) // itemsize
314 rffi.cast(lltype.Signed, ptr2))
315 if itemsize > 1:
316 if diff % itemsize:
317 raise oefmt(space.w_ValueError,
318 "pointer subtraction: the distance between the two "
319 "pointers is not a multiple of the item size")
320 diff //= itemsize
317321 return space.wrap(diff)
318322 #
319323 return self._add_or_sub(w_other, -1)
156156 mustfree_max_plus_1 = 0
157157 buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
158158 try:
159 keepalives = [None] * len(args_w) # None or strings
159160 for i in range(len(args_w)):
160161 data = rffi.ptradd(buffer, cif_descr.exchange_args[i])
161162 w_obj = args_w[i]
162163 argtype = self.fargs[i]
163 if argtype.convert_argument_from_object(data, w_obj):
164 if argtype.convert_argument_from_object(data, w_obj,
165 keepalives, i):
164166 # argtype is a pointer type, and w_obj a list/tuple/str
165167 mustfree_max_plus_1 = i + 1
166168
176178 if isinstance(argtype, W_CTypePointer):
177179 data = rffi.ptradd(buffer, cif_descr.exchange_args[i])
178180 flag = get_mustfree_flag(data)
181 raw_cdata = rffi.cast(rffi.CCHARPP, data)[0]
179182 if flag == 1:
180 raw_cdata = rffi.cast(rffi.CCHARPP, data)[0]
181183 lltype.free(raw_cdata, flavor='raw')
184 elif flag >= 4:
185 value = keepalives[i]
186 assert value is not None
187 rffi.free_nonmovingbuffer(value, raw_cdata, chr(flag))
182188 lltype.free(buffer, flavor='raw')
183189 keepalive_until_here(args_w)
184190 return w_res
8282 raise oefmt(space.w_TypeError, "cannot initialize cdata '%s'",
8383 self.name)
8484
85 def convert_argument_from_object(self, cdata, w_ob):
85 def convert_argument_from_object(self, cdata, w_ob, keepalives, i):
8686 self.convert_from_object(cdata, w_ob)
8787 return False
8888
8383 if self.size == 1:
8484 with cdataobj as ptr:
8585 s = ptr[0]
86 return self.space.wrap(s)
86 return self.space.newbytes(s)
8787 return W_CType.string(self, cdataobj, maxlen)
8888
8989 def unpack_ptr(self, w_ctypeptr, ptr, length):
125125 return self.space.wrap(ord(cdata[0]))
126126
127127 def convert_to_object(self, cdata):
128 return self.space.wrap(cdata[0])
128 return self.space.newbytes(cdata[0])
129129
130130 def _convert_to_char(self, w_ob):
131131 space = self.space
132132 if space.isinstance_w(w_ob, space.w_str):
133 s = space.str_w(w_ob)
133 s = space.bytes_w(w_ob)
134134 if len(s) == 1:
135135 return s[0]
136136 if (isinstance(w_ob, cdataobj.W_CData) and
145145
146146 def unpack_ptr(self, w_ctypeptr, ptr, length):
147147 s = rffi.charpsize2str(ptr, length)
148 return self.space.wrapbytes(s)
148 return self.space.newbytes(s)
149149
150150
151151 # XXX explicitly use an integer type instead of lltype.UniChar here,
1313
1414
1515 class W_CTypePtrOrArray(W_CType):
16 _attrs_ = ['ctitem', 'can_cast_anything', 'length']
17 _immutable_fields_ = ['ctitem', 'can_cast_anything', 'length']
16 _attrs_ = ['ctitem', 'can_cast_anything', 'accept_str', 'length']
17 _immutable_fields_ = ['ctitem', 'can_cast_anything', 'accept_str', 'length']
1818 length = -1
1919
2020 def __init__(self, space, size, extra, extra_position, ctitem,
2727 # - for functions, it is the return type
2828 self.ctitem = ctitem
2929 self.can_cast_anything = could_cast_anything and ctitem.cast_anything
30 self.accept_str = (self.can_cast_anything or
31 (ctitem.is_primitive_integer and
32 ctitem.size == rffi.sizeof(lltype.Char)))
3033
3134 def is_unichar_ptr_or_array(self):
3235 return isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveUniChar)
6972 pass
7073 else:
7174 self._convert_array_from_listview(cdata, space.listview(w_ob))
72 elif (self.can_cast_anything or
73 (self.ctitem.is_primitive_integer and
74 self.ctitem.size == rffi.sizeof(lltype.Char))):
75 elif self.accept_str:
7576 if not space.isinstance_w(w_ob, space.w_str):
7677 raise self._convert_error("str or list or tuple", w_ob)
7778 s = space.str_w(w_ob)
119120 s = rffi.charp2str(ptr)
120121 else:
121122 s = rffi.charp2strn(ptr, length)
122 return space.wrapbytes(s)
123 return space.newbytes(s)
123124 #
124125 # pointer to a wchar_t: builds and returns a unicode
125126 if self.is_unichar_ptr_or_array():
128129 u = rffi.wcharp2unicode(cdata)
129130 else:
130131 u = rffi.wcharp2unicoden(cdata, length)
131 return space.wrap(u)
132 return space.newunicode(u)
132133 #
133134 return W_CType.string(self, cdataobj, maxlen)
134135
259260 else:
260261 return lltype.nullptr(rffi.CCHARP.TO)
261262
262 def _prepare_pointer_call_argument(self, w_init, cdata):
263 space = self.space
263 def _prepare_pointer_call_argument(self, w_init, cdata, keepalives, i):
264 space = self.space
265 if self.accept_str and space.isinstance_w(w_init, space.w_str):
266 # special case to optimize strings passed to a "char *" argument
267 value = w_init.str_w(space)
268 keepalives[i] = value
269 buf, buf_flag = rffi.get_nonmovingbuffer_final_null(value)
270 rffi.cast(rffi.CCHARPP, cdata)[0] = buf
271 return ord(buf_flag) # 4, 5 or 6
272 #
264273 if (space.isinstance_w(w_init, space.w_list) or
265274 space.isinstance_w(w_init, space.w_tuple)):
266275 length = space.int_w(space.len(w_init))
296305 rffi.cast(rffi.CCHARPP, cdata)[0] = result
297306 return 1
298307
299 def convert_argument_from_object(self, cdata, w_ob):
308 def convert_argument_from_object(self, cdata, w_ob, keepalives, i):
300309 from pypy.module._cffi_backend.ctypefunc import set_mustfree_flag
301310 result = (not isinstance(w_ob, cdataobj.W_CData) and
302 self._prepare_pointer_call_argument(w_ob, cdata))
311 self._prepare_pointer_call_argument(w_ob, cdata,
312 keepalives, i))
303313 if result == 0:
304314 self.convert_from_object(cdata, w_ob)
305315 set_mustfree_flag(cdata, result)
8989 self.force_lazy_struct()
9090 space = self.space
9191 try:
92 cfield = self._fields_dict[fieldname]
92 cfield = self._getcfield_const(fieldname)
9393 except KeyError:
9494 raise OperationError(space.w_KeyError, space.wrap(fieldname))
9595 if cfield.bitshift >= 0:
352352 'array.array' or numpy arrays."""
353353 #
354354 w_ctchara = newtype._new_chara_type(self.space)
355 return func.from_buffer(self.space, w_ctchara, w_python_buffer)
355 return func._from_buffer(self.space, w_ctchara, w_python_buffer)
356356
357357
358358 @unwrap_spec(w_arg=W_CData)
00 from rpython.rtyper.annlowlevel import llstr
11 from rpython.rtyper.lltypesystem import lltype, rffi
22 from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
3 from rpython.rlib.objectmodel import keepalive_until_here
3 from rpython.rlib.objectmodel import keepalive_until_here, we_are_translated
4 from rpython.rlib import jit
45
56 from pypy.interpreter.error import OperationError, oefmt
67 from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
131132 raise oefmt(space.w_TypeError,
132133 "needs 'char[]', got '%s'", w_ctype.name)
133134 #
135 return _from_buffer(space, w_ctype, w_x)
136
137 def _from_buffer(space, w_ctype, w_x):
134138 buf = _fetch_as_read_buffer(space, w_x)
135 try:
136 _cdata = buf.get_raw_address()
137 except ValueError:
138 raise oefmt(space.w_TypeError,
139 "from_buffer() got a '%T' object, which supports the "
140 "buffer interface but cannot be rendered as a plain "
141 "raw address on PyPy", w_x)
139 if space.isinstance_w(w_x, space.w_str):
140 _cdata = get_raw_address_of_string(space, w_x)
141 else:
142 try:
143 _cdata = buf.get_raw_address()
144 except ValueError:
145 raise oefmt(space.w_TypeError,
146 "from_buffer() got a '%T' object, which supports the "
147 "buffer interface but cannot be rendered as a plain "
148 "raw address on PyPy", w_x)
142149 #
143150 return cdataobj.W_CDataFromBuffer(space, _cdata, w_ctype, buf, w_x)
151
152 # ____________________________________________________________
153
154 class RawBytes(object):
155 def __init__(self, string):
156 self.ptr = rffi.str2charp(string, track_allocation=False)
157 def __del__(self):
158 rffi.free_charp(self.ptr, track_allocation=False)
159
160 class RawBytesCache(object):
161 def __init__(self, space):
162 from pypy.interpreter.baseobjspace import W_Root
163 from rpython.rlib import rweakref
164 self.wdict = rweakref.RWeakKeyDictionary(W_Root, RawBytes)
165
166 @jit.dont_look_inside
167 def get_raw_address_of_string(space, w_x):
168 """Special case for ffi.from_buffer(string). Returns a 'char *' that
169 is valid as long as the string object is alive. Two calls to
170 ffi.from_buffer(same_string) are guaranteed to return the same pointer.
171 """
172 from rpython.rtyper.annlowlevel import llstr
173 from rpython.rtyper.lltypesystem.rstr import STR
174 from rpython.rtyper.lltypesystem import llmemory
175 from rpython.rlib import rgc
176
177 cache = space.fromcache(RawBytesCache)
178 rawbytes = cache.wdict.get(w_x)
179 if rawbytes is None:
180 data = space.str_w(w_x)
181 if we_are_translated() and not rgc.can_move(data):
182 lldata = llstr(data)
183 data_start = (llmemory.cast_ptr_to_adr(lldata) +
184 rffi.offsetof(STR, 'chars') +
185 llmemory.itemoffsetof(STR.chars, 0))
186 data_start = rffi.cast(rffi.CCHARP, data_start)
187 data_start[len(data)] = '\x00' # write the final extra null
188 return data_start
189 rawbytes = RawBytes(data)
190 cache.wdict.set(w_x, rawbytes)
191 return rawbytes.ptr
192
193 # ____________________________________________________________
144194
145195
146196 def unsafe_escaping_ptr_for_ptr_or_array(w_cdata):
200250 else:
201251 copy_string_to_raw(llstr(src_string), dest_data, 0, n)
202252 else:
253 # nowadays this case should be rare or impossible: as far as
254 # I know, all common types implementing the *writable* buffer
255 # interface now support get_raw_address()
203256 if src_is_ptr:
204257 for i in range(n):
205258 dest_buf.setitem(i, src_data[i])
252252 sandboxsafe=True)
253253
254254 # split here for JIT backends that don't support floats/longlongs/etc.
255 @jit.dont_look_inside
255256 def is_nonnull_longdouble(cdata):
256257 return _is_nonnull_longdouble(read_raw_longdouble_data(cdata))
257258 def is_nonnull_float(cdata, size):
9696 [rffi.INT], rffi.CCHARP)
9797
9898 def parse_c_type(info, input):
99 p_input = rffi.str2charp(input)
100 try:
99 with rffi.scoped_view_charp(input) as p_input:
101100 res = ll_parse_c_type(info, p_input)
102 finally:
103 rffi.free_charp(p_input)
104101 return rffi.cast(lltype.Signed, res)
105102
106103 NULL_CTX = lltype.nullptr(PCTX.TO)
129126 return rffi.getintfield(src_ctx, 'c_num_types')
130127
131128 def search_in_globals(ctx, name):
132 c_name = rffi.str2charp(name)
133 result = ll_search_in_globals(ctx, c_name,
134 rffi.cast(rffi.SIZE_T, len(name)))
135 rffi.free_charp(c_name)
129 with rffi.scoped_view_charp(name) as c_name:
130 result = ll_search_in_globals(ctx, c_name,
131 rffi.cast(rffi.SIZE_T, len(name)))
136132 return rffi.cast(lltype.Signed, result)
137133
138134 def search_in_struct_unions(ctx, name):
139 c_name = rffi.str2charp(name)
140 result = ll_search_in_struct_unions(ctx, c_name,
141 rffi.cast(rffi.SIZE_T, len(name)))
142 rffi.free_charp(c_name)
135 with rffi.scoped_view_charp(name) as c_name:
136 result = ll_search_in_struct_unions(ctx, c_name,
137 rffi.cast(rffi.SIZE_T, len(name)))
143138 return rffi.cast(lltype.Signed, result)
00 # ____________________________________________________________
11
22 import sys
3 assert __version__ == "1.7.0", ("This test_c.py file is for testing a version"
3 assert __version__ == "1.8.0", ("This test_c.py file is for testing a version"
44 " of cffi that differs from the one that we"
55 " get from 'import _cffi_backend'")
66 if sys.version_info < (3,):
574574 py.test.raises(TypeError, "a - q")
575575 e = py.test.raises(TypeError, "q - a")
576576 assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'"
577
578 def test_ptr_sub_unaligned():
579 BInt = new_primitive_type("int")
580 BIntPtr = new_pointer_type(BInt)
581 a = cast(BIntPtr, 1240)
582 for bi in range(1430, 1438):
583 b = cast(BIntPtr, bi)
584 if ((bi - 1240) % size_of_int()) == 0:
585 assert b - a == (bi - 1240) // size_of_int()
586 assert a - b == (1240 - bi) // size_of_int()
587 else:
588 py.test.raises(ValueError, "b - a")
589 py.test.raises(ValueError, "a - b")
577590
578591 def test_cast_primitive_from_cdata():
579592 p = new_primitive_type("int")
33293342 BChar = new_primitive_type("char")
33303343 BCharP = new_pointer_type(BChar)
33313344 BCharA = new_array_type(BCharP, None)
3332 py.test.raises(TypeError, from_buffer, BCharA, b"foo")
3345 p1 = from_buffer(BCharA, b"foo")
3346 assert p1 == from_buffer(BCharA, b"foo")
3347 import gc; gc.collect()
3348 assert p1 == from_buffer(BCharA, b"foo")
33333349 py.test.raises(TypeError, from_buffer, BCharA, u+"foo")
33343350 try:
33353351 from __builtin__ import buffer
33363352 except ImportError:
33373353 pass
33383354 else:
3355 # from_buffer(buffer(b"foo")) does not work, because it's not
3356 # implemented on pypy; only from_buffer(b"foo") works.
33393357 py.test.raises(TypeError, from_buffer, BCharA, buffer(b"foo"))
33403358 py.test.raises(TypeError, from_buffer, BCharA, buffer(u+"foo"))
33413359 try:
6868 sub_ffi.set_source('re_py_subsrc', None)
6969 sub_ffi.emit_python_code(str(tmpdir.join('re_py_subsrc.py')))
7070 #
71 space.appexec([space.wrap(str(tmpdir))], """(path):
72 import _cffi_backend # force it to be initialized
73 import sys
74 sys.path.insert(0, path)
71 cls.w_fix_path = space.appexec([space.wrap(str(tmpdir))], """(path):
72 def fix_path(ignored=None):
73 import _cffi_backend # force it to be initialized
74 import sys
75 if path not in sys.path:
76 sys.path.insert(0, path)
77 return fix_path
7578 """)
7679
7780 def teardown_method(self, meth):
8588
8689
8790 def test_constant_1(self):
91 self.fix_path()
8892 from re_python_pysrc import ffi
8993 assert ffi.integer_const('FOOBAR') == -42
9094 assert ffi.integer_const('FOOBAZ') == -43
9195
9296 def test_large_constant(self):
97 self.fix_path()
9398 from re_python_pysrc import ffi
9499 assert ffi.integer_const('BIGPOS') == 420000000000
95100 assert ffi.integer_const('BIGNEG') == -420000000000
96101
97102 def test_function(self):
98103 import _cffi_backend
104 self.fix_path()
99105 from re_python_pysrc import ffi
100106 lib = ffi.dlopen(self.extmod)
101107 assert lib.add42(-10) == 32
103109
104110 def test_dlclose(self):
105111 import _cffi_backend
112 self.fix_path()
106113 from re_python_pysrc import ffi
107114 lib = ffi.dlopen(self.extmod)
108115 ffi.dlclose(lib)
114121 "library '%s' has been closed" % (self.extmod,))
115122
116123 def test_constant_via_lib(self):
124 self.fix_path()
117125 from re_python_pysrc import ffi
118126 lib = ffi.dlopen(self.extmod)
119127 assert lib.FOOBAR == -42
120128 assert lib.FOOBAZ == -43
121129
122130 def test_opaque_struct(self):
131 self.fix_path()
123132 from re_python_pysrc import ffi
124133 ffi.cast("struct foo_s *", 0)
125134 raises(TypeError, ffi.new, "struct foo_s *")
126135
127136 def test_nonopaque_struct(self):
137 self.fix_path()
128138 from re_python_pysrc import ffi
129139 for p in [ffi.new("struct bar_s *", [5, b"foobar"]),
130140 ffi.new("bar_t *", [5, b"foobar"])]:
133143 assert p.a[5] == ord('r')
134144
135145 def test_enum(self):
146 self.fix_path()
136147 from re_python_pysrc import ffi
137148 assert ffi.integer_const("BB") == 1
138149 e = ffi.cast("enum foo_e", 2)
139150 assert ffi.string(e) == "CC"
140151
141152 def test_include_1(self):
153 self.fix_path()
142154 from re_py_subsrc import ffi
143155 assert ffi.integer_const('FOOBAR') == -42
144156 assert ffi.integer_const('FOOBAZ') == -43
152164 assert p.a[4] == ord('a')
153165
154166 def test_global_var(self):
167 self.fix_path()
155168 from re_python_pysrc import ffi
156169 lib = ffi.dlopen(self.extmod)
157170 assert lib.globalvar42 == 1234
162175 assert lib.globalvar42 == 1238
163176
164177 def test_global_const_int(self):
178 self.fix_path()
165179 from re_python_pysrc import ffi
166180 lib = ffi.dlopen(self.extmod)
167181 assert lib.globalconst42 == 4321
168182 raises(AttributeError, ffi.addressof, lib, 'globalconst42')
169183
170184 def test_global_const_nonint(self):
185 self.fix_path()
171186 from re_python_pysrc import ffi
172187 lib = ffi.dlopen(self.extmod)
173188 assert ffi.string(lib.globalconsthello, 8) == "hello"
174189 raises(AttributeError, ffi.addressof, lib, 'globalconsthello')
175190
176191 def test_rtld_constants(self):
192 self.fix_path()
177193 from re_python_pysrc import ffi
178194 ffi.RTLD_NOW # check that we have the attributes
179195 ffi.RTLD_LAZY
180196 ffi.RTLD_GLOBAL
181197
182198 def test_no_such_function_or_global_var(self):
199 self.fix_path()
183200 from re_python_pysrc import ffi
184201 lib = ffi.dlopen(self.extmod)
185202 e = raises(ffi.error, getattr, lib, 'no_such_function')
3535 w_errorhandler = lookup_error(space, errors)
3636 if decode:
3737 w_cls = space.w_UnicodeDecodeError
38 w_input = space.newbytes(input)
3839 else:
3940 w_cls = space.w_UnicodeEncodeError
41 w_input = space.newunicode(input)
4042 w_exc = space.call_function(
4143 w_cls,
4244 space.wrap(encoding),
43 space.wrap(input),
45 w_input,
4446 space.wrap(startpos),
4547 space.wrap(endpos),
4648 space.wrap(reason))
313315 @unwrap_spec(errors='str_or_None')
314316 def readbuffer_encode(space, w_data, errors='strict'):
315317 s = space.getarg_w('s#', w_data)
316 return space.newtuple([space.wrap(s), space.wrap(len(s))])
318 return space.newtuple([space.newbytes(s), space.wrap(len(s))])
317319
318320 @unwrap_spec(errors='str_or_None')
319321 def charbuffer_encode(space, w_data, errors='strict'):
376378 state = space.fromcache(CodecState)
377379 func = getattr(runicode, rname)
378380 result = func(uni, len(uni), errors, state.encode_error_handler)
379 return space.newtuple([space.wrap(result), space.wrap(len(uni))])
381 return space.newtuple([space.newbytes(result), space.wrap(len(uni))])
380382 wrap_encoder.func_name = rname
381383 globals()[name] = wrap_encoder
382384
397399 wrap_decoder.func_name = rname
398400 globals()[name] = wrap_decoder
399401
400 for encoders in [
402 for encoder in [
401403 "ascii_encode",
402404 "latin_1_encode",
403405 "utf_7_encode",
411413 "raw_unicode_escape_encode",
412414 "unicode_internal_encode",
413415 ]:
414 make_encoder_wrapper(encoders)
415
416 for decoders in [
416 make_encoder_wrapper(encoder)
417
418 for decoder in [
417419 "ascii_decode",
418420 "latin_1_decode",
419421 "utf_7_decode",
425427 "utf_32_le_decode",
426428 "raw_unicode_escape_decode",
427429 ]:
428 make_decoder_wrapper(decoders)
430 make_decoder_wrapper(decoder)
429431
430432 if hasattr(runicode, 'str_decode_mbcs'):
431433 make_encoder_wrapper('mbcs_encode')
559561
560562 if space.isinstance_w(w_ch, space.w_str):
561563 # Charmap may return a string
562 return space.str_w(w_ch)
564 return space.bytes_w(w_ch)
563565 elif space.isinstance_w(w_ch, space.w_int):
564566 # Charmap may return a number
565567 x = space.int_w(w_ch)
607609 result = runicode.unicode_encode_charmap(
608610 uni, len(uni), errors,
609611 state.encode_error_handler, mapping)
610 return space.newtuple([space.wrap(result), space.wrap(len(uni))])
612 return space.newtuple([space.newbytes(result), space.wrap(len(uni))])
611613
612614
613615 @unwrap_spec(chars=unicode)
695697 def escape_decode(space, data, errors='strict'):
696698 from pypy.interpreter.pyparser.parsestring import PyString_DecodeEscape
697699 result = PyString_DecodeEscape(space, data, errors, None)
698 return space.newtuple([space.wrap(result), space.wrap(len(data))])
700 return space.newtuple([space.newbytes(result), space.wrap(len(data))])
3737 errors = None
3838 fd = -1
3939 cffi_fileobj = None # pypy/module/_cffi_backend
40 w_tb = None # String representation of the traceback at creation time
4041
4142 newlines = 0 # Updated when the stream is closed
4243
4344 def __init__(self, space):
4445 self.space = space
4546 self.register_finalizer(space)
47 if self.space.sys.track_resources:
48 self.w_tb = self.space.format_traceback()
4649
4750 def _finalize_(self):
4851 # assume that the file and stream objects are only visible in the
4952 # thread that runs _finalize_, so no race condition should be
5053 # possible and no locking is done here.
51 if self.stream is not None:
52 try:
53 self.direct_close()
54 except StreamErrors as e:
55 operr = wrap_streamerror(self.space, e, self.w_name)
56 raise operr
54 if self.stream is None:
55 return
56 if self.space.sys.track_resources:
57 w_repr = self.space.repr(self)
58 str_repr = self.space.str_w(w_repr)
59 w_msg = self.space.wrap("WARNING: unclosed file: " + str_repr)
60 self.space.resource_warning(w_msg, self.w_tb)
61 #
62 try:
63 self.direct_close()
64 except StreamErrors as e:
65 operr = wrap_streamerror(self.space, e, self.w_name)
66 raise operr
5767
5868 def fdopenstream(self, stream, fd, mode, w_name=None):
5969 self.fd = fd
00 from __future__ import with_statement
1 import py, os, errno
1 import pytest, os, errno
2 from pypy.interpreter.gateway import interp2app, unwrap_spec
23
34 def getfile(space):
45 return space.appexec([], """():
910 return file
1011 """)
1112
13 # the following function is used e.g. in test_resource_warning
14 @unwrap_spec(regex=str, s=str)
15 def regex_search(space, regex, s):
16 import re
17 import textwrap
18 regex = textwrap.dedent(regex).strip()
19 m = re.search(regex, s)
20 m = bool(m)
21 return space.wrap(m)
22
1223 class AppTestFile(object):
1324 spaceconfig = dict(usemodules=("_file",))
1425
1526 def setup_class(cls):
1627 cls.w_temppath = cls.space.wrap(
17 str(py.test.ensuretemp("fileimpl").join("foo.txt")))
28 str(pytest.ensuretemp("fileimpl").join("foo.txt")))
1829 cls.w_file = getfile(cls.space)
30 cls.w_regex_search = cls.space.wrap(interp2app(regex_search))
1931
2032 def test_simple(self):
2133 f = self.file(self.temppath, "w")
205217 assert exc.value.filename == os.curdir
206218
207219 def test_encoding_errors(self):
220 import sys
221 if '__pypy__' not in sys.builtin_module_names:
222 pytest.skip("pypy only test")
208223 import _file
209224
210225 with self.file(self.temppath, "w") as f:
252267 # the following is a "nice to have" feature that CPython doesn't have
253268 if '__pypy__' in sys.builtin_module_names:
254269 assert repr(self.temppath) in g.getvalue()
270
271 @pytest.mark.skipif("config.option.runappdirect")
272 def test_track_resources(self):
273 import os, gc, sys, cStringIO
274 if '__pypy__' not in sys.builtin_module_names:
275 skip("pypy specific test")
276 def fn(flag1, flag2, do_close=False):
277 sys.pypy_set_track_resources(flag1)
278 f = self.file(self.temppath, 'w')
279 sys.pypy_set_track_resources(flag2)
280 buf = cStringIO.StringIO()
281 preverr = sys.stderr
282 try:
283 sys.stderr = buf
284 if do_close:
285 f.close()
286 del f
287 gc.collect() # force __del__ to be called
288 finally:
289 sys.stderr = preverr
290 sys.pypy_set_track_resources(False)
291 return buf.getvalue()
292
293 # check with track_resources disabled
294 assert fn(False, False) == ""
295 #
296 # check that we don't get the warning if we actually close the file
297 assert fn(False, False, do_close=True) == ""
298 #
299 # check with track_resources enabled
300 msg = fn(True, True)
301 assert self.regex_search(r"""
302 WARNING: unclosed file: <open file .*>
303 Created at \(most recent call last\):
304 File ".*", line .*, in test_track_resources
305 File ".*", line .*, in fn
306 """, msg)
307 #
308 # check with track_resources enabled in the destructor BUT with a
309 # file which was created when track_resources was disabled
310 msg = fn(False, True)
311 assert self.regex_search("WARNING: unclosed file: <open file .*>", msg)
312 assert "Created at" not in msg
313
314 @pytest.mark.skipif("config.option.runappdirect")
315 def test_track_resources_dont_crash(self):
316 import os, gc, sys, cStringIO
317 if '__pypy__' not in sys.builtin_module_names:
318 skip("pypy specific test")
319 #
320 # try hard to create a code object whose co_filename points to an
321 # EXISTING file, so that traceback.py tries to open it when formatting
322 # the stacktrace
323 f = open(self.temppath, 'w')
324 f.close()
325 co = compile('open("%s")' % self.temppath, self.temppath, 'exec')
326 sys.pypy_set_track_resources(True)
327 try:
328 # this exec used to fail, because space.format_traceback tried to
329 # recurively open a file, causing an infinite recursion. For the
330 # purpose of this test, it is enough that it actually finishes
331 # without errors
332 exec co
333 finally:
334 sys.pypy_set_track_resources(False)
255335
256336 def test_truncate(self):
257337 f = self.file(self.temppath, "w")
312392 cls.old_read = os.read
313393
314394 if cls.runappdirect:
315 py.test.skip("works with internals of _file impl on py.py")
395 pytest.skip("works with internals of _file impl on py.py")
316396 def read(fd, n=None):
317397 if fd != 424242:
318398 return cls.old_read(fd, n)
351431
352432 def setup_class(cls):
353433 if not cls.runappdirect:
354 py.test.skip("likely to deadlock when interpreted by py.py")
434 pytest.skip("likely to deadlock when interpreted by py.py")
355435 cls.w_temppath = cls.space.wrap(
356 str(py.test.ensuretemp("fileimpl").join("concurrency.txt")))
436 str(pytest.ensuretemp("fileimpl").join("concurrency.txt")))
357437 cls.w_file = getfile(cls.space)
358438
359439 def test_concurrent_writes(self):
464544
465545 def setup_class(cls):
466546 cls.w_temppath = cls.space.wrap(
467 str(py.test.ensuretemp("fileimpl").join("foo.txt")))
547 str(pytest.ensuretemp("fileimpl").join("foo.txt")))
468548 cls.w_file = getfile(cls.space)
469549
470550 def test___enter__(self):
110110 def digest(self, space):
111111 "Return the digest value as a string of binary data."
112112 digest = self._digest(space)
113 return space.wrap(digest)
113 return space.newbytes(digest)
114114
115115 def hexdigest(self, space):
116116 "Return the digest value as a string of hexadecimal digits."
342342 self._writer_reset_buf()
343343
344344 def _write(self, space, data):
345 w_data = space.wrap(data)
345 w_data = space.newbytes(data)
346346 while True:
347347 try:
348348 w_written = space.call_method(self.w_raw, "write", w_data)
414414 else:
415415 raise oefmt(space.w_ValueError,
416416 "read length must be positive or -1")
417 return space.wrap(res)
417 return space.newbytes(res)
418418
419419 @unwrap_spec(size=int)
420420 def peek_w(self, space, size=0):
431431 have = self._readahead()
432432 if have > 0:
433433 data = ''.join(self.buffer[self.pos:self.pos+have])
434 return space.wrap(data)
434 return space.newbytes(data)
435435
436436 # Fill the buffer from the raw stream, and copy it to the result
437437 self._reader_reset_buf()
441441 size = 0
442442 self.pos = 0
443443 data = ''.join(self.buffer[:size])
444 return space.wrap(data)
444 return space.newbytes(data)
445445
446446 @unwrap_spec(size=int)
447447 def read1_w(self, space, size):
451451 if size < 0:
452452 raise oefmt(space.w_ValueError, "read length must be positive")
453453 if size == 0:
454 return space.wrap("")
454 return space.newbytes("")
455455
456456 with self.lock:
457457 # Return up to n bytes. If at least one byte is buffered, we only
479479 endpos = self.pos + size
480480 data = ''.join(self.buffer[self.pos:endpos])
481481 self.pos = endpos
482 return space.wrap(data)
482 return space.newbytes(data)
483483
484484 def _read_all(self, space):
485485 "Read all the file, don't update the cache"
504504 if current_size == 0:
505505 return w_data
506506 break
507 data = space.str_w(w_data)
507 data = space.bytes_w(w_data)
508508 size = len(data)
509509 if size == 0:
510510 break
512512 current_size += size
513513 if self.abs_pos != -1:
514514 self.abs_pos += size
515 return space.wrap(builder.build())
515 return space.newbytes(builder.build())
516516
517517 def _raw_read(self, space, buffer, start, length):
518518 length = intmask(length)
643643 else:
644644 pos = -1
645645 if pos >= 0:
646 w_res = space.wrap(''.join(self.buffer[self.pos:pos+1]))
646 w_res = space.newbytes(''.join(self.buffer[self.pos:pos+1]))
647647 self.pos = pos + 1
648648 return w_res
649649 if have == limit:
650 w_res = space.wrap(''.join(self.buffer[self.pos:self.pos+have]))
650 w_res = space.newbytes(''.join(self.buffer[self.pos:self.pos+have]))
651651 self.pos += have
652652 return w_res
653653
689689 written += have
690690 if limit >= 0:
691691 limit -= have
692 return space.wrap(''.join(chunks))
692 return space.newbytes(''.join(chunks))
693693
694694 # ____________________________________________________
695695 # Write methods
10231023 self._deprecated_max_buffer_size(space)
10241024
10251025 self.state = STATE_ZERO
1026
10271026 check_readable_w(space, w_raw)
10281027 check_writable_w(space, w_raw)
10291028 check_seekable_w(space, w_raw)
3131 def read_w(self, space, w_size=None):
3232 self._check_closed(space)
3333 size = convert_size(space, w_size)
34 return space.wrap(self.read(size))
34 return space.newbytes(self.read(size))
3535
3636 def readline_w(self, space, w_limit=None):
3737 self._check_closed(space)
3838 limit = convert_size(space, w_limit)
39 return space.wrap(self.readline(limit))
39 return space.newbytes(self.readline(limit))
4040
4141 def read1_w(self, space, w_size):
4242 return self.read_w(space, w_size)
8080
8181 def getvalue_w(self, space):
8282 self._check_closed(space)
83 return space.wrap(self.getvalue())
83 return space.newbytes(self.getvalue())
8484
8585 def tell_w(self, space):
8686 self._check_closed(space)
127127 def getstate_w(self, space):
128128 self._check_closed(space)
129129 return space.newtuple([
130 space.wrap(self.getvalue()),
130 space.newbytes(self.getvalue()),
131131 space.wrap(self.tell()),
132132 self.getdict(space)])
133133
360360 raise wrap_oserror(space, e,
361361 exception_name='w_IOError')
362362
363 return space.wrap(s)
363 return space.newbytes(s)
364364
365365 def readinto_w(self, space, w_buffer):
366366 self._check_closed(space)
404404 break
405405 builder.append(chunk)
406406 total += len(chunk)
407 return space.wrap(builder.build())
407 return space.newbytes(builder.build())
408408
409409 if sys.platform == "win32":
410410 def _truncate(self, size):
191191 length = space.len_w(w_readahead)
192192 if length > 0:
193193 n = 0
194 buf = space.str_w(w_readahead)
194 buf = space.bytes_w(w_readahead)
195195 if limit >= 0:
196196 while True:
197197 if n >= length or n >= limit:
218218 raise oefmt(space.w_IOError,
219219 "peek() should have returned a bytes object, not "
220220 "'%T'", w_read)
221 read = space.str_w(w_read)
221 read = space.bytes_w(w_read)
222222 if not read:
223223 break
224224
228228 if read[-1] == '\n':
229229 break
230230
231 return space.wrap(builder.build())
231 return space.newbytes(builder.build())
232232
233233 def readlines_w(self, space, w_hint=None):
234234 hint = convert_size(space, w_hint)
338338
339339 if not space.isinstance_w(w_data, space.w_str):
340340 raise oefmt(space.w_TypeError, "read() should return bytes")
341 data = space.str_w(w_data)
341 data = space.bytes_w(w_data)
342342 if not data:
343343 break
344344 builder.append(data)
345 return space.wrap(builder.build())
345 return space.newbytes(builder.build())
346346
347347 W_RawIOBase.typedef = TypeDef(
348348 '_io._RawIOBase', W_IOBase.typedef,
159159 w_buffer, w_flag = space.unpackiterable(w_state, 2)
160160 flag = space.r_longlong_w(w_flag)
161161 else:
162 w_buffer = space.wrap("")
162 w_buffer = space.newbytes("")
163163 flag = 0
164164 flag <<= 1
165165 if self.pendingcr:
555555 # Given this, we know there was a valid snapshot point
556556 # len(dec_buffer) bytes ago with decoder state (b'', dec_flags).
557557 w_dec_buffer, w_dec_flags = space.unpackiterable(w_state, 2)
558 dec_buffer = space.str_w(w_dec_buffer)
558 dec_buffer = space.bytes_w(w_dec_buffer)
559559 dec_flags = space.int_w(w_dec_flags)
560560 else:
561561 dec_buffer = None
581581 if self.telling:
582582 # At the snapshot point, len(dec_buffer) bytes before the read,
583583 # the next input to be decoded is dec_buffer + input_chunk.
584 next_input = dec_buffer + space.str_w(w_input)
584 next_input = dec_buffer + space.bytes_w(w_input)
585585 self.snapshot = PositionSnapshot(dec_flags, next_input)
586586
587587 return not eof
768768 else:
769769 w_bytes = space.call_method(self.w_encoder, "encode", w_text)
770770
771 b = space.str_w(w_bytes)
771 b = space.bytes_w(w_bytes)
772772 if not self.pending_bytes:
773773 self.pending_bytes = []
774774 self.pending_bytes_count = 0
798798
799799 while True:
800800 try:
801 space.call_method(self.w_buffer, "write", space.wrap(pending_bytes))
801 space.call_method(self.w_buffer, "write",
802 space.newbytes(pending_bytes))
802803 except OperationError as e:
803804 if trap_eintr(space, e):
804805 continue
827828 space.call_method(self.w_decoder, "reset")
828829 else:
829830 space.call_method(self.w_decoder, "setstate",
830 space.newtuple([space.wrap(""),
831 space.newtuple([space.newbytes(""),
831832 space.wrap(cookie.dec_flags)]))
832833
833834 def _encoder_setstate(self, space, cookie):
903904 raise oefmt(space.w_TypeError, msg, w_chunk)
904905
905906 self.snapshot = PositionSnapshot(cookie.dec_flags,
906 space.str_w(w_chunk))
907 space.bytes_w(w_chunk))
907908
908909 w_decoded = space.call_method(self.w_decoder, "decode",
909910 w_chunk, space.wrap(cookie.need_eof))
974975 i = 0
975976 while i < len(input):
976977 w_decoded = space.call_method(self.w_decoder, "decode",
977 space.wrap(input[i]))
978 space.newbytes(input[i]))
978979 check_decoded(space, w_decoded)
979980 chars_decoded += len(space.unicode_w(w_decoded))
980981
0 from pypy.interpreter.mixedmodule import MixedModule
1 from rpython.rlib.rvmprof import VMProfPlatformUnsupported
2
3 class Module(MixedModule):
4 """ JitLog the new logging facility """
5 appleveldefs = {
6 }
7
8 interpleveldefs = {
9 'enable': 'interp_jitlog.enable',
10 'disable': 'interp_jitlog.disable',
11 'JitlogError': 'space.fromcache(interp_jitlog.Cache).w_JitlogError',
12 }
0 from pypy.interpreter.error import OperationError
1 from pypy.interpreter.gateway import unwrap_spec
2 from pypy.interpreter.pyframe import PyFrame
3 from pypy.interpreter.pycode import PyCode
4 from pypy.interpreter.baseobjspace import W_Root
5 from rpython.rlib.rjitlog import rjitlog
6 from rpython.rlib import jit
7
8 class Cache:
9 def __init__(self, space):
10 self.w_JitlogError = space.new_exception_class("_jitlog.JitlogError")
11
12 def JitlogError(space, e):
13 w_JitlogError = space.fromcache(Cache).w_JitlogError
14 return OperationError(w_JitlogError, space.wrap(e.msg))
15
16 @unwrap_spec(fileno=int)
17 def enable(space, fileno):
18 """ Enable PyPy's logging facility. """
19 try:
20 rjitlog.enable_jitlog(fileno)
21 except rjitlog.JitlogError, e:
22 raise JitlogError(space, e)
23
24 @jit.dont_look_inside
25 def disable(space):
26 """ Disable PyPy's logging facility. """
27 rjitlog.disable_jitlog()
0 import sys
1 import platform
2 from rpython.tool.udir import udir
3 from pypy.tool.pytest.objspace import gettestobjspace
4 from rpython.rlib.rjitlog import rjitlog as jl
5 from rpython.jit.metainterp.resoperation import opname
6
7 class AppTestJitLog(object):
8 spaceconfig = {'usemodules': ['_jitlog', 'struct']}
9
10 def setup_class(cls):
11 cls.w_tmpfilename = cls.space.wrap(str(udir.join('test__jitlog.1')))
12 cls.w_mark_header = cls.space.newbytes(jl.MARK_JITLOG_HEADER)
13 cls.w_version = cls.space.newbytes(jl.JITLOG_VERSION_16BIT_LE)
14 cls.w_is_32bit = cls.space.wrap(sys.maxint == 2**31-1)
15 cls.w_machine = cls.space.newbytes(platform.machine())
16 cls.w_resops = cls.space.newdict()
17 space = cls.space
18 for key, value in opname.items():
19 space.setitem(cls.w_resops, space.wrap(key), space.wrap(value))
20
21 def test_enable(self):
22 import _jitlog, struct
23 tmpfile = open(self.tmpfilename, 'wb')
24 fileno = tmpfile.fileno()
25 _jitlog.enable(fileno)
26 _jitlog.disable()
27 # no need to clsoe tmpfile, it is done by jitlog
28
29 with open(self.tmpfilename, 'rb') as fd:
30 assert fd.read(1) == self.mark_header
31 assert fd.read(2) == self.version
32 assert bool(ord(fd.read(1))) == self.is_32bit
33 strcount, = struct.unpack('<i', fd.read(4))
34 machine = fd.read(strcount)
35 assert machine == self.machine
36 # resoperations
37 count, = struct.unpack('<h', fd.read(2))
38 opnames = set()
39 for i in range(count):
40 opnum = struct.unpack('<h', fd.read(2))
41 strcount, = struct.unpack('<i', fd.read(4))
42 opname = fd.read(strcount)
43 opnames.append((opnum, opname))
44
45 for opnum, opname in opnames:
46 # must be known resoperation
47 assert opnum in self.resops
48 # the name must equal
49 assert self.resops[opnum] == opname
1919 self.update(string)
2020
2121 def digest_w(self):
22 return self.space.wrap(self.digest())
22 return self.space.newbytes(self.digest())
2323
2424 def hexdigest_w(self):
2525 return self.space.wrap(self.hexdigest())
8282 return space.w_None
8383 except curses_error as e:
8484 raise convert_error(space, e)
85 return space.wrap(result)
85 return space.newbytes(result)
8686
8787 @unwrap_spec(s=str)
8888 def tparm(space, s, args_w):
8989 args = [space.int_w(a) for a in args_w]
9090 try:
91 return space.wrap(_curses_tparm(s, args))
91 return space.newbytes(_curses_tparm(s, args))
9292 except curses_error as e:
9393 raise convert_error(space, e)
112112 pos = c_codecs.pypy_cjk_enc_inbuf_consumed(self.encodebuf)
113113 assert 0 <= pos <= len(object)
114114 self.pending = object[pos:]
115 return space.wrap(output)
115 return space.newbytes(output)
116116
117117
118118 @unwrap_spec(errors="str_or_None")
3939 raise wrap_unicodeencodeerror(space, e, input, self.name)
4040 except RuntimeError:
4141 raise wrap_runtimeerror(space)
42 return space.newtuple([space.wrap(output),
42 return space.newtuple([space.newbytes(output),
4343 space.wrap(len(input))])
4444
4545
6565 space.w_UnicodeDecodeError,
6666 space.newtuple([
6767 space.wrap(name),
68 space.wrap(input),
68 space.newbytes(input),
6969 space.wrap(e.start),
7070 space.wrap(e.end),
7171 space.wrap(e.reason)]))
267267 min = 0;
268268 max = haystacksize;
269269
270 for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1)
270 for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1) {
271271 if (value < haystack[pos].uniseq) {
272 if (max == pos) break;
273 else max = pos;
272 if (max != pos) {
273 max = pos;
274 continue;
275 }
274276 }
275277 else if (value > haystack[pos].uniseq) {
276 if (min == pos) break;
277 else min = pos;
278 if (min != pos) {
279 min = pos;
280 continue;
281 }
278282 }
279 else
280 break;
281
282 if (value == haystack[pos].uniseq)
283 return haystack[pos].code;
284 else
285 return DBCINV;
283 break;
284 }
285
286 if (value == haystack[pos].uniseq) {
287 return haystack[pos].code;
288 }
289 return DBCINV;
286290 }
287291 #endif
288292
121121 space, self.BUFFER_SIZE, maxlength)
122122 try:
123123 if newbuf:
124 return space.wrap(rffi.charpsize2str(newbuf, res))
124 return space.newbytes(rffi.charpsize2str(newbuf, res))
125125 else:
126 return space.wrap(rffi.charpsize2str(self.buffer, res))
126 return space.newbytes(rffi.charpsize2str(self.buffer, res))
127127 finally:
128128 if newbuf:
129129 rffi.free_charp(newbuf)
137137 space, length - offset, PY_SSIZE_T_MAX)
138138 try:
139139 if newbuf:
140 raise BufferTooShort(space, space.wrap(
140 raise BufferTooShort(space, space.newbytes(
141141 rffi.charpsize2str(newbuf, res)))
142142 rwbuffer.setslice(offset, rffi.charpsize2str(self.buffer, res))
143143 finally:
165165 space, self.BUFFER_SIZE, PY_SSIZE_T_MAX)
166166 try:
167167 if newbuf:
168 w_received = space.wrap(rffi.charpsize2str(newbuf, res))
168 w_received = space.newbytes(rffi.charpsize2str(newbuf, res))
169169 else:
170 w_received = space.wrap(rffi.charpsize2str(self.buffer, res))
170 w_received = space.newbytes(rffi.charpsize2str(self.buffer, res))
171171 finally:
172172 if newbuf:
173173 rffi.free_charp(newbuf)
400400 _WriteFile, ERROR_NO_SYSTEM_RESOURCES)
401401 from rpython.rlib import rwin32
402402
403 charp = rffi.str2charp(buf)
404 written_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1,
405 flavor='raw')
406 try:
407 result = _WriteFile(
408 self.handle, rffi.ptradd(charp, offset),
409 size, written_ptr, rffi.NULL)
410
411 if (result == 0 and
412 rwin32.GetLastError_saved() == ERROR_NO_SYSTEM_RESOURCES):
413 raise oefmt(space.w_ValueError,
414 "Cannot send %d bytes over connection", size)
415 finally:
416 rffi.free_charp(charp)
417 lltype.free(written_ptr, flavor='raw')
403 with rffi.scoped_view_charp(buf) as charp:
404 written_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1,
405 flavor='raw')
406 try:
407 result = _WriteFile(
408 self.handle, rffi.ptradd(charp, offset),
409 size, written_ptr, rffi.NULL)
410
411 if (result == 0 and
412 rwin32.GetLastError_saved() == ERROR_NO_SYSTEM_RESOURCES):
413 raise oefmt(space.w_ValueError,
414 "Cannot send %d bytes over connection", size)
415 finally:
416 lltype.free(written_ptr, flavor='raw')
418417
419418 def do_recv_string(self, space, buflength, maxlength):
420419 from pypy.module._multiprocessing.interp_win32 import (
359359 hexdigits = self.getslice(start, i)
360360 try:
361361 val = int(hexdigits, 16)
362 if val & 0xfc00 == 0xd800:
362 if sys.maxunicode > 65535 and 0xd800 <= val <= 0xdfff:
363363 # surrogate pair
364 val = self.decode_surrogate_pair(i, val)
365 i += 6
364 if self.ll_chars[i] == '\\' and self.ll_chars[i+1] == 'u':
365 val = self.decode_surrogate_pair(i, val)
366 i += 6
366367 except ValueError:
367368 self._raise("Invalid \uXXXX escape (char %d)", i-1)
368369 return # help the annotator to know that we'll never go beyond
374375 return i
375376
376377 def decode_surrogate_pair(self, i, highsurr):
377 if self.ll_chars[i] != '\\' or self.ll_chars[i+1] != 'u':
378 self._raise("Unpaired high surrogate at char %d", i)
378 """ uppon enter the following must hold:
379 chars[i] == "\\" and chars[i+1] == "u"
380 """
379381 i += 2
380382 hexdigits = self.getslice(i, i+4)
381383 lowsurr = int(hexdigits, 16) # the possible ValueError is caugth by the caller
182182 expected = u'z\U0001d120x'
183183 res = _pypyjson.loads('"z\\ud834\\udd20x"')
184184 assert res == expected
185
186 def test_surrogate_pair(self):
187 import _pypyjson
188 json = '{"a":"\\uD83D"}'
189 res = _pypyjson.loads(json)
190 assert res == {u'a': u'\ud83d'}
185191
186192 def test_tab_in_string_should_fail(self):
187193 import _pypyjson
1919 def _getfunc(space, CDLL, w_name, w_argtypes, w_restype):
2020 argtypes_w, argtypes, w_restype, restype = unpack_argtypes(
2121 space, w_argtypes, w_restype)
22 if space.isinstance_w(w_name, space.w_str):
22 if (space.isinstance_w(w_name, space.w_str) or
23 space.isinstance_w(w_name, space.w_unicode)):
2324 name = space.str_w(w_name)
2425 try:
2526 func = CDLL.cdll.getpointer(name, argtypes, restype,
1111 handle_signed = handle_all
1212 handle_unsigned = handle_all
1313 handle_pointer = handle_all
14 handle_char = handle_all
14 handle_char = handle_all
1515 handle_unichar = handle_all
1616 handle_longlong = handle_all
1717 handle_char_p = handle_all
1818 handle_unichar_p = handle_all
1919 handle_float = handle_all
2020 handle_singlefloat = handle_all
21
21
2222 def handle_struct(self, w_ffitype, w_structinstance):
2323 self.lastval = w_structinstance
2424
118118
119119 def test_strings(self):
120120 # first, try automatic conversion from applevel
121 self.check(app_types.char_p, self.space.wrap('foo'), 'foo')
122 self.check(app_types.unichar_p, self.space.wrap(u'foo\u1234'), u'foo\u1234')
123 self.check(app_types.unichar_p, self.space.wrap('foo'), u'foo')
121 self.check(app_types.char_p, self.space.newbytes('foo'), 'foo')
122 self.check(app_types.unichar_p, self.space.wrap(u'foo\u1234'), u'foo\u1234')
123 self.check(app_types.unichar_p, self.space.wrap('foo'), u'foo')
124124 # then, try to pass explicit pointers
125125 self.check(app_types.char_p, self.space.wrap(42), 42)
126 self.check(app_types.unichar_p, self.space.wrap(42), 42)
126 self.check(app_types.unichar_p, self.space.wrap(42), 42)
127127
128128
129129
135135 get_signed = get_all
136136 get_unsigned = get_all
137137 get_pointer = get_all
138 get_char = get_all
138 get_char = get_all
139139 get_unichar = get_all
140140 get_longlong = get_all
141141 get_char_p = get_all
143143 get_float = get_all
144144 get_singlefloat = get_all
145145 get_unsigned_which_fits_into_a_signed = get_all
146
146
147147 def convert(self, w_ffitype, val):
148148 self.val = val
149149 return self.do_and_wrap(w_ffitype)
180180 start, stop = self.decodeslice(space, w_slice)
181181 ll_buffer = self.ll_buffer
182182 result = [ll_buffer[i] for i in range(start, stop)]
183 return space.wrap(''.join(result))
183 return space.newbytes(''.join(result))
184184
185185 def setslice(self, space, w_slice, w_value):
186186 start, stop = self.decodeslice(space, w_slice)
11 from pypy.interpreter.baseobjspace import W_Root
22 from pypy.interpreter.error import OperationError, oefmt, wrap_oserror
33 from pypy.interpreter.gateway import interp2app, unwrap_spec
4 from pypy.interpreter.typedef import interp_attrproperty
45 from pypy.interpreter.typedef import TypeDef, GetSetProperty
56
67 from rpython.rlib.clibffi import *
236237 __new__ = interp2app(descr_new_cdll),
237238 ptr = interp2app(W_CDLL.ptr),
238239 getaddressindll = interp2app(W_CDLL.getaddressindll),
240 name = interp_attrproperty('name', W_CDLL),
239241 __doc__ = """ C Dynamically loaded library
240242 use CDLL(libname) to create a handle to a C library (the argument is processed
241243 the same way as dlopen processes it). On such a library you can call:
569571 s = rffi.charp2str(charp_addr)
570572 else:
571573 s = rffi.charp2strn(charp_addr, maxlength)
572 return space.wrap(s)
574 return space.newbytes(s)
573575
574576 @unwrap_spec(address=r_uint, maxlength=int)
575577 def wcharp2unicode(space, address, maxlength=-1):
587589 if maxlength == -1:
588590 return charp2string(space, address)
589591 s = rffi.charpsize2str(rffi.cast(rffi.CCHARP, address), maxlength)
590 return space.wrap(s)
592 return space.newbytes(s)
591593
592594 @unwrap_spec(address=r_uint, maxlength=int)
593595 def wcharp2rawunicode(space, address, maxlength=-1):
12221222 assert z == 43
12231223 arg.free()
12241224
1225 def test_cdll_name(self):
1226 import _rawffi
1227 lib = _rawffi.CDLL(self.lib_name)
1228 assert lib.name == self.lib_name
1229
12251230
12261231 class AppTestAutoFree:
12271232 spaceconfig = dict(usemodules=['_rawffi', 'struct'])
208208 buf = rsocket.inet_aton(ip)
209209 except SocketError as e:
210210 raise converted_error(space, e)
211 return space.wrap(buf)
211 return space.newbytes(buf)
212212
213213 @unwrap_spec(packed=str)
214214 def inet_ntoa(space, packed):
233233 buf = rsocket.inet_pton(family, ip)
234234 except SocketError as e:
235235 raise converted_error(space, e)
236 return space.wrap(buf)
236 return space.newbytes(buf)
237237
238238 @unwrap_spec(family=int, packed=str)
239239 def inet_ntop(space, family, packed):
262262 if space.is_w(w_host, space.w_None):
263263 host = None
264264 elif space.isinstance_w(w_host, space.w_str):
265 host = space.str_w(w_host)
265 host = space.bytes_w(w_host)
266266 elif space.isinstance_w(w_host, space.w_unicode):
267267 w_shost = space.call_method(w_host, "encode", space.wrap("idna"))
268 host = space.str_w(w_shost)
268 host = space.bytes_w(w_shost)
269269 else:
270270 raise oefmt(space.w_TypeError,
271271 "getaddrinfo() argument 1 must be string or None")
276276 elif space.isinstance_w(w_port, space.w_int) or space.isinstance_w(w_port, space.w_long):
277277 port = str(space.int_w(w_port))
278278 elif space.isinstance_w(w_port, space.w_str):
279 port = space.str_w(w_port)
279 port = space.bytes_w(w_port)
280280 else:
281281 raise oefmt(space.w_TypeError,
282282 "getaddrinfo() argument 2 must be integer or string")
150150
151151
152152 class W_Socket(W_Root):
153 w_tb = None # String representation of the traceback at creation time
154
153155 def __init__(self, space, sock):
156 self.space = space
154157 self.sock = sock
155158 register_socket(space, sock)
159 if self.space.sys.track_resources:
160 self.w_tb = self.space.format_traceback()
161 self.register_finalizer(space)
162
163 def _finalize_(self):
164 is_open = self.sock.fd >= 0
165 if is_open and self.space.sys.track_resources:
166 w_repr = self.space.repr(self)
167 str_repr = self.space.str_w(w_repr)
168 w_msg = self.space.wrap("WARNING: unclosed " + str_repr)
169 self.space.resource_warning(w_msg, self.w_tb)
156170
157171 def get_type_w(self, space):
158172 return space.wrap(self.sock.type)
295309 except SocketError as e:
296310 raise converted_error(space, e)
297311 buflen = space.int_w(w_buflen)
298 return space.wrap(self.sock.getsockopt(level, optname, buflen))
312 return space.newbytes(self.sock.getsockopt(level, optname, buflen))
299313
300314 def gettimeout_w(self, space):
301315 """gettimeout() -> timeout
344358 data = self.sock.recv(buffersize, flags)
345359 except SocketError as e:
346360 raise converted_error(space, e)
347 return space.wrap(data)
361 return space.newbytes(data)
348362
349363 @unwrap_spec(buffersize='nonnegint', flags=int)
350364 def recvfrom_w(self, space, buffersize, flags=0):
358372 w_addr = addr_as_object(addr, self.sock.fd, space)
359373 else:
360374 w_addr = space.w_None
361 return space.newtuple([space.wrap(data), w_addr])
375 return space.newtuple([space.newbytes(data), w_addr])
362376 except SocketError as e:
363377 raise converted_error(space, e)
364378
435449 except OperationError as e:
436450 if e.async(space):
437451 raise
438 optval = space.str_w(w_optval)
452 optval = space.bytes_w(w_optval)
439453 try:
440454 self.sock.setsockopt(level, optname, optval)
441455 except SocketError as e:
00 import sys, os
1 import py
1 import pytest
22 from pypy.tool.pytest.objspace import gettestobjspace
3 from pypy.interpreter.gateway import interp2app
4 from pypy.module._file.test.test_file import regex_search
35 from rpython.tool.udir import udir
46 from rpython.rlib import rsocket
57 from rpython.rtyper.lltypesystem import lltype, rffi
1113 mod.w_socket = space.appexec([], "(): import _socket as m; return m")
1214 mod.path = udir.join('fd')
1315 mod.path.write('fo')
14 mod.raises = py.test.raises # make raises available from app-level tests
15 mod.skip = py.test.skip
1616
1717 def test_gethostname():
1818 host = space.appexec([w_socket], "(_socket): return _socket.gethostname()")
4040 for host in ["localhost", "127.0.0.1", "::1"]:
4141 if host == "::1" and not ipv6:
4242 from pypy.interpreter.error import OperationError
43 with py.test.raises(OperationError):
43 with pytest.raises(OperationError):
4444 space.appexec([w_socket, space.wrap(host)],
4545 "(_socket, host): return _socket.gethostbyaddr(host)")
4646 continue
5656 assert space.unwrap(port) == 25
5757 # 1 arg version
5858 if sys.version_info < (2, 4):
59 py.test.skip("getservbyname second argument is not optional before python 2.4")
59 pytest.skip("getservbyname second argument is not optional before python 2.4")
6060 port = space.appexec([w_socket, space.wrap(name)],
6161 "(_socket, name): return _socket.getservbyname(name)")
6262 assert space.unwrap(port) == 25
6363
6464 def test_getservbyport():
6565 if sys.version_info < (2, 4):
66 py.test.skip("getservbyport does not exist before python 2.4")
66 pytest.skip("getservbyport does not exist before python 2.4")
6767 port = 25
6868 # 2 args version
6969 name = space.appexec([w_socket, space.wrap(port)],
9696 def test_fromfd():
9797 # XXX review
9898 if not hasattr(socket, 'fromfd'):
99 py.test.skip("No socket.fromfd on this platform")
99 pytest.skip("No socket.fromfd on this platform")
100100 orig_fd = path.open()
101101 fd = space.appexec([w_socket, space.wrap(orig_fd.fileno()),
102102 space.wrap(socket.AF_INET), space.wrap(socket.SOCK_STREAM),
156156
157157 def test_pton_ntop_ipv4():
158158 if not hasattr(socket, 'inet_pton'):
159 py.test.skip('No socket.inet_pton on this platform')
159 pytest.skip('No socket.inet_pton on this platform')
160160 tests = [
161161 ("123.45.67.89", "\x7b\x2d\x43\x59"),
162162 ("0.0.0.0", "\x00" * 4),
172172
173173 def test_ntop_ipv6():
174174 if not hasattr(socket, 'inet_pton'):
175 py.test.skip('No socket.inet_pton on this platform')
175 pytest.skip('No socket.inet_pton on this platform')
176176 if not socket.has_ipv6:
177 py.test.skip("No IPv6 on this platform")
177 pytest.skip("No IPv6 on this platform")
178178 tests = [
179179 ("\x00" * 16, "::"),
180180 ("\x01" * 16, ":".join(["101"] * 8)),
193193
194194 def test_pton_ipv6():
195195 if not hasattr(socket, 'inet_pton'):
196 py.test.skip('No socket.inet_pton on this platform')
196 pytest.skip('No socket.inet_pton on this platform')
197197 if not socket.has_ipv6:
198 py.test.skip("No IPv6 on this platform")
198 pytest.skip("No IPv6 on this platform")
199199 tests = [
200200 ("\x00" * 16, "::"),
201201 ("\x01" * 16, ":".join(["101"] * 8)),
214214 assert space.unwrap(w_packed) == packed
215215
216216 def test_has_ipv6():
217 py.test.skip("has_ipv6 is always True on PyPy for now")
217 pytest.skip("has_ipv6 is always True on PyPy for now")
218218 res = space.appexec([w_socket], "(_socket): return _socket.has_ipv6")
219219 assert space.unwrap(res) == socket.has_ipv6
220220
228228 w_l = space.appexec([w_socket, space.wrap(host), space.wrap(port)],
229229 "(_socket, host, port): return _socket.getaddrinfo(host, long(port))")
230230 assert space.unwrap(w_l) == info
231 py.test.skip("Unicode conversion is too slow")
231 pytest.skip("Unicode conversion is too slow")
232232 w_l = space.appexec([w_socket, space.wrap(unicode(host)), space.wrap(port)],
233233 "(_socket, host, port): return _socket.getaddrinfo(host, port)")
234234 assert space.unwrap(w_l) == info
249249 def test_addr_raw_packet():
250250 from pypy.module._socket.interp_socket import addr_as_object
251251 if not hasattr(rsocket._c, 'sockaddr_ll'):
252 py.test.skip("posix specific test")
252 pytest.skip("posix specific test")
253253 # HACK: To get the correct interface number of lo, which in most cases is 1,
254254 # but can be anything (i.e. 39), we need to call the libc function
255255 # if_nametoindex to get the correct index
313313 def setup_class(cls):
314314 cls.space = space
315315 cls.w_udir = space.wrap(str(udir))
316 cls.w_regex_search = space.wrap(interp2app(regex_search))
316317
317318 def teardown_class(cls):
318319 if not cls.runappdirect:
400401 s.close()
401402 if os.name != 'nt':
402403 raises(OSError, os.close, fileno)
404
405 def test_socket_track_resources(self):
406 import _socket, os, gc, sys, cStringIO
407 s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
408 fileno = s.fileno()
409 assert s.fileno() >= 0
410 s.close()
411 assert s.fileno() < 0
412 s.close()
413 if os.name != 'nt':
414 raises(OSError, os.close, fileno)
415
416 @pytest.mark.skipif("config.option.runappdirect")
417 def test_track_resources(self):
418 import os, gc, sys, cStringIO
419 import _socket
420 if '__pypy__' not in sys.builtin_module_names:
421 skip("pypy specific test")
422 #
423 def fn(flag1, flag2, do_close=False):
424 sys.pypy_set_track_resources(flag1)
425 mysock = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
426 sys.pypy_set_track_resources(flag2)
427 buf = cStringIO.StringIO()
428 preverr = sys.stderr
429 try:
430 sys.stderr = buf
431 if do_close:
432 mysock.close()
433 del mysock
434 gc.collect() # force __del__ to be called
435 finally:
436 sys.stderr = preverr
437 sys.pypy_set_track_resources(False)
438 return buf.getvalue()
439
440 # check with track_resources disabled
441 assert fn(False, False) == ""
442 #
443 # check that we don't get the warning if we actually closed the socket
444 msg = fn(True, True, do_close=True)
445 assert msg == ''
446 #
447 # check with track_resources enabled
448 msg = fn(True, True)
449 assert self.regex_search(r"""
450 WARNING: unclosed <socket object, .*>
451 Created at \(most recent call last\):
452 File ".*", line .*, in test_track_resources
453 File ".*", line .*, in fn
454 """, msg)
455 #
456 # track_resources is enabled after the construction of the socket. in
457 # this case, the socket is not registered for finalization at all, so
458 # we don't see a message
459 msg = fn(False, True)
460 assert msg == ''
461
403462
404463 def test_socket_close_error(self):
405464 import _socket, os
629688 class AppTestNetlink:
630689 def setup_class(cls):
631690 if not hasattr(os, 'getpid'):
632 py.test.skip("AF_NETLINK needs os.getpid()")
691 pytest.skip("AF_NETLINK needs os.getpid()")
633692 w_ok = space.appexec([], "(): import _socket; " +
634693 "return hasattr(_socket, 'AF_NETLINK')")
635694 if not space.is_true(w_ok):
636 py.test.skip("no AF_NETLINK on this platform")
695 pytest.skip("no AF_NETLINK on this platform")
637696 cls.space = space
638697
639698 def test_connect_to_kernel_netlink_routing_socket(self):
649708 class AppTestPacket:
650709 def setup_class(cls):
651710 if not hasattr(os, 'getuid') or os.getuid() != 0:
652 py.test.skip("AF_PACKET needs to be root for testing")
711 pytest.skip("AF_PACKET needs to be root for testing")
653712 w_ok = space.appexec([], "(): import _socket; " +
654713 "return hasattr(_socket, 'AF_PACKET')")
655714 if not space.is_true(w_ok):
656 py.test.skip("no AF_PACKET on this platform")
715 pytest.skip("no AF_PACKET on this platform")
657716 cls.space = space
658717
659718 def test_convert_between_tuple_and_sockaddr_ll(self):
670729
671730 class AppTestSocketTCP:
672731 HOST = 'localhost'
673
674 def setup_class(cls):
675 cls.space = space
732 spaceconfig = {'usemodules': ['_socket', 'array']}
676733
677734 def setup_method(self, method):
678 w_HOST = space.wrap(self.HOST)
679 self.w_serv = space.appexec([w_socket, w_HOST],
735 w_HOST = self.space.wrap(self.HOST)
736 self.w_serv =self.space.appexec([w_socket, w_HOST],
680737 '''(_socket, HOST):
681738 serv = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM)
682739 serv.bind((HOST, 0))
686743
687744 def teardown_method(self, method):
688745 if hasattr(self, 'w_serv'):
689 space.appexec([self.w_serv], '(serv): serv.close()')
746 self.space.appexec([self.w_serv], '(serv): serv.close()')
690747 self.w_serv = None
691748
692749 def test_timeout(self):
802859
803860
804861 class AppTestErrno:
805 def setup_class(cls):
806 cls.space = space
862 spaceconfig = {'usemodules': ['_socket']}
807863
808864 def test_errno(self):
809865 from socket import socket, AF_INET, SOCK_STREAM, error
3535 def slice_w(space, ctx, start, end, w_default):
3636 if 0 <= start <= end:
3737 if isinstance(ctx, rsre_core.BufMatchContext):
38 return space.wrap(ctx._buffer.getslice(start, end, 1, end-start))
38 return space.newbytes(ctx._buffer.getslice(start, end, 1,
39 end-start))
3940 if isinstance(ctx, rsre_core.StrMatchContext):
40 return space.wrap(ctx._string[start:end])
41 return space.newbytes(ctx._string[start:end])
4142 elif isinstance(ctx, rsre_core.UnicodeMatchContext):
42 return space.wrap(ctx._unicodestr[start:end])
43 return space.newunicode(ctx._unicodestr[start:end])
4344 else:
4445 # unreachable
4546 raise SystemError
241242 space.isinstance_w(w_string, space.w_unicode) and literal)
242243 else:
243244 try:
244 filter_as_string = space.str_w(w_ptemplate)
245 filter_as_string = space.bytes_w(w_ptemplate)
245246 except OperationError as e:
246247 if e.async(space):
247248 raise
330331 strbuilder, unicodebuilder, last_pos, ctx.end)
331332 if use_builder:
332333 if strbuilder is not None:
333 return space.wrap(strbuilder.build()), n
334 return space.newbytes(strbuilder.build()), n
334335 else:
335336 assert unicodebuilder is not None
336 return space.wrap(unicodebuilder.build()), n
337 return space.newunicode(unicodebuilder.build()), n
337338 else:
338339 if space.isinstance_w(w_string, space.w_unicode):
339 w_emptystr = space.wrap(u'')
340 w_emptystr = space.newunicode(u'')
340341 else:
341 w_emptystr = space.wrap('')
342 w_emptystr = space.newbytes('')
342343 w_item = space.call_method(w_emptystr, 'join',
343344 space.newlist(sublist_w))
344345 return w_item, n
564565 def fget_string(self, space):
565566 ctx = self.ctx
566567 if isinstance(ctx, rsre_core.BufMatchContext):
567 return space.wrap(ctx._buffer.as_str())
568 return space.newbytes(ctx._buffer.as_str())
568569 elif isinstance(ctx, rsre_core.StrMatchContext):
569 return space.wrap(ctx._string)
570 return space.newbytes(ctx._string)
570571 elif isinstance(ctx, rsre_core.UnicodeMatchContext):
571 return space.wrap(ctx._unicodestr)
572 return space.newunicode(ctx._unicodestr)
572573 else:
573574 raise SystemError
574575
134134
135135 def __init__(self, ctx, protos):
136136 self.protos = protos
137 self.buf, self.pinned, self.is_raw = rffi.get_nonmovingbuffer(protos)
137 self.buf, self.bufflag = rffi.get_nonmovingbuffer(protos)
138138 NPN_STORAGE.set(rffi.cast(lltype.Unsigned, self.buf), self)
139139
140140 # set both server and client callbacks, because the context
146146
147147 def __del__(self):
148148 rffi.free_nonmovingbuffer(
149 self.protos, self.buf, self.pinned, self.is_raw)
149 self.protos, self.buf, self.bufflag)
150150
151151 @staticmethod
152152 def advertiseNPN_cb(s, data_ptr, len_ptr, args):
180180
181181 def __init__(self, ctx, protos):
182182 self.protos = protos
183 self.buf, self.pinned, self.is_raw = rffi.get_nonmovingbuffer(protos)
183 self.buf, self.bufflag = rffi.get_nonmovingbuffer(protos)
184184 ALPN_STORAGE.set(rffi.cast(lltype.Unsigned, self.buf), self)
185185
186186 with rffi.scoped_str2charp(protos) as protos_buf:
192192
193193 def __del__(self):
194194 rffi.free_nonmovingbuffer(
195 self.protos, self.buf, self.pinned, self.is_raw)
195 self.protos, self.buf, self.bufflag)
196196
197197 @staticmethod
198198 def selectALPN_cb(s, out_ptr, outlen_ptr, client, client_len, args):
227227
228228 Mix string into the OpenSSL PRNG state. entropy (a float) is a lower
229229 bound on the entropy contained in string."""
230 with rffi.scoped_str2charp(string) as buf:
230 with rffi.scoped_nonmovingbuffer(string) as buf:
231231 libssl_RAND_add(buf, len(string), entropy)
232232
233233 def RAND_status(space):
665665 length = libssl_SSL_get_peer_finished(self.ssl, buf, CB_MAXLEN)
666666
667667 if length > 0:
668 return space.wrap(rffi.charpsize2str(buf, intmask(length)))
668 return space.newbytes(rffi.charpsize2str(buf, intmask(length)))
669669
670670 def descr_get_context(self, space):
671671 return self.w_ctx
706706 if length < 0:
707707 raise _ssl_seterror(space, None, 0)
708708 try:
709 return space.wrap(rffi.charpsize2str(buf_ptr[0], length))
709 return space.newbytes(rffi.charpsize2str(buf_ptr[0], length))
710710 finally:
711711 libssl_OPENSSL_free(buf_ptr[0])
712712
925925 if length < 0:
926926 raise _ssl_seterror(space, None, 0)
927927 try:
928 w_value = space.wrap(rffi.charpsize2str(buf_ptr[0], length))
928 w_value = space.newbytes(rffi.charpsize2str(buf_ptr[0], length))
929929 w_value = space.call_method(w_value, "decode", space.wrap("utf-8"))
930930 finally:
931931 libssl_OPENSSL_free(buf_ptr[0])
12311231 w_ssl_socket, space.w_None, w_ctx)
12321232
12331233 else:
1234 w_servername = space.wrapbytes(rffi.charp2str(servername))
1234 w_servername = space.newbytes(rffi.charp2str(servername))
12351235 try:
12361236 w_servername_idna = space.call_method(
12371237 w_servername, 'decode', space.wrap('idna'))
17771777 if not path:
17781778 return space.w_None
17791779 else:
1780 return space.wrapbytes(rffi.charp2str(path))
1780 return space.newbytes(rffi.charp2str(path))
17811781
17821782 def get_default_verify_paths(space):
17831783 return space.newtuple([
7373
7474 def w_parseKeyUsage(space, pCertCtx, flags):
7575 with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as size_ptr:
76 if not CertGetEnhancedKeyUsage(pCertCtx, flags,
76 if not CertGetEnhancedKeyUsage(pCertCtx, flags,
7777 lltype.nullptr(CERT_ENHKEY_USAGE), size_ptr):
7878 last_error = rwin32.lastSavedWindowsError()
7979 if last_error.winerror == CRYPT_E_NOT_FOUND:
119119 pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)
120120 if not pCertCtx:
121121 break
122 w_cert = space.wrapbytes(
122 w_cert = space.newbytes(
123123 rffi.charpsize2str(pCertCtx.c_pbCertEncoded,
124124 intmask(pCertCtx.c_cbCertEncoded)))
125125 w_enc = w_certEncodingType(space, pCertCtx.c_dwCertEncodingType)
161161 pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)
162162 if not pCrlCtx:
163163 break
164 w_crl = space.wrapbytes(
164 w_crl = space.newbytes(
165165 rffi.charpsize2str(pCrlCtx.c_pbCrlEncoded,
166166 intmask(pCrlCtx.c_cbCrlEncoded)))
167167 w_enc = w_certEncodingType(space, pCrlCtx.c_dwCertEncodingType)
22 from pypy.interpreter.pyframe import PyFrame
33 from pypy.interpreter.pycode import PyCode
44 from pypy.interpreter.baseobjspace import W_Root
5 from rpython.rlib import rvmprof
5 from rpython.rlib import rvmprof, jit
66
77 # ____________________________________________________________
88
22 from pypy.tool.pytest.objspace import gettestobjspace
33
44 class AppTestVMProf(object):
5 spaceconfig = {'usemodules': ['_vmprof', 'struct']}
6
57 def setup_class(cls):
6 cls.space = gettestobjspace(usemodules=['_vmprof', 'struct'])
78 cls.w_tmpfilename = cls.space.wrap(str(udir.join('test__vmprof.1')))
89 cls.w_tmpfilename2 = cls.space.wrap(str(udir.join('test__vmprof.2')))
910
1617 import struct, sys, gc
1718
1819 WORD = struct.calcsize('l')
19
20
2021 def count(s):
2122 i = 0
2223 count = 0
4344 else:
4445 raise AssertionError(ord(s[i]))
4546 return count
46
47
4748 import _vmprof
4849 gc.collect() # try to make the weakref list deterministic
4950 gc.collect() # by freeing all dead code objects
357357
358358 elif typ == rwinreg.REG_SZ or typ == rwinreg.REG_EXPAND_SZ:
359359 if not buflen:
360 return space.wrap("")
361 s = rffi.charp2strn(rffi.cast(rffi.CCHARP, buf), buflen)
362 return space.wrap(s)
360 s = ""
361 else:
362 # may or may not have a trailing NULL in the buffer.
363 buf = rffi.cast(rffi.CCHARP, buf)
364 if buf[buflen - 1] == '\x00':
365 buflen -= 1
366 s = rffi.charp2strn(buf, buflen)
367 w_s = space.wrap(s)
368 return space.call_method(w_s, 'decode', space.wrap('mbcs'))
363369
364370 elif typ == rwinreg.REG_MULTI_SZ:
365371 if not buflen:
379385 return space.newlist(l)
380386
381387 else: # REG_BINARY and all other types
382 return space.wrap(rffi.charpsize2str(buf, buflen))
388 return space.newbytes(rffi.charpsize2str(buf, buflen))
383389
384390 @unwrap_spec(value_name=str, typ=int)
385391 def SetValueEx(space, w_hkey, value_name, w_reserved, typ, w_value):
459465 return space.newtuple([
460466 convert_from_regdata(space, databuf,
461467 length, retType[0]),
462 space.wrap(retType[0]),
468 space.wrap(intmask(retType[0])),
463469 ])
464470
465471 @unwrap_spec(subkey=str)
611617 space.wrap(rffi.charp2str(valuebuf)),
612618 convert_from_regdata(space, databuf,
613619 length, retType[0]),
614 space.wrap(retType[0]),
620 space.wrap(intmask(retType[0])),
615621 ])
616622
617623 @unwrap_spec(index=int)
150150
151151 def test_readValues(self):
152152 from _winreg import OpenKey, EnumValue, QueryValueEx, EnumKey
153 from _winreg import REG_SZ, REG_EXPAND_SZ
153154 key = OpenKey(self.root_key, self.test_key_name)
154155 sub_key = OpenKey(key, "sub_key")
155156 index = 0
163164 assert index == len(self.test_data)
164165
165166 for name, value, type in self.test_data:
166 assert QueryValueEx(sub_key, name) == (value, type)
167 result = QueryValueEx(sub_key, name)
168 assert result == (value, type)
169 if type == REG_SZ or type == REG_EXPAND_SZ:
170 assert isinstance(result[0], unicode) # not string
167171
168172 assert EnumKey(key, 0) == "sub_key"
169173 raises(EnvironmentError, EnumKey, key, 1)
224224 """
225225 size = self.len
226226 if size == 0:
227 return space.wrap('')
227 return space.newbytes('')
228228 cbuf = self._charbuf_start()
229229 s = rffi.charpsize2str(cbuf, size * self.itemsize)
230230 self._charbuf_stop()
231 return self.space.wrap(s)
231 return self.space.newbytes(s)
232232
233233 def descr_fromstring(self, space, w_s):
234234 """ fromstring(string)
262262 except OverflowError:
263263 raise MemoryError
264264 w_item = space.call_method(w_f, 'read', space.wrap(size))
265 item = space.str_w(w_item)
265 item = space.bytes_w(w_item)
266266 if len(item) < size:
267267 n = len(item) % self.itemsize
268268 elems = max(0, len(item) - (len(item) % self.itemsize))
337337 else:
338338 args = [space.wrap(self.typecode)]
339339 try:
340 dct = space.getattr(self, space.wrap('__dict__'))
340 w_dict = space.getattr(self, space.wrap('__dict__'))
341341 except OperationError:
342 dct = space.w_None
343 return space.newtuple([space.type(self), space.newtuple(args), dct])
342 w_dict = space.w_None
343 return space.newtuple([space.type(self), space.newtuple(args), w_dict])
344344
345345 def descr_copy(self, space):
346346 """ copy(array)
7070 if leftbits != 0:
7171 raise_Error(space, "Incorrect padding")
7272
73 return space.wrap(res.build())
73 return space.newbytes(res.build())
7474
7575 # ____________________________________________________________
7676
109109 res.append(table_b2a_base64[(leftchar & 0xf) << 2])
110110 res.append(PAD)
111111 res.append('\n')
112 return space.wrap(res.build())
112 return space.newbytes(res.build())
2323 for c in data:
2424 res.append(_value2char(ord(c) >> 4))
2525 res.append(_value2char(ord(c) & 0xf))
26 return space.wrap(res.build())
26 return space.newbytes(res.build())
2727
2828 # ____________________________________________________________
2929
5252 a = _char2value(space, hexstr[i])
5353 b = _char2value(space, hexstr[i+1])
5454 res.append(chr((a << 4) | b))
55 return space.wrap(res.build())
55 return space.newbytes(res.build())
1010 FAIL = 0x7d
1111
1212 table_a2b_hqx = [
13 #^@ ^A ^B ^C ^D ^E ^F ^G
14 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
15 #\b \t \n ^K ^L \r ^N ^O
13 #^@ ^A ^B ^C ^D ^E ^F ^G
14 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
15 #\b \t \n ^K ^L \r ^N ^O
1616 FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
17 #^P ^Q ^R ^S ^T ^U ^V ^W
18 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
19 #^X ^Y ^Z ^[ ^\ ^] ^^ ^_
20 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
21 # ! " # $ % & '
17 #^P ^Q ^R ^S ^T ^U ^V ^W
18 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
19 #^X ^Y ^Z ^[ ^\ ^] ^^ ^_
20 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
21 # ! " # $ % & '
2222 FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
23 #( ) * + , - . /
23 #( ) * + , - . /
2424 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
25 #0 1 2 3 4 5 6 7
25 #0 1 2 3 4 5 6 7
2626 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
27 #8 9 : ; < = > ?
27 #8 9 : ; < = > ?
2828 0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
29 #@ A B C D E F G
29 #@ A B C D E F G
3030 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
31 #H I J K L M N O
31 #H I J K L M N O
3232 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
33 #P Q R S T U V W
33 #P Q R S T U V W
3434 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
35 #X Y Z [ \ ] ^ _
35 #X Y Z [ \ ] ^ _
3636 0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
37 #` a b c d e f g
37 #` a b c d e f g
3838 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
39 #h i j k l m n o
39 #h i j k l m n o
4040 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
41 #p q r s t u v w
41 #p q r s t u v w
4242 0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
43 #x y z { | } ~ ^?
43 #x y z { | } ~ ^?
4444 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
4545 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
4646 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
9696 else:
9797 if pending_bits > 0:
9898 raise_Incomplete(space, 'String has incomplete number of bytes')
99 return space.newtuple([space.wrap(res.build()), space.wrap(done)])
99 return space.newtuple([space.newbytes(res.build()), space.wrap(done)])
100100
101101 # ____________________________________________________________
102102
127127 if leftbits > 0:
128128 leftchar <<= (6 - leftbits)
129129 res.append(hqx_encoding[leftchar & 0x3f])
130 return space.wrap(res.build())
130 return space.newbytes(res.build())
131131
132132 # ____________________________________________________________
133133
149149 lastpushed = ord(c)
150150 else:
151151 if i == end:
152 raise_Incomplete(space, 'String ends with the RLE code \x90')
152 raise_Incomplete(space, 'String ends with the RLE code \\x90')
153153 count = ord(hexbin[i]) - 1
154154 i += 1
155155 if count < 0:
157157 lastpushed = 0x90
158158 else:
159159 if lastpushed < 0:
160 raise_Error(space, 'String starts with the RLE code \x90')
160 raise_Error(space, 'String starts with the RLE code \\x90')
161161 res.append_multiple_char(chr(lastpushed), count)
162 return space.wrap(res.build())
162 return space.newbytes(res.build())
163163
164164 # ____________________________________________________________
165165
196196 # string that rledecode_hqx() would expand back to 'data', there are
197197 # some programs somewhere that would start failing obscurely in rare
198198 # cases.
199 return space.wrap(res.build())
199 return space.newbytes(res.build())
200200
201201 # ____________________________________________________________
202202
5555 if header and c == '_':
5656 c = ' '
5757 odata.append(c)
58 return space.wrap(odata.build())
58 return space.newbytes(odata.build())
5959
6060 # ____________________________________________________________
6161
158158 odata.append(c)
159159 inp += 1
160160
161 return space.wrap(odata.build())
161 return space.newbytes(odata.build())
5353 remaining = length - res.getlength()
5454 if remaining > 0:
5555 res.append_multiple_char('\x00', remaining)
56 return space.wrap(res.build())
56 return space.newbytes(res.build())
5757
5858 # ____________________________________________________________
5959
8585 res.append(chr(0x20 + (C & 0x3F)))
8686
8787 res.append('\n')
88 return space.wrap(res.build())
88 return space.newbytes(res.build())
556556 datasize = len(data)
557557
558558 if datasize == 0:
559 return self.space.wrap("")
559 return self.space.newbytes("")
560560
561561 if not self.running:
562562 raise oefmt(self.space.w_ValueError,
581581 out.prepare_next_chunk()
582582
583583 res = out.make_result_string()
584 return self.space.wrap(res)
584 return self.space.newbytes(res)
585585
586586 def flush(self):
587587 if not self.running:
601601 out.prepare_next_chunk()
602602
603603 res = out.make_result_string()
604 return self.space.wrap(res)
604 return self.space.newbytes(res)
605605
606606 W_BZ2Compressor.typedef = TypeDef("BZ2Compressor",
607607 __doc__ = W_BZ2Compressor.__doc__,
668668 raise oefmt(self.space.w_EOFError,
669669 "end of stream was already found")
670670 if data == '':
671 return self.space.wrap('')
671 return self.space.newbytes('')
672672
673673 in_bufsize = len(data)
674674
697697 out.prepare_next_chunk()
698698
699699 res = out.make_result_string()
700 return self.space.wrap(res)
700 return self.space.newbytes(res)
701701
702702
703703 W_BZ2Decompressor.typedef = TypeDef("BZ2Decompressor",
536536 releasegil=ts_helper,
537537 compilation_info=backend.eci)
538538 def c_charp2stdstring(space, svalue):
539 charp = rffi.str2charp(svalue)
540 result = _c_charp2stdstring(charp)
541 rffi.free_charp(charp)
539 with rffi.scoped_view_charp(svalue) as charp:
540 result = _c_charp2stdstring(charp)
542541 return result
543542 _c_stdstring2stdstring = rffi.llexternal(
544543 "cppyy_stdstring2stdstring",
8181 releasegil=ts_helper,
8282 compilation_info=eci)
8383 def c_charp2TString(space, svalue):
84 charp = rffi.str2charp(svalue)
85 result = _c_charp2TString(charp)
86 rffi.free_charp(charp)
84 with rffi.scoped_view_charp(svalue) as charp:
85 result = _c_charp2TString(charp)
8786 return result
8887 _c_TString2TString = rffi.llexternal(
8988 "cppyy_TString2TString",
6464 else: # only other use is sring
6565 n = len(obj._string)
6666 assert raw_string == rffi.cast(rffi.CCHARP, 0)
67 # XXX could use rffi.get_nonmovingbuffer_final_null()
6768 raw_string = rffi.str2charp(obj._string)
6869 data = rffi.cast(rffi.CCHARPP, data)
6970 data[0] = raw_string
174174 "__new__" : make_new(class_name),
175175 }
176176 pycppclass = metacpp(class_name, _drop_cycles(bases), d)
177
177
178178 # cache result early so that the class methods can find the class itself
179179 setattr(scope, final_class_name, pycppclass)
180180
191191 for dm_name in cppclass.get_datamember_names():
192192 cppdm = cppclass.get_datamember(dm_name)
193193
194 # here, setattr() can not be used, because a data member can shadow one in
195 # its base class, resulting in the __set__() of its base class being called
196 # by setattr(); so, store directly on the dictionary
197 pycppclass.__dict__[dm_name] = cppdm
194 setattr(pycppclass, dm_name, cppdm)
198195 import cppyy
199196 if cppyy._is_static(cppdm): # TODO: make this a method of cppdm
200 metacpp.__dict__[dm_name] = cppdm
197 setattr(metacpp, dm_name, cppdm)
201198
202199 # the call to register will add back-end specific pythonizations and thus
203200 # needs to run first, so that the generic pythonizations can use them
412409 lib = cppyy._load_dictionary(name)
413410 _loaded_dictionaries[name] = lib
414411 return lib
415
412
416413 def _init_pythonify():
417414 # cppyy should not be loaded at the module level, as that will trigger a
418415 # call to space.getbuiltinmodule(), which will cause cppyy to be loaded
1010 from rpython.rtyper.annlowlevel import llhelper
1111 from rpython.rlib.objectmodel import we_are_translated, keepalive_until_here
1212 from rpython.rlib.objectmodel import dont_inline
13 from rpython.rlib.rfile import (FILEP, c_fread, c_fclose, c_fwrite,
14 c_fdopen, c_fileno,
15 c_fopen)# for tests
1316 from rpython.translator import cdir
1417 from rpython.translator.tool.cbuild import ExternalCompilationInfo
1518 from rpython.translator.gensupp import NameManager
8487 assert CONST_WSTRING == rffi.CWCHARP
8588
8689 # FILE* interface
87 FILEP = rffi.COpaquePtr('FILE')
8890
8991 if sys.platform == 'win32':
9092 dash = '_'
9193 else:
9294 dash = ''
93 fileno = rffi.llexternal(dash + 'fileno', [FILEP], rffi.INT)
94 fopen = rffi.llexternal('fopen', [CONST_STRING, CONST_STRING], FILEP)
95 fdopen = rffi.llexternal(dash + 'fdopen', [rffi.INT, CONST_STRING],
96 FILEP, save_err=rffi.RFFI_SAVE_ERRNO)
97
98 _fclose = rffi.llexternal('fclose', [FILEP], rffi.INT)
95
9996 def fclose(fp):
100 if not is_valid_fd(fileno(fp)):
97 if not is_valid_fd(c_fileno(fp)):
10198 return -1
102 return _fclose(fp)
103
104 _fwrite = rffi.llexternal('fwrite',
105 [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
106 rffi.SIZE_T)
99 return c_fclose(fp)
100
107101 def fwrite(buf, sz, n, fp):
108 validate_fd(fileno(fp))
109 return _fwrite(buf, sz, n, fp)
110
111 _fread = rffi.llexternal('fread',
112 [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
113 rffi.SIZE_T)
102 validate_fd(c_fileno(fp))
103 return c_fwrite(buf, sz, n, fp)
104
114105 def fread(buf, sz, n, fp):
115 validate_fd(fileno(fp))
116 return _fread(buf, sz, n, fp)
106 validate_fd(c_fileno(fp))
107 return c_fread(buf, sz, n, fp)
117108
118109 _feof = rffi.llexternal('feof', [FILEP], rffi.INT)
119110 def feof(fp):
120 validate_fd(fileno(fp))
111 validate_fd(c_fileno(fp))
121112 return _feof(fp)
122113
123114 def is_valid_fp(fp):
124 return is_valid_fd(fileno(fp))
115 return is_valid_fd(c_fileno(fp))
125116
126117 pypy_decl = 'pypy_decl.h'
127118
128119 constant_names = """
129120 Py_TPFLAGS_READY Py_TPFLAGS_READYING Py_TPFLAGS_HAVE_GETCHARBUFFER
130121 METH_COEXIST METH_STATIC METH_CLASS Py_TPFLAGS_BASETYPE
131 METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O
132 Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS
122 METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O Py_TPFLAGS_HAVE_INPLACEOPS
123 Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_HAVE_NEWBUFFER
133124 Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES
134125 """.split()
135126 for name in constant_names:
267258
268259 # extract the signature from the (CPython-level) code object
269260 from pypy.interpreter import pycode
270 argnames, varargname, kwargname = pycode.cpython_code_signature(callable.func_code)
271
272 assert argnames[0] == 'space'
261 sig = pycode.cpython_code_signature(callable.func_code)
262 assert sig.argnames[0] == 'space'
263 self.argnames = sig.argnames[1:]
273264 if gil == 'pygilstate_ensure':
274 assert argnames[-1] == 'previous_state'
275 del argnames[-1]
276 self.argnames = argnames[1:]
265 assert self.argnames[-1] == 'previous_state'
266 del self.argnames[-1]
277267 assert len(self.argnames) == len(self.argtypes)
268
278269 self.gil = gil
279270 self.result_borrowed = result_borrowed
280271 self.result_is_ll = result_is_ll
657648 #('smalltable', rffi.CFixedArray(Py_ssize_t, 2)),
658649 ('internal', rffi.VOIDP)
659650 ))
651 Py_bufferP = lltype.Ptr(Py_buffer)
660652
661653 @specialize.memo()
662654 def is_PyObject(TYPE):
799791 pypy_debug_catch_fatal_exception()
800792 assert False
801793
794 def _restore_gil_state(pygilstate_release, gilstate, gil_release, _gil_auto, tid):
795 from rpython.rlib import rgil
796 # see "Handling of the GIL" above
797 assert cpyext_glob_tid_ptr[0] == 0
798 if pygilstate_release:
799 from pypy.module.cpyext import pystate
800 unlock = (gilstate == pystate.PyGILState_UNLOCKED)
801 else:
802 unlock = gil_release or _gil_auto
803 if unlock:
804 rgil.release()
805 else:
806 cpyext_glob_tid_ptr[0] = tid
807
808
802809 def make_wrapper_second_level(space, argtypesw, restype,
803810 result_kind, error_value, gil):
804811 from rpython.rlib import rgil
826833 def wrapper_second_level(callable, pname, *args):
827834 from pypy.module.cpyext.pyobject import make_ref, from_ref, is_pyobj
828835 from pypy.module.cpyext.pyobject import as_pyobj
836 from pypy.module.cpyext import pystate
829837 # we hope that malloc removal removes the newtuple() that is
830838 # inserted exactly here by the varargs specializer
831839
838846 rgil.acquire()
839847 assert cpyext_glob_tid_ptr[0] == 0
840848 elif pygilstate_ensure:
841 from pypy.module.cpyext import pystate
842849 if cpyext_glob_tid_ptr[0] == tid:
843850 cpyext_glob_tid_ptr[0] = 0
844851 args += (pystate.PyGILState_LOCKED,)
849856 if cpyext_glob_tid_ptr[0] != tid:
850857 no_gil_error(pname)
851858 cpyext_glob_tid_ptr[0] = 0
859 if pygilstate_release:
860 gilstate = rffi.cast(lltype.Signed, args[-1])
861 else:
862 gilstate = pystate.PyGILState_IGNORE
852863
853864 rffi.stackcounter.stacks_counter += 1
854865 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py
918929
919930 except Exception as e:
920931 unexpected_exception(pname, e, tb)
932 _restore_gil_state(pygilstate_release, gilstate, gil_release, _gil_auto, tid)
921933 return fatal_value
922934
923935 assert lltype.typeOf(retval) == restype
924936 rffi.stackcounter.stacks_counter -= 1
925937
926 # see "Handling of the GIL" above
927 assert cpyext_glob_tid_ptr[0] == 0
928 if pygilstate_release:
929 from pypy.module.cpyext import pystate
930 arg = rffi.cast(lltype.Signed, args[-1])
931 unlock = (arg == pystate.PyGILState_UNLOCKED)
932 else:
933 unlock = gil_release or _gil_auto
934 if unlock:
935 rgil.release()
936 else:
937 cpyext_glob_tid_ptr[0] = tid
938
938 _restore_gil_state(pygilstate_release, gilstate, gil_release, _gil_auto, tid)
939939 return retval
940940
941941 wrapper_second_level._dont_inline_ = True
12011201 cpyext_type_init = self.cpyext_type_init
12021202 self.cpyext_type_init = None
12031203 for pto, w_type in cpyext_type_init:
1204 if space.is_w(w_type, space.w_str):
1205 pto.c_tp_itemsize = 1
12061204 finish_type_1(space, pto)
12071205 finish_type_2(space, pto, w_type)
12081206
15111509 try:
15121510 ll_libname = rffi.str2charp(path)
15131511 try:
1514 dll = rdynload.dlopen(ll_libname)
1512 dll = rdynload.dlopen(ll_libname, space.sys.dlopenflags)
15151513 finally:
15161514 lltype.free(ll_libname, flavor='raw')
15171515 except rdynload.DLOpenError as e:
00 from pypy.interpreter.error import oefmt
11 from rpython.rtyper.lltypesystem import rffi, lltype
22 from pypy.module.cpyext.api import (
3 cpython_api, CANNOT_FAIL, Py_buffer)
3 cpython_api, CANNOT_FAIL, Py_buffer, Py_TPFLAGS_HAVE_NEWBUFFER)
44 from pypy.module.cpyext.pyobject import PyObject
55
66 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
7 def PyObject_CheckBuffer(space, w_obj):
7 def PyObject_CheckBuffer(space, pyobj):
88 """Return 1 if obj supports the buffer interface otherwise 0."""
9 return 0 # the bf_getbuffer field is never filled by cpyext
9 as_buffer = pyobj.c_ob_type.c_tp_as_buffer
10 flags = pyobj.c_ob_type.c_tp_flags
11 if (flags & Py_TPFLAGS_HAVE_NEWBUFFER and as_buffer.c_bf_getbuffer):
12 return 1
13 return 0
1014
1115 @cpython_api([PyObject, lltype.Ptr(Py_buffer), rffi.INT_real],
1216 rffi.INT_real, error=-1)
7878 Py_DecRef(space, py_buf.c_b_base)
7979 else:
8080 rffi.free_charp(rffi.cast(rffi.CCHARP, py_buf.c_b_ptr))
81 from pypy.module.cpyext.object import PyObject_dealloc
82 PyObject_dealloc(space, py_obj)
81 from pypy.module.cpyext.object import _dealloc
82 _dealloc(space, py_obj)
2424
2525 PyByteArrayObjectStruct = lltype.ForwardReference()
2626 PyByteArrayObject = lltype.Ptr(PyByteArrayObjectStruct)
27 PyByteArrayObjectFields = PyVarObjectFields
28 # (("ob_exports", rffi.INT), ("ob_alloc", rffi.LONG), ("ob_bytes", rffi.CCHARP))
27 PyByteArrayObjectFields = PyVarObjectFields
2928 cpython_struct("PyByteArrayObject", PyByteArrayObjectFields, PyByteArrayObjectStruct)
3029
31 @bootstrap_function
32 def init_bytearrayobject(space):
33 "Type description of PyByteArrayObject"
34 #make_typedescr(space.w_bytearray.layout.typedef,
35 # basestruct=PyByteArrayObject.TO,
36 # attach=bytearray_attach,
37 # dealloc=bytearray_dealloc,
38 # realize=bytearray_realize)
39
4030 PyByteArray_Check, PyByteArray_CheckExact = build_type_checkers("ByteArray", "w_bytearray")
41
42 # XXX dead code to be removed
43 #def bytearray_attach(space, py_obj, w_obj):
44 # """
45 # Fills a newly allocated PyByteArrayObject with the given bytearray object
46 # """
47 # py_ba = rffi.cast(PyByteArrayObject, py_obj)
48 # py_ba.c_ob_size = len(space.str_w(w_obj))
49 # py_ba.c_ob_bytes = lltype.nullptr(rffi.CCHARP.TO)
50 # py_ba.c_ob_exports = rffi.cast(rffi.INT, 0)
51
52 #def bytearray_realize(space, py_obj):
53 # """
54 # Creates the bytearray in the interpreter.
55 # """
56 # py_ba = rffi.cast(PyByteArrayObject, py_obj)
57 # if not py_ba.c_ob_bytes:
58 # py_ba.c_buffer = lltype.malloc(rffi.CCHARP.TO, py_ba.c_ob_size + 1,
59 # flavor='raw', zero=True)
60 # s = rffi.charpsize2str(py_ba.c_ob_bytes, py_ba.c_ob_size)
61 # w_obj = space.wrap(s)
62 # py_ba.c_ob_exports = rffi.cast(rffi.INT, 0)
63 # track_reference(space, py_obj, w_obj)
64 # return w_obj
65
66 #@cpython_api([PyObject], lltype.Void, header=None)
67 #def bytearray_dealloc(space, py_obj):
68 # """Frees allocated PyByteArrayObject resources.
69 # """
70 # py_ba = rffi.cast(PyByteArrayObject, py_obj)
71 # if py_ba.c_ob_bytes:
72 # lltype.free(py_ba.c_ob_bytes, flavor="raw")
73 # from pypy.module.cpyext.object import PyObject_dealloc
74 # PyObject_dealloc(space, py_obj)
7531
7632 #_______________________________________________________________________
7733
8945 """Create a new bytearray object from string and its length, len. On
9046 failure, NULL is returned."""
9147 if char_p:
92 w_s = space.wrap(rffi.charpsize2str(char_p, length))
48 w_s = space.newbytes(rffi.charpsize2str(char_p, length))
9349 else:
94 w_s = space.wrap(length)
50 w_s = space.newint(length)
9551 w_buffer = space.call_function(space.w_bytearray, w_s)
9652 return make_ref(space, w_buffer)
9753
12379 if space.isinstance_w(w_obj, space.w_bytearray):
12480 oldlen = space.len_w(w_obj)
12581 if newlen > oldlen:
126 space.call_method(w_obj, 'extend', space.wrap('\x00' * (newlen - oldlen)))
82 space.call_method(w_obj, 'extend', space.newbytes('\x00' * (newlen - oldlen)))
12783 elif oldlen > newlen:
12884 assert newlen >= 0
12985 space.delslice(w_obj, space.wrap(newlen), space.wrap(oldlen))
55 from pypy.module.cpyext.pyerrors import PyErr_BadArgument
66 from pypy.module.cpyext.pyobject import (
77 PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
8 make_typedescr, get_typedescr, as_pyobj, Py_IncRef, get_w_obj_and_decref)
9
10 ##
11 ## Implementation of PyStringObject
8 make_typedescr, get_typedescr, as_pyobj, Py_IncRef, get_w_obj_and_decref,
9 pyobj_has_w_obj)
10 from pypy.objspace.std.bytesobject import W_BytesObject
11
12 ##
13 ## Implementation of PyBytesObject
1214 ## ================================
1315 ##
1416 ## The problem
1517 ## -----------
1618 ##
1719 ## PyString_AsString() must return a (non-movable) pointer to the underlying
18 ## buffer, whereas pypy strings are movable. C code may temporarily store
20 ## ob_sval, whereas pypy strings are movable. C code may temporarily store
1921 ## this address and use it, as long as it owns a reference to the PyObject.
2022 ## There is no "release" function to specify that the pointer is not needed
2123 ## any more.
2628 ## Solution
2729 ## --------
2830 ##
29 ## PyStringObject contains two additional members: the ob_size and a pointer to a
30 ## char buffer; it may be NULL.
31 ##
32 ## - A string allocated by pypy will be converted into a PyStringObject with a
31 ## PyBytesObject contains two additional members: the ob_size and a pointer to a
32 ## char ob_sval; it may be NULL.
33 ##
34 ## - A string allocated by pypy will be converted into a PyBytesObject with a
3335 ## NULL buffer. The first time PyString_AsString() is called, memory is
3436 ## allocated (with flavor='raw') and content is copied.
3537 ##
3638 ## - A string allocated with PyString_FromStringAndSize(NULL, size) will
37 ## allocate a PyStringObject structure, and a buffer with the specified
39 ## allocate a PyBytesObject structure, and a buffer with the specified
3840 ## size+1, but the reference won't be stored in the global map; there is no
3941 ## corresponding object in pypy. When from_ref() or Py_INCREF() is called,
4042 ## the pypy string is created, and added to the global map of tracked
4143 ## objects. The buffer is then supposed to be immutable.
4244 ##
45 ##- A buffer obtained from PyString_AS_STRING() could be mutable iff
46 ## there is no corresponding pypy object for the string
47 ##
4348 ## - _PyString_Resize() works only on not-yet-pypy'd strings, and returns a
4449 ## similar object.
4550 ##
4954 ## corresponds to the pypy gc-managed string.
5055 ##
5156
52 PyStringObjectStruct = lltype.ForwardReference()
53 PyStringObject = lltype.Ptr(PyStringObjectStruct)
54 PyStringObjectFields = PyVarObjectFields + \
55 (("ob_shash", rffi.LONG), ("ob_sstate", rffi.INT), ("buffer", rffi.CCHARP))
56 cpython_struct("PyStringObject", PyStringObjectFields, PyStringObjectStruct)
57 PyBytesObjectStruct = lltype.ForwardReference()
58 PyBytesObject = lltype.Ptr(PyBytesObjectStruct)
59 PyBytesObjectFields = PyVarObjectFields + \
60 (("ob_shash", rffi.LONG), ("ob_sstate", rffi.INT), ("ob_sval", rffi.CArray(lltype.Char)))
61 cpython_struct("PyStringObject", PyBytesObjectFields, PyBytesObjectStruct)
5762
5863 @bootstrap_function
59 def init_stringobject(space):
60 "Type description of PyStringObject"
64 def init_bytesobject(space):
65 "Type description of PyBytesObject"
6166 make_typedescr(space.w_str.layout.typedef,
62 basestruct=PyStringObject.TO,
63 attach=string_attach,
64 dealloc=string_dealloc,
65 realize=string_realize)
67 basestruct=PyBytesObject.TO,
68 attach=bytes_attach,
69 dealloc=bytes_dealloc,
70 realize=bytes_realize)
6671
6772 PyString_Check, PyString_CheckExact = build_type_checkers("String", "w_str")
6873
6974 def new_empty_str(space, length):
7075 """
71 Allocate a PyStringObject and its buffer, but without a corresponding
72 interpreter object. The buffer may be mutated, until string_realize() is
76 Allocate a PyBytesObject and its ob_sval, but without a corresponding
77 interpreter object. The ob_sval may be mutated, until bytes_realize() is
7378 called. Refcount of the result is 1.
7479 """
7580 typedescr = get_typedescr(space.w_str.layout.typedef)
76 py_obj = typedescr.allocate(space, space.w_str)
77 py_str = rffi.cast(PyStringObject, py_obj)
78
79 buflen = length + 1
80 py_str.c_ob_size = length
81 py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen,
82 flavor='raw', zero=True,
83 add_memory_pressure=True)
81 py_obj = typedescr.allocate(space, space.w_str, length)
82 py_str = rffi.cast(PyBytesObject, py_obj)
83 py_str.c_ob_shash = -1
8484 py_str.c_ob_sstate = rffi.cast(rffi.INT, 0) # SSTATE_NOT_INTERNED
8585 return py_str
8686
87 def string_attach(space, py_obj, w_obj):
88 """
89 Fills a newly allocated PyStringObject with the given string object. The
90 buffer must not be modified.
91 """
92 py_str = rffi.cast(PyStringObject, py_obj)
93 py_str.c_ob_size = len(space.str_w(w_obj))
94 py_str.c_buffer = lltype.nullptr(rffi.CCHARP.TO)
87 def bytes_attach(space, py_obj, w_obj):
88 """
89 Copy RPython string object contents to a PyBytesObject. The
90 c_ob_sval must not be modified.
91 """
92 py_str = rffi.cast(PyBytesObject, py_obj)
93 s = space.str_w(w_obj)
94 if py_str.c_ob_size < len(s):
95 raise oefmt(space.w_ValueError,
96 "bytes_attach called on object with ob_size %d but trying to store %d",
97 py_str.c_ob_size, len(s))
98 with rffi.scoped_nonmovingbuffer(s) as s_ptr:
99 rffi.c_memcpy(py_str.c_ob_sval, s_ptr, len(s))
100 py_str.c_ob_sval[len(s)] = '\0'
95101 py_str.c_ob_shash = space.hash_w(w_obj)
96102 py_str.c_ob_sstate = rffi.cast(rffi.INT, 1) # SSTATE_INTERNED_MORTAL
97103
98 def string_realize(space, py_obj):
99 """
100 Creates the string in the interpreter. The PyStringObject buffer must not
104 def bytes_realize(space, py_obj):
105 """
106 Creates the string in the interpreter. The PyBytesObject ob_sval must not
101107 be modified after this call.
102108 """
103 py_str = rffi.cast(PyStringObject, py_obj)
104 if not py_str.c_buffer:
105 py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, py_str.c_ob_size + 1,
106 flavor='raw', zero=True)
107 s = rffi.charpsize2str(py_str.c_buffer, py_str.c_ob_size)
108 w_obj = space.wrap(s)
109 py_str = rffi.cast(PyBytesObject, py_obj)
110 s = rffi.charpsize2str(py_str.c_ob_sval, py_str.c_ob_size)
111 w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type))
112 w_obj = space.allocate_instance(W_BytesObject, w_type)
113 w_obj.__init__(s)
109114 py_str.c_ob_shash = space.hash_w(w_obj)
110115 py_str.c_ob_sstate = rffi.cast(rffi.INT, 1) # SSTATE_INTERNED_MORTAL
111116 track_reference(space, py_obj, w_obj)
112117 return w_obj
113118
114119 @cpython_api([PyObject], lltype.Void, header=None)
115 def string_dealloc(space, py_obj):
116 """Frees allocated PyStringObject resources.
117 """
118 py_str = rffi.cast(PyStringObject, py_obj)
119 if py_str.c_buffer:
120 lltype.free(py_str.c_buffer, flavor="raw")
121 from pypy.module.cpyext.object import PyObject_dealloc
122 PyObject_dealloc(space, py_obj)
120 def bytes_dealloc(space, py_obj):
121 """Frees allocated PyBytesObject resources.
122 """
123 from pypy.module.cpyext.object import _dealloc
124 _dealloc(space, py_obj)
123125
124126 #_______________________________________________________________________
125127
138140
139141 @cpython_api([PyObject], rffi.CCHARP, error=0)
140142 def PyString_AsString(space, ref):
143 return _PyString_AsString(space, ref)
144
145 def _PyString_AsString(space, ref):
141146 if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
142147 pass # typecheck returned "ok" without forcing 'ref' at all
143148 elif not PyString_Check(space, ref): # otherwise, use the alternate way
149154 raise oefmt(space.w_TypeError,
150155 "expected string or Unicode object, %T found",
151156 from_ref(space, ref))
152 ref_str = rffi.cast(PyStringObject, ref)
153 if not ref_str.c_buffer:
154 # copy string buffer
155 w_str = from_ref(space, ref)
156 s = space.str_w(w_str)
157 ref_str.c_buffer = rffi.str2charp(s)
158 return ref_str.c_buffer
157 ref_str = rffi.cast(PyBytesObject, ref)
158 if not pyobj_has_w_obj(ref):
159 # XXX Force the ref?
160 bytes_realize(space, ref)
161 return ref_str.c_ob_sval
162
163 @cpython_api([rffi.VOIDP], rffi.CCHARP, error=0)
164 def PyString_AS_STRING(space, void_ref):
165 ref = rffi.cast(PyObject, void_ref)
166 # if no w_str is associated with this ref,
167 # return the c-level ptr as RW
168 if not pyobj_has_w_obj(ref):
169 py_str = rffi.cast(PyBytesObject, ref)
170 return py_str.c_ob_sval
171 return _PyString_AsString(space, ref)
159172
160173 @cpython_api([PyObject, rffi.CCHARPP, rffi.CArrayPtr(Py_ssize_t)], rffi.INT_real, error=-1)
161 def PyString_AsStringAndSize(space, ref, buffer, length):
174 def PyString_AsStringAndSize(space, ref, data, length):
162175 if not PyString_Check(space, ref):
163176 from pypy.module.cpyext.unicodeobject import (
164177 PyUnicode_Check, _PyUnicode_AsDefaultEncodedString)
168181 raise oefmt(space.w_TypeError,
169182 "expected string or Unicode object, %T found",
170183 from_ref(space, ref))
171 ref_str = rffi.cast(PyStringObject, ref)
172 if not ref_str.c_buffer:
173 # copy string buffer
174 w_str = from_ref(space, ref)
175 s = space.str_w(w_str)
176 ref_str.c_buffer = rffi.str2charp(s)
177 buffer[0] = ref_str.c_buffer
184 if not pyobj_has_w_obj(ref):
185 # force the ref
186 bytes_realize(space, ref)
187 ref_str = rffi.cast(PyBytesObject, ref)
188 data[0] = ref_str.c_ob_sval
178189 if length:
179190 length[0] = ref_str.c_ob_size
180191 else:
181192 i = 0
182 while ref_str.c_buffer[i] != '\0':
193 while ref_str.c_ob_sval[i] != '\0':
183194 i += 1
184195 if i != ref_str.c_ob_size:
185196 raise oefmt(space.w_TypeError,
189200 @cpython_api([PyObject], Py_ssize_t, error=-1)
190201 def PyString_Size(space, ref):
191202 if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
192 ref = rffi.cast(PyStringObject, ref)
203 ref = rffi.cast(PyBytesObject, ref)
193204 return ref.c_ob_size
194205 else:
195206 w_obj = from_ref(space, ref)
208219 set to NULL, a memory exception is set, and -1 is returned.
209220 """
210221 # XXX always create a new string so far
211 py_str = rffi.cast(PyStringObject, ref[0])
212 if not py_str.c_buffer:
222 if pyobj_has_w_obj(ref[0]):
213223 raise oefmt(space.w_SystemError,
214224 "_PyString_Resize called on already created string")
225 py_str = rffi.cast(PyBytesObject, ref[0])
215226 try:
216227 py_newstr = new_empty_str(space, newsize)
217228 except MemoryError:
223234 if oldsize < newsize:
224235 to_cp = oldsize
225236 for i in range(to_cp):
226 py_newstr.c_buffer[i] = py_str.c_buffer[i]
237 py_newstr.c_ob_sval[i] = py_str.c_ob_sval[i]
227238 Py_DecRef(space, ref[0])
228239 ref[0] = rffi.cast(PyObject, py_newstr)
229240 return 0
+0
-71
pypy/module/cpyext/c-api.txt less more
0 Reference Count
1 ===============
2
3 XXX
4
5 Borrowed References
6 ===================
7
8 XXX
9
10 PyStringObject support
11 ======================
12
13 The problem
14 -----------
15
16 PyString_AsString() returns a (non-movable) pointer to the underlying
17 buffer, whereas pypy strings are movable. C code may temporarily
18 store this address and use it, as long as it owns a reference to the
19 PyObject. There is no "release" function to specify that the pointer
20 is not needed any more.
21
22 Note that the pointer may be used to fill the initial value of
23 string. This is valid only when the string was just allocated, and is
24 not used elsewhere.
25
26 Proposed solution
27 -----------------
28
29 Our emulation of the PyStringObject contains an additional member: a
30 pointer to a char buffer; it may be NULL.
31
32 - A string allocated by pypy will be converted into a PyStringObject
33 with a NULL buffer. When PyString_AsString() is called, memory is
34 allocated (with flavor='raw') and content is copied.
35
36 - A string allocated with PyString_FromStringAndSize(NULL, size) will
37 allocate a buffer with the specified size, but the reference won't
38 be stored in the global map py_objects_r2w; there won't be a
39 corresponding object in pypy. When from_ref() or Py_INCREF() is
40 called, the pypy string is created, and added in py_objects_r2w.
41 The buffer is then supposed to be immutable.
42
43 - _PyString_Resize works only on not-yet-pypy'd strings, and returns a
44 similar object.
45
46 - PyString_Size don't need to force the object. (in this case, another
47 "size" member is needed)
48
49 - There could be an (expensive!) check in from_ref() that the buffer
50 still corresponds to the pypy gc-managed string.
51
52 PySequence_Fast support
53 ======================
54 There are five functions for fast sequence access offered by the CPython API:
55
56 PyObject* PySequence_Fast(PyObject *o, const char *m)
57
58 PyObject* PySequence_Fast_GET_ITEM( PyObject *o, int i)
59
60 PyObject** PySequence_Fast_ITEMS( PyObject *o)
61
62 PyObject* PySequence_ITEM( PyObject *o, int i)
63
64 int PySequence_Fast_GET_SIZE( PyObject *o)
65
66 PyPy supports four of these, but does not support PySequence_Fast_ITEMS.
67 (Various ways to support PySequence_Fast_ITEMS were considered. They all had
68 two things in common: they would have taken a lot of work, and they would have
69 resulted in incomplete semantics or in poor performance. We decided that a slow
70 implementation of PySequence_Fast_ITEMS was not very useful.)
1212 "PyCompilerFlags", (("cf_flags", rffi.INT),))
1313 PyCompilerFlagsPtr = lltype.Ptr(PyCompilerFlags)
1414
15 PyCF_MASK = (consts.CO_FUTURE_DIVISION |
15 PyCF_MASK = (consts.CO_FUTURE_DIVISION |
1616 consts.CO_FUTURE_ABSOLUTE_IMPORT |
1717 consts.CO_FUTURE_WITH_STATEMENT |
1818 consts.CO_FUTURE_PRINT_FUNCTION |
9393 Py_eval_input = 258
9494
9595 def compile_string(space, source, filename, start, flags=0):
96 w_source = space.wrap(source)
96 w_source = space.newbytes(source)
9797 start = rffi.cast(lltype.Signed, start)
9898 if start == Py_file_input:
9999 mode = 'exec'
226226 cf.c_cf_flags = rffi.cast(rffi.INT, flags)
227227 return result
228228
229
229
4545 Py_DecRef(space, py_code)
4646 Py_DecRef(space, py_frame.c_f_globals)
4747 Py_DecRef(space, py_frame.c_f_locals)
48 from pypy.module.cpyext.object import PyObject_dealloc
49 PyObject_dealloc(space, py_obj)
48 from pypy.module.cpyext.object import _dealloc
49 _dealloc(space, py_obj)
5050
5151 def frame_realize(space, py_obj):
5252 """
5959 def function_dealloc(space, py_obj):
6060 py_func = rffi.cast(PyFunctionObject, py_obj)
6161 Py_DecRef(space, py_func.c_func_name)
62 from pypy.module.cpyext.object import PyObject_dealloc
63 PyObject_dealloc(space, py_obj)
62 from pypy.module.cpyext.object import _dealloc
63 _dealloc(space, py_obj)
6464
6565 def code_attach(space, py_obj, w_obj):
6666 py_code = rffi.cast(PyCodeObject, py_obj)
7979 py_code = rffi.cast(PyCodeObject, py_obj)
8080 Py_DecRef(space, py_code.c_co_name)
8181 Py_DecRef(space, py_code.c_co_filename)
82 from pypy.module.cpyext.object import PyObject_dealloc
83 PyObject_dealloc(space, py_obj)
82 from pypy.module.cpyext.object import _dealloc
83 _dealloc(space, py_obj)
8484
8585 @cpython_api([PyObject], PyObject, result_borrowed=True)
8686 def PyFunction_GetCode(space, w_func):
11 #define Py_PYTHON_H
22
33 /* Compat stuff */
4 #ifdef __GNUC__
5 #define _GNU_SOURCE 1
6 #endif
47 #ifndef _WIN32
58 # include <inttypes.h>
69 # include <stdint.h>
5154 #ifndef DL_IMPORT
5255 # define DL_IMPORT(RTYPE) RTYPE
5356 #endif
54
5557 #include <stdlib.h>
5658
5759 #ifndef _WIN32
44 npy_bool obval;
55 } PyBoolScalarObject;
66
7 static int import_array(){return 0;};
8 static int _import_array(){return 0;};
9 static int _import_math(){return 0;};
7 #if PY_VERSION_HEX >= 0x03000000
8 #define NUMPY_IMPORT_ARRAY_RETVAL NULL
9 #else
10 #define NUMPY_IMPORT_ARRAY_RETVAL
11 #endif
1012
13 #define import_array() {return NUMPY_IMPORT_ARRAY_RETVAL;}
14
15
560560 #define PyObject_TypeCheck(ob, tp) \
561561 ((ob)->ob_type == (tp) || PyType_IsSubtype((ob)->ob_type, (tp)))
562562
563 #define Py_TRASHCAN_SAFE_BEGIN(pyObj)
564 #define Py_TRASHCAN_SAFE_END(pyObj)
563 #define Py_TRASHCAN_SAFE_BEGIN(pyObj) do {
564 #define Py_TRASHCAN_SAFE_END(pyObj) ; } while(0);
565 /* note: the ";" at the start of Py_TRASHCAN_SAFE_END is needed
566 if the code has a label in front of the macro call */
565567
566568 /* Copied from CPython ----------------------------- */
567569 PyAPI_FUNC(int) PyObject_AsReadBuffer(PyObject *, const void **, Py_ssize_t *);
2828 #define PY_VERSION "2.7.10"
2929
3030 /* PyPy version as a string */
31 #define PYPY_VERSION "5.3.1"
32 #define PYPY_VERSION_NUM 0x05030100
31 #define PYPY_VERSION "5.4.0"
32 #define PYPY_VERSION_NUM 0x05040000
3333
3434 /* Defined to mean a PyPy where cpyext holds more regular references
3535 to PyObjects, e.g. staying alive as long as the internal PyPy object
6363 # error "Python needs a typedef for Py_uintptr_t in pyport.h."
6464 #endif /* HAVE_UINTPTR_T */
6565
66 /* Py_hash_t is the same size as a pointer. */
67 #define SIZEOF_PY_HASH_T SIZEOF_SIZE_T
68 typedef Py_ssize_t Py_hash_t;
69 /* Py_uhash_t is the unsigned equivalent needed to calculate numeric hash. */
70 #define SIZEOF_PY_UHASH_T SIZEOF_SIZE_T
71 typedef size_t Py_uhash_t;
72
7366
7467 /*******************************
7568 * stat() and fstat() fiddling *
99 #include <stdarg.h>
1010
1111 #define PyString_GET_SIZE(op) PyString_Size((PyObject*)(op))
12 #define PyString_AS_STRING(op) PyString_AsString((PyObject*)(op))
1312 /*
1413 Type PyStringObject represents a character string. An extra zero byte is
1514 reserved at the end to ensure it is zero-terminated, but a size is
4039 PyObject_VAR_HEAD
4140 long ob_shash;
4241 int ob_sstate;
43 char * buffer; /* change the name from cpython so all non-api c access is thwarted */
42 char ob_sval[1];
4443
4544 /* Invariants
46 * (not relevant in PyPy, all stringobjects are backed by a pypy object)
47 * buffer contains space for 'ob_size+1' elements.
48 * buffer[ob_size] == 0.
45 * ob_sval contains space for 'ob_size+1' elements.
46 * ob_sval[ob_size] == 0.
4947 * ob_shash is the hash of the string or -1 if not computed yet.
5048 * ob_sstate != 0 iff the string object is in stringobject.c's
5149 * 'interned' dictionary; in this case the two references
77 #endif
88
99 typedef struct {
10 PyObject_HEAD
11 Py_ssize_t ob_size;
12 PyObject **ob_item; /* XXX optimize to ob_item[] */
10 PyObject_VAR_HEAD
11 PyObject *ob_item[1];
12 /* ob_item contains space for 'ob_size' elements.
13 * Items must normally not be NULL, except during construction when
14 * the tuple is not yet visible outside the function that builds it.
15 */
1316 } PyTupleObject;
1417
1518 /* defined in varargswrapper.c */
1111 @cpython_api([PyObject], PyObject)
1212 def PyMemoryView_GET_BASE(space, w_obj):
1313 # return the obj field of the Py_buffer created by PyMemoryView_GET_BUFFER
14 raise NotImplementedError
14 raise NotImplementedError('PyMemoryView_GET_BUFFER')
1515
1616 @cpython_api([PyObject], lltype.Ptr(Py_buffer), error=CANNOT_FAIL)
1717 def PyMemoryView_GET_BUFFER(space, w_obj):
0 from rpython.rtyper.lltypesystem import lltype, rffi
0 from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
11
22 from pypy.interpreter.baseobjspace import W_Root
33 from pypy.interpreter.error import OperationError, oefmt
99 from pypy.module.cpyext.api import (
1010 CONST_STRING, METH_CLASS, METH_COEXIST, METH_KEYWORDS, METH_NOARGS, METH_O,
1111 METH_STATIC, METH_VARARGS, PyObject, PyObjectFields, bootstrap_function,
12 build_type_checkers, cpython_api, cpython_struct, generic_cpy_call)
12 build_type_checkers, cpython_api, cpython_struct, generic_cpy_call,
13 PyTypeObjectPtr)
1314 from pypy.module.cpyext.pyobject import (
14 Py_DecRef, from_ref, make_ref, make_typedescr)
15 Py_DecRef, from_ref, make_ref, as_pyobj, make_typedescr)
1516
1617 PyCFunction_typedef = rffi.COpaquePtr(typedef='PyCFunction')
1718 PyCFunction = lltype.Ptr(lltype.FuncType([PyObject, PyObject], PyObject))
5455 py_func = rffi.cast(PyCFunctionObject, py_obj)
5556 Py_DecRef(space, py_func.c_m_self)
5657 Py_DecRef(space, py_func.c_m_module)
57 from pypy.module.cpyext.object import PyObject_dealloc
58 PyObject_dealloc(space, py_obj)
58 from pypy.module.cpyext.object import _dealloc
59 _dealloc(space, py_obj)
5960
6061
6162 class W_PyCFunctionObject(W_Root):
150151
151152 class W_PyCWrapperObject(W_Root):
152153 def __init__(self, space, pto, method_name, wrapper_func,
153 wrapper_func_kwds, doc, func):
154 wrapper_func_kwds, doc, func, offset=None):
154155 self.space = space
155156 self.method_name = method_name
156157 self.wrapper_func = wrapper_func
157158 self.wrapper_func_kwds = wrapper_func_kwds
158159 self.doc = doc
159160 self.func = func
161 self.offset = offset
160162 pyo = rffi.cast(PyObject, pto)
161163 w_type = from_ref(space, pyo)
162164 assert isinstance(w_type, W_TypeObject)
163165 self.w_objclass = w_type
164166
165167 def call(self, space, w_self, w_args, w_kw):
168 func_to_call = self.func
169 if self.offset:
170 pto = as_pyobj(space, self.w_objclass)
171 # make ptr the equivalent of this, using the offsets
172 #func_to_call = rffi.cast(rffi.VOIDP, ptr.c_tp_as_number.c_nb_multiply)
173 if pto:
174 cptr = rffi.cast(rffi.CCHARP, pto)
175 for o in self.offset:
176 ptr = rffi.cast(rffi.VOIDPP, rffi.ptradd(cptr, o))[0]
177 cptr = rffi.cast(rffi.CCHARP, ptr)
178 func_to_call = rffi.cast(rffi.VOIDP, cptr)
179 else:
180 # Should never happen, assert to get a traceback
181 assert False, "failed to convert w_type %s to PyObject" % str(
182 self.w_objclass)
183 assert func_to_call
166184 if self.wrapper_func is None:
167185 assert self.wrapper_func_kwds is not None
168 return self.wrapper_func_kwds(space, w_self, w_args, self.func,
186 return self.wrapper_func_kwds(space, w_self, w_args, func_to_call,
169187 w_kw)
170188 if space.is_true(w_kw):
171189 raise oefmt(space.w_TypeError,
172190 "wrapper %s doesn't take any keyword arguments",
173191 self.method_name)
174 return self.wrapper_func(space, w_self, w_args, self.func)
192 return self.wrapper_func(space, w_self, w_args, func_to_call)
175193
176194 def descr_method_repr(self):
177195 return self.space.wrap("<slot wrapper '%s' of '%s' objects>" %
299317 @cpython_api([PyObject, lltype.Ptr(PyMethodDef)], PyObject)
300318 def PyDescr_NewClassMethod(space, w_type, method):
301319 return space.wrap(W_PyCClassMethodObject(space, method, w_type))
302
303 def PyDescr_NewWrapper(space, pto, method_name, wrapper_func,
304 wrapper_func_kwds, doc, func):
305 # not exactly the API sig
306 return space.wrap(W_PyCWrapperObject(space, pto, method_name,
307 wrapper_func, wrapper_func_kwds, doc, func))
308320
309321 @cpython_api([lltype.Ptr(PyMethodDef), PyObject, CONST_STRING], PyObject)
310322 def Py_FindMethod(space, table, w_obj, name_ptr):
1919 def PyNumber_Check(space, w_obj):
2020 """Returns 1 if the object o provides numeric protocols, and false otherwise.
2121 This function always succeeds."""
22 try:
23 space.float_w(w_obj)
22 # According to CPython, this means: w_obj is not None, and
23 # the type of w_obj has got a method __int__ or __float__.
24 if w_obj is None:
25 return 0
26 if space.lookup(w_obj, '__int__') or space.lookup(w_obj, '__float__'):
2427 return 1
25 except OperationError:
26 pass
27 try:
28 space.int_w(w_obj)
29 return 1
30 except OperationError:
31 pass
3228 return 0
3329
3430 @cpython_api([PyObject, PyObject], Py_ssize_t, error=-1)
2020 flavor='raw',
2121 add_memory_pressure=True)
2222
23 realloc = rffi.llexternal('realloc', [rffi.VOIDP, rffi.SIZE_T], rffi.VOIDP)
24
2325 @cpython_api([rffi.VOIDP, size_t], rffi.VOIDP)
2426 def PyObject_Realloc(space, ptr, size):
2527 if not lltype.cast_ptr_to_int(ptr):
2729 flavor='raw',
2830 add_memory_pressure=True)
2931 # XXX FIXME
30 return lltype.nullptr(rffi.VOIDP.TO)
32 return realloc(ptr, size)
3133
3234 @cpython_api([rffi.VOIDP], lltype.Void)
3335 def PyObject_Free(space, ptr):
5355
5456 @cpython_api([PyObject], lltype.Void)
5557 def PyObject_dealloc(space, obj):
58 return _dealloc(space, obj)
59
60 def _dealloc(space, obj):
5661 # This frees an object after its refcount dropped to zero, so we
5762 # assert that it is really zero here.
5863 assert obj.c_ob_refcnt == 0
00 from rpython.rtyper.lltypesystem import rffi, lltype
1 from rpython.rlib.rfile import c_setvbuf, _IONBF
12 from pypy.module.cpyext.api import (
2 cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, build_type_checkers, fdopen)
3 cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, build_type_checkers, c_fdopen)
34 from pypy.module.cpyext.pyobject import PyObject
45 from pypy.module.cpyext.object import Py_PRINT_RAW
56 from pypy.interpreter.error import (OperationError, oefmt,
2223 try:
2324 w_readline = space.getattr(w_obj, space.wrap('readline'))
2425 except OperationError:
25 raise oefmt(space.w_TypeError,
26 raise oefmt(space.w_TypeError,
2627 "argument must be a file, or have a readline() method.")
2728
2829 n = rffi.cast(lltype.Signed, n)
4041 On success, return a new file object that is opened on the file given by
4142 filename, with a file mode given by mode, where mode has the same
4243 semantics as the standard C routine fopen(). On failure, return NULL."""
43 w_filename = space.wrap(rffi.charp2str(filename))
44 w_filename = space.newbytes(rffi.charp2str(filename))
4445 w_mode = space.wrap(rffi.charp2str(mode))
4546 return space.call_method(space.builtin, 'file', w_filename, w_mode)
4647
5455 if not PyFile_Check(space, w_p):
5556 raise oefmt(space.w_IOError, 'first argument must be an open file')
5657 assert isinstance(w_p, W_File)
58 w_p.stream.flush_buffers()
5759 try:
5860 fd = space.int_w(space.call_method(w_p, 'fileno'))
5961 mode = w_p.mode
6264 if (fd < 0 or not mode or mode[0] not in ['r', 'w', 'a', 'U'] or
6365 ('U' in mode and ('w' in mode or 'a' in mode))):
6466 raise oefmt(space.w_IOError, 'invalid fileno or mode')
65 ret = fdopen(fd, mode)
67 ret = c_fdopen(fd, mode)
6668 if not ret:
6769 raise exception_from_saved_errno(space, space.w_IOError)
70 # XXX fix this once use-file-star-for-file lands
71 c_setvbuf(ret, lltype.nullptr(rffi.CCHARP.TO), _IONBF, 0)
6872 return ret
69
7073
7174 @cpython_api([FILEP, CONST_STRING, CONST_STRING, rffi.VOIDP], PyObject)
7275 def PyFile_FromFile(space, fp, name, mode, close):
66 from pypy.module.cpyext.api import (
77 cpython_api, bootstrap_function, PyObject, PyObjectP, ADDR,
88 CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr, is_PyObject,
9 INTERPLEVEL_API)
9 INTERPLEVEL_API, PyVarObject)
1010 from pypy.module.cpyext.state import State
1111 from pypy.objspace.std.typeobject import W_TypeObject
1212 from pypy.objspace.std.objectobject import W_ObjectObject
4646 size = pytype.c_tp_basicsize
4747 else:
4848 size = rffi.sizeof(self.basestruct)
49 if itemcount and w_type is not space.w_str:
49 if pytype.c_tp_itemsize:
5050 size += itemcount * pytype.c_tp_itemsize
5151 assert size >= rffi.sizeof(PyObject.TO)
5252 buf = lltype.malloc(rffi.VOIDP.TO, size,
5353 flavor='raw', zero=True,
5454 add_memory_pressure=True)
5555 pyobj = rffi.cast(PyObject, buf)
56 if pytype.c_tp_itemsize:
57 pyvarobj = rffi.cast(PyVarObject, pyobj)
58 pyvarobj.c_ob_size = itemcount
5659 pyobj.c_ob_refcnt = 1
5760 #pyobj.c_ob_pypy_link should get assigned very quickly
5861 pyobj.c_ob_type = pytype
151154 class InvalidPointerException(Exception):
152155 pass
153156
154 def create_ref(space, w_obj, itemcount=0):
157 def create_ref(space, w_obj):
155158 """
156159 Allocates a PyObject, and fills its fields with info from the given
157160 interpreter object.
158161 """
159162 w_type = space.type(w_obj)
163 pytype = rffi.cast(PyTypeObjectPtr, as_pyobj(space, w_type))
160164 typedescr = get_typedescr(w_obj.typedef)
165 if pytype.c_tp_itemsize != 0:
166 itemcount = space.len_w(w_obj) # PyBytesObject and subclasses
167 else:
168 itemcount = 0
161169 py_obj = typedescr.allocate(space, w_type, itemcount=itemcount)
162170 track_reference(space, py_obj, w_obj)
163171 #
206206 PyGILState_STATE = rffi.INT
207207 PyGILState_LOCKED = 0
208208 PyGILState_UNLOCKED = 1
209 PyGILState_IGNORE = 2
209210
210211 ExecutionContext.cpyext_gilstate_counter_noleave = 0
211212
4545 py_traceback = rffi.cast(PyTracebackObject, py_obj)
4646 Py_DecRef(space, rffi.cast(PyObject, py_traceback.c_tb_next))
4747 Py_DecRef(space, rffi.cast(PyObject, py_traceback.c_tb_frame))
48 from pypy.module.cpyext.object import PyObject_dealloc
49 PyObject_dealloc(space, py_obj)
48 from pypy.module.cpyext.object import _dealloc
49 _dealloc(space, py_obj)
99 from pypy.objspace.std import tupleobject
1010
1111 from pypy.module.cpyext.tupleobject import PyTuple_Check, PyTuple_SetItem
12 from pypy.module.cpyext.object import Py_IncRef, Py_DecRef
12 from pypy.module.cpyext.pyobject import decref
1313
1414 from pypy.module.cpyext.dictobject import PyDict_Check
1515
251251 def setitem(self, w_list, index, w_obj):
252252 storage = self.unerase(w_list.lstorage)
253253 index = self._check_index(index, storage._length)
254 Py_DecRef(w_list.space, storage._elems[index])
254 decref(w_list.space, storage._elems[index])
255255 storage._elems[index] = make_ref(w_list.space, w_obj)
256256
257257 def length(self, w_list):
263263 return storage._elems
264264
265265 def getslice(self, w_list, start, stop, step, length):
266 #storage = self.unerase(w_list.lstorage)
267 raise oefmt(w_list.space.w_NotImplementedError,
268 "settting a slice of a PySequence_Fast is not supported")
266 w_list.switch_to_object_strategy()
267 return w_list.strategy.getslice(w_list, start, stop, step, length)
269268
270269 def getitems(self, w_list):
271270 # called when switching list strategy, so convert storage
388387
389388 def __del__(self):
390389 for i in range(self._length):
391 Py_DecRef(self.space, self._elems[i])
390 decref(self.space, self._elems[i])
392391 lltype.free(self._elems, flavor='raw')
3737
3838 @cpython_api([PyObject], lltype.Void, header=None)
3939 def slice_dealloc(space, py_obj):
40 """Frees allocated PyStringObject resources.
40 """Frees allocated PyBytesObject resources.
4141 """
4242 py_slice = rffi.cast(PySliceObject, py_obj)
4343 Py_DecRef(space, py_slice.c_start)
4444 Py_DecRef(space, py_slice.c_stop)
4545 Py_DecRef(space, py_slice.c_step)
46 from pypy.module.cpyext.object import PyObject_dealloc
47 PyObject_dealloc(space, py_obj)
46 from pypy.module.cpyext.object import _dealloc
47 _dealloc(space, py_obj)
4848
4949 PySlice_Check, PySlice_CheckExact = build_type_checkers("Slice")
5050
7272 length length, and store the length of the slice in slicelength. Out
7373 of bounds indices are clipped in a manner consistent with the handling of
7474 normal slices.
75
75
7676 Returns 0 on success and -1 on error with exception set."""
7777 if not PySlice_Check(space, w_slice):
7878 PyErr_BadInternalCall(space)
8787 """Retrieve the start, stop and step indices from the slice object slice,
8888 assuming a sequence of length length. Treats indices greater than
8989 length as errors.
90
90
9191 Returns 0 on success and -1 on error with no exception set (unless one of
9292 the indices was not None and failed to be converted to an integer,
9393 in which case -1 is returned with an exception set).
94
94
9595 You probably do not want to use this function. If you want to use slice
9696 objects in versions of Python prior to 2.3, you would probably do well to
9797 incorporate the source of PySlice_GetIndicesEx(), suitably renamed,
22 import re
33
44 from rpython.rtyper.lltypesystem import rffi, lltype
5 from rpython.rlib.rarithmetic import widen
56 from pypy.module.cpyext.api import (
67 cpython_api, generic_cpy_call, PyObject, Py_ssize_t, Py_TPFLAGS_CHECKTYPES,
7 mangle_name, pypy_decl)
8 mangle_name, pypy_decl, Py_buffer, Py_bufferP)
89 from pypy.module.cpyext.typeobjectdefs import (
910 unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, ternaryfunc,
1011 getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry,
1112 ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
1213 cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
13 readbufferproc, ssizessizeobjargproc)
14 readbufferproc, getbufferproc, ssizessizeobjargproc)
1415 from pypy.module.cpyext.pyobject import from_ref, make_ref, Py_DecRef
1516 from pypy.module.cpyext.pyerrors import PyErr_Occurred
1617 from pypy.module.cpyext.state import State
2122 from rpython.rlib.objectmodel import specialize
2223 from rpython.tool.sourcetools import func_renamer
2324 from rpython.rtyper.annlowlevel import llhelper
25 from pypy.module.sys.version import CPYTHON_VERSION
26
27 PY3 = CPYTHON_VERSION[0] == 3
2428
2529 # XXX: Also defined in object.h
2630 Py_LT = 0
297301 # Similar to Py_buffer
298302 _immutable_ = True
299303
300 def __init__(self, ptr, size, w_obj):
304 def __init__(self, ptr, size, w_obj, format='B', shape=None,
305 strides=None, ndim=1, itemsize=1, readonly=True):
301306 self.ptr = ptr
302307 self.size = size
303308 self.w_obj = w_obj # kept alive
304 self.readonly = True
309 self.format = format
310 if not shape:
311 self.shape = [size]
312 else:
313 self.shape = shape
314 if not strides:
315 self.strides = [1]
316 else:
317 self.strides = strides
318 self.ndim = ndim
319 self.itemsize = itemsize
320 self.readonly = readonly
305321
306322 def getlength(self):
307323 return self.size
311327
312328 def get_raw_address(self):
313329 return rffi.cast(rffi.CCHARP, self.ptr)
330
331 def getformat(self):
332 return self.format
333
334 def getshape(self):
335 return self.shape
336
337 def getitemsize(self):
338 return self.itemsize
314339
315340 def wrap_getreadbuffer(space, w_self, w_args, func):
316341 func_target = rffi.cast(readbufferproc, func)
320345 if size < 0:
321346 space.fromcache(State).check_and_raise_exception(always=True)
322347 return space.newbuffer(CPyBuffer(ptr[0], size, w_self))
348
349 def wrap_getbuffer(space, w_self, w_args, func):
350 func_target = rffi.cast(getbufferproc, func)
351 with lltype.scoped_alloc(Py_buffer) as pybuf:
352 _flags = 0
353 if space.len_w(w_args) > 0:
354 _flags = space.int_w(space.listview(w_args)[0])
355 flags = rffi.cast(rffi.INT_real,_flags)
356 size = generic_cpy_call(space, func_target, w_self, pybuf, flags)
357 if widen(size) < 0:
358 space.fromcache(State).check_and_raise_exception(always=True)
359 ptr = pybuf.c_buf
360 size = pybuf.c_len
361 ndim = widen(pybuf.c_ndim)
362 shape = [pybuf.c_shape[i] for i in range(ndim)]
363 strides = [pybuf.c_strides[i] for i in range(ndim)]
364 if pybuf.c_format:
365 format = rffi.charp2str(pybuf.c_format)
366 else:
367 format = 'B'
368 return space.newbuffer(CPyBuffer(ptr, size, w_self, format=format,
369 ndim=ndim, shape=shape, strides=strides,
370 itemsize=pybuf.c_itemsize,
371 readonly=widen(pybuf.c_readonly)))
323372
324373 def get_richcmp_func(OP_CONST):
325374 def inner(space, w_self, w_args, func):
379428 ('tp_as_number.c_nb_absolute', '__abs__'),
380429 ('tp_as_number.c_nb_invert', '__invert__'),
381430 ('tp_as_number.c_nb_index', '__index__'),
431 ('tp_as_number.c_nb_hex', '__hex__'),
432 ('tp_as_number.c_nb_oct', '__oct__'),
382433 ('tp_str', '__str__'),
383434 ('tp_repr', '__repr__'),
384435 ('tp_iter', '__iter__'),
397448
398449 # binary functions
399450 for tp_name, attr in [('tp_as_number.c_nb_add', '__add__'),
400 ('tp_as_number.c_nb_subtract', '__subtract__'),
451 ('tp_as_number.c_nb_subtract', '__sub__'),
401452 ('tp_as_number.c_nb_multiply', '__mul__'),
402453 ('tp_as_number.c_nb_divide', '__div__'),
403454 ('tp_as_number.c_nb_remainder', '__mod__'),
407458 ('tp_as_number.c_nb_and', '__and__'),
408459 ('tp_as_number.c_nb_xor', '__xor__'),
409460 ('tp_as_number.c_nb_or', '__or__'),
461 ('tp_as_sequence.c_sq_concat', '__add__'),
462 ('tp_as_sequence.c_sq_inplace_concat', '__iadd__')
410463 ]:
411464 if name == tp_name:
412465 slot_fn = w_type.getdictvalue(space, attr)
420473 api_func = slot_func.api_func
421474 handled = True
422475
476 # binary-with-Py_ssize_t-type
477 for tp_name, attr in [('tp_as_sequence.c_sq_item', '__getitem'),
478 ('tp_as_sequence.c_sq_repeat', '__mul__'),
479 ('tp_as_sequence.c_sq_repeat', '__mul__'),
480 ('tp_as_sequence.c_sq_inplace_repeat', '__imul__'),
481 ]:
482 if name == tp_name:
483 slot_fn = w_type.getdictvalue(space, attr)
484 if slot_fn is None:
485 return
486
487 @cpython_api([PyObject, Py_ssize_t], PyObject, header=header)
488 @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
489 def slot_func(space, w_self, arg):
490 return space.call_function(slot_fn, w_self, space.wrap(arg))
491 api_func = slot_func.api_func
492 handled = True
493
423494 # ternary functions
424 for tp_name, attr in [('tp_as_number.c_nb_power', ''),
495 for tp_name, attr in [('tp_as_number.c_nb_power', '__pow__'),
425496 ]:
426497 if name == tp_name:
427498 slot_fn = w_type.getdictvalue(space, attr)
463534 def slot_tp_getattro(space, w_self, w_name):
464535 return space.call_function(getattr_fn, w_self, w_name)
465536 api_func = slot_tp_getattro.api_func
466
467537 elif name == 'tp_call':
468538 call_fn = w_type.getdictvalue(space, '__call__')
469539 if call_fn is None:
519589 w_stararg=w_args, w_starstararg=w_kwds)
520590 return space.call_args(space.get(new_fn, w_self), args)
521591 api_func = slot_tp_new.api_func
592 elif name == 'tp_as_buffer.c_bf_getbuffer':
593 buff_fn = w_type.getdictvalue(space, '__buffer__')
594 if buff_fn is None:
595 return
596 @cpython_api([PyObject, Py_bufferP, rffi.INT_real],
597 rffi.INT_real, header=None, error=-1)
598 @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
599 def buff_w(space, w_self, pybuf, flags):
600 # XXX this is wrong, needs a test
601 raise oefmt(space.w_NotImplemented,
602 "calling bf_getbuffer on a builtin type not supported yet")
603 #args = Arguments(space, [w_self],
604 # w_stararg=w_args, w_starstararg=w_kwds)
605 #return space.call_args(space.get(buff_fn, w_self), args)
606 api_func = buff_w.api_func
522607 else:
523608 # missing: tp_as_number.nb_nonzero, tp_as_number.nb_coerce
609 # tp_as_sequence.c_sq_contains, tp_as_sequence.c_sq_length
610 # richcmpfunc(s)
524611 return
525612
526613 return lambda: llhelper(api_func.functype, api_func.get_wrapper(space))
825912 slotdefs = eval(slotdefs_str)
826913 # PyPy addition
827914 slotdefs += (
828 TPSLOT("__buffer__", "tp_as_buffer.c_bf_getreadbuffer", None, "wrap_getreadbuffer", ""),
915 # XXX that might not be what we want!
916 TPSLOT("__buffer__", "tp_as_buffer.c_bf_getbuffer", None, "wrap_getbuffer", ""),
829917 )
918
919 if not PY3:
920 slotdefs += (
921 TPSLOT("__buffer__", "tp_as_buffer.c_bf_getreadbuffer", None, "wrap_getreadbuffer", ""),
922 )
923
830924
831925 # partial sort to solve some slot conflicts:
832926 # Number slots before Mapping slots before Sequence slots.
927 # also prefer the new buffer interface
833928 # These are the only conflicts between __name__ methods
834929 def slotdef_sort_key(slotdef):
835930 if slotdef.slot_name.startswith('tp_as_number'):
838933 return 2
839934 if slotdef.slot_name.startswith('tp_as_sequence'):
840935 return 3
936 if slotdef.slot_name == 'tp_as_buffer.c_bf_getbuffer':
937 return 100
938 if slotdef.slot_name == 'tp_as_buffer.c_bf_getreadbuffer':
939 return 101
841940 return 0
842941 slotdefs = sorted(slotdefs, key=slotdef_sort_key)
843942
106106 if (!string)
107107 return NULL;
108108
109 s = PyString_AsString(string);
109 s = PyString_AS_STRING(string);
110110
111111 for (f = format; *f; f++) {
112112 if (*f == '%') {
18561856 return 0;
18571857 }
18581858 }
1859
1860 static PyObject*
1861 array_multiply(PyObject* obj1, PyObject* obj2)
1862 {
1863 if (PyList_Check(obj1) && ((arrayobject*)obj2)->ob_descr->typecode == 'i' && Py_SIZE(obj2) == 1)
1864 {
1865 int ii, nn;
1866 int n = PyList_Size(obj1);
1867 PyObject *v = getarrayitem(obj2, 0);
1868 int i = ((PyIntObject*)v)->ob_ival;
1869 PyObject * ret = PyList_New(n*i);
1870 for (ii = 0; ii < i; ii++)
1871 for (nn = 0; nn < n; nn++)
1872 {
1873 v = PyList_GetItem(obj1, nn);
1874 PyList_SetItem(ret, nn+ii*n, v);
1875 }
1876 return ret;
1877 }
1878 else if (PyList_Check(obj2) && ((arrayobject*)obj1)->ob_descr->typecode == 'i' && Py_SIZE(obj1) == 1)
1879 {
1880 int ii, nn;
1881 int n = PyList_Size(obj2);
1882 PyObject *v = getarrayitem(obj1, 0);
1883 int i = ((PyIntObject*)v)->ob_ival;
1884 PyObject * ret = PyList_New(n*i);
1885 for (ii = 0; ii < i; ii++)
1886 for (nn = 0; nn < n; nn++)
1887 {
1888 v = PyList_GetItem(obj2, nn);
1889 PyList_SetItem(ret, nn+ii*n, v);
1890 }
1891 return ret;
1892 }
1893 else if(obj1->ob_type == &Arraytype)
1894 fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
1895 ((arrayobject*)obj1)->ob_descr->typecode, obj2->ob_type->tp_name);
1896 else if(obj2->ob_type == &Arraytype)
1897 fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
1898 ((arrayobject*)obj2)->ob_descr->typecode, obj1->ob_type->tp_name);
1899 Py_INCREF(Py_NotImplemented);
1900 return Py_NotImplemented;
1901 }
1902
1903 static PyNumberMethods array_as_number = {
1904 (binaryfunc)NULL, /* nb_add*/
1905 (binaryfunc)NULL, /* nb_subtract */
1906 (binaryfunc)array_multiply, /* nb_multiply */
1907 (binaryfunc)NULL, /* nb_divide */
1908 };
1909
1910 static PyObject*
1911 array_base_multiply(PyObject* obj1, PyObject* obj2)
1912 {
1913 if (PyList_Check(obj1) && ((arrayobject*)obj2)->ob_descr->typecode == 'i' && Py_SIZE(obj2) == 1)
1914 {
1915 int nn;
1916 int n = PyList_Size(obj1);
1917 PyObject *v = getarrayitem(obj2, 0);
1918 int i = ((PyIntObject*)v)->ob_ival;
1919 PyObject * ret = PyList_New(n);
1920 for (nn = 0; nn < n; nn++)
1921 {
1922 v = PyList_GetItem(obj1, nn);
1923 if (PyInt_Check(v))
1924 PyList_SetItem(ret, nn, PyLong_FromLong(i * ((PyIntObject*)v)->ob_ival));
1925 else
1926 PyList_SetItem(ret, nn, v);
1927 }
1928 return ret;
1929 }
1930 else if (PyList_Check(obj2) && ((arrayobject*)obj1)->ob_descr->typecode == 'i' && Py_SIZE(obj1) == 1)
1931 {
1932 int nn;
1933 int n = PyList_Size(obj2);
1934 PyObject *v = getarrayitem(obj1, 0);
1935 int i = ((PyIntObject*)v)->ob_ival;
1936 PyObject * ret = PyList_New(n);
1937 for (nn = 0; nn < n; nn++)
1938 {
1939 v = PyList_GetItem(obj2, nn);
1940 if (PyInt_Check(v))
1941 PyList_SetItem(ret, nn, PyLong_FromLong(i * ((PyIntObject*)v)->ob_ival));
1942 else
1943 PyList_SetItem(ret, nn, v);
1944 }
1945 return ret;
1946 }
1947 else if(obj1->ob_type == &Arraytype)
1948 fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
1949 ((arrayobject*)obj1)->ob_descr->typecode, obj2->ob_type->tp_name);
1950 else if(obj2->ob_type == &Arraytype)
1951 fprintf(stderr, "\nCannot multiply array of type %c and %s\n",
1952 ((arrayobject*)obj2)->ob_descr->typecode, obj1->ob_type->tp_name);
1953 Py_INCREF(Py_NotImplemented);
1954 return Py_NotImplemented;
1955 }
1956
1957 static PyNumberMethods array_base_as_number = {
1958 (binaryfunc)NULL, /* nb_add*/
1959 (binaryfunc)NULL, /* nb_subtract */
1960 (binaryfunc)array_base_multiply, /* nb_multiply */
1961 (binaryfunc)NULL, /* nb_divide */
1962 };
18591963
18601964 static PyMappingMethods array_as_mapping = {
18611965 (lenfunc)array_length,
20392143 return array_new(type, args, NULL);
20402144 }
20412145
2146 static PyObject *
2147 switch_multiply(void)
2148 {
2149 Arraytype.tp_as_number->nb_multiply = array_base_multiply;
2150 Py_RETURN_NONE;
2151 };
2152
20422153 PyDoc_STRVAR(module_doc,
20432154 "This module defines an object type which can efficiently represent\n\
20442155 an array of basic values: characters, integers, floating point\n\
21052216
21062217 static PyObject *array_iter(arrayobject *ao);
21072218
2219 static PyTypeObject ArrayBasetype = {
2220 PyVarObject_HEAD_INIT(NULL, 0)
2221 "array.basearray",
2222 sizeof(arrayobject),
2223 0,
2224 (destructor)array_dealloc, /* tp_dealloc */
2225 0, /* tp_print */
2226 0, /* tp_getattr */
2227 0, /* tp_setattr */
2228 0, /* tp_compare */
2229 (reprfunc)array_repr, /* tp_repr */
2230 &array_base_as_number, /* tp_as_number*/
2231 &array_as_sequence, /* tp_as_sequence*/
2232 &array_as_mapping, /* tp_as_mapping*/
2233 0, /* tp_hash */
2234 0, /* tp_call */
2235 0, /* tp_str */
2236 PyObject_GenericGetAttr, /* tp_getattro */
2237 0, /* tp_setattro */
2238 &array_as_buffer, /* tp_as_buffer*/
2239 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
2240 Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
2241 arraytype_doc, /* tp_doc */
2242 0, /* tp_traverse */
2243 0, /* tp_clear */
2244 array_richcompare, /* tp_richcompare */
2245 offsetof(arrayobject, weakreflist), /* tp_weaklistoffset */
2246 (getiterfunc)array_iter, /* tp_iter */
2247 0, /* tp_iternext */
2248 array_methods, /* tp_methods */
2249 0, /* tp_members */
2250 array_getsets, /* tp_getset */
2251 0, /* tp_base */
2252 0, /* tp_dict */
2253 0, /* tp_descr_get */
2254 0, /* tp_descr_set */
2255 0, /* tp_dictoffset */
2256 0, /* tp_init */
2257 PyType_GenericAlloc, /* tp_alloc */
2258 array_new, /* tp_new */
2259 PyObject_Del, /* tp_free */
2260 };
2261
21082262 static PyTypeObject Arraytype = {
21092263 PyVarObject_HEAD_INIT(NULL, 0)
21102264 "array.array",
21162270 0, /* tp_setattr */
21172271 0, /* tp_compare */
21182272 (reprfunc)array_repr, /* tp_repr */
2119 0, /* tp_as_number*/
2273 &array_as_number, /* tp_as_number*/
21202274 &array_as_sequence, /* tp_as_sequence*/
21212275 &array_as_mapping, /* tp_as_mapping*/
21222276 0, /* tp_hash */
21252279 PyObject_GenericGetAttr, /* tp_getattro */
21262280 0, /* tp_setattro */
21272281 &array_as_buffer, /* tp_as_buffer*/
2128 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
2282 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
2283 Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
21292284 arraytype_doc, /* tp_doc */
21302285 0, /* tp_traverse */
21312286 0, /* tp_clear */
22452400 /* No functions in array module. */
22462401 static PyMethodDef a_methods[] = {
22472402 {"_reconstruct", (PyCFunction)_reconstruct, METH_VARARGS, NULL},
2403 {"switch_multiply", (PyCFunction)switch_multiply, METH_NOARGS, NULL},
22482404 {NULL, NULL, 0, NULL} /* Sentinel */
22492405 };
22502406
22592415 {
22602416 PyObject *m;
22612417
2418 ArrayBasetype.ob_type = &PyType_Type;
2419 Arraytype.tp_base = &ArrayBasetype;
22622420 Arraytype.ob_type = &PyType_Type;
22632421 PyArrayIter_Type.ob_type = &PyType_Type;
22642422 m = Py_InitModule3("array", a_methods, module_doc);
22652423 if (m == NULL)
22662424 return;
22672425
2268 Py_INCREF((PyObject *)&Arraytype);
2426 if (PyType_Ready(&ArrayBasetype) < 0)
2427 return;
22692428 if (PyType_Ready(&Arraytype) < 0)
22702429 return;
22712430 PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype);
2272 Py_INCREF((PyObject *)&Arraytype);
22732431 PyModule_AddObject(m, "array", (PyObject *)&Arraytype);
2274 /* No need to check the error here, the caller will do that */
2275 }
2432 PyModule_AddObject(m, "arraybase", (PyObject *)&ArrayBasetype);
2433 }
0 #ifdef _MSC_VER
1 #define _CRT_SECURE_NO_WARNINGS 1
2 #endif
3 #include <Python.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6
7 /*
8 * Adapted from https://jakevdp.github.io/blog/2014/05/05/introduction-to-the-python-buffer-protocol,
9 * which is copyright Jake Vanderplas and released under the BSD license
10 */
11
12 /* Structure defines a 1-dimensional strided array */
13 typedef struct{
14 int* arr;
15 Py_ssize_t length;
16 } MyArray;
17
18 /* initialize the array with integers 0...length */
19 void initialize_MyArray(MyArray* a, long length){
20 int i;
21 a->length = length;
22 a->arr = (int*)malloc(length * sizeof(int));
23 for(i=0; i<length; i++){
24 a->arr[i] = i;
25 }
26 }
27
28 /* free the memory when finished */
29 void deallocate_MyArray(MyArray* a){
30 free(a->arr);
31 a->arr = NULL;
32 }
33
34 /* tools to print the array */
35 char* stringify(MyArray* a, int nmax){
36 char* output = (char*) malloc(nmax * 20);
37 int k, pos = sprintf(&output[0], "[");
38
39 for (k=0; k < a->length && k < nmax; k++){
40 pos += sprintf(&output[pos], " %d", a->arr[k]);
41 }
42 if(a->length > nmax)
43 pos += sprintf(&output[pos], "...");
44 sprintf(&output[pos], " ]");
45 return output;
46 }
47
48 void print_MyArray(MyArray* a, int nmax){
49 char* s = stringify(a, nmax);
50 printf("%s", s);
51 free(s);
52 }
53
54 /* This is where we define the PyMyArray object structure */
55 typedef struct {
56 PyObject_HEAD
57 /* Type-specific fields go below. */
58 MyArray arr;
59 } PyMyArray;
60
61
62 /* This is the __init__ function, implemented in C */
63 static int
64 PyMyArray_init(PyMyArray *self, PyObject *args, PyObject *kwds)
65 {
66 int length = 0;
67 static char *kwlist[] = {"length", NULL};
68 // init may have already been called
69 if (self->arr.arr != NULL) {
70 deallocate_MyArray(&self->arr);
71 }
72
73 if (! PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &length))
74 return -1;
75
76 if (length < 0)
77 length = 0;
78
79 initialize_MyArray(&self->arr, length);
80
81 return 0;
82 }
83
84
85 /* this function is called when the object is deallocated */
86 static void
87 PyMyArray_dealloc(PyMyArray* self)
88 {
89 deallocate_MyArray(&self->arr);
90 Py_TYPE(self)->tp_free((PyObject*)self);
91 }
92
93
94 /* This function returns the string representation of our object */
95 static PyObject *
96 PyMyArray_str(PyMyArray * self)
97 {
98 char* s = stringify(&self->arr, 10);
99 PyObject* ret = PyUnicode_FromString(s);
100 free(s);
101 return ret;
102 }
103
104 /* Here is the buffer interface function */
105 static int
106 PyMyArray_getbuffer(PyObject *obj, Py_buffer *view, int flags)
107 {
108 PyMyArray* self = (PyMyArray*)obj;
109 fprintf(stdout, "in PyMyArray_getbuffer\n");
110 if (view == NULL) {
111 fprintf(stdout, "view is NULL\n");
112 PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer");
113 return -1;
114 }
115 if (flags == 0) {
116 fprintf(stdout, "flags is 0\n");
117 PyErr_SetString(PyExc_ValueError, "flags == 0 in getbuffer");
118 return -1;
119 }
120
121 view->obj = (PyObject*)self;
122 view->buf = (void*)self->arr.arr;
123 view->len = self->arr.length * sizeof(int);
124 view->readonly = 0;
125 view->itemsize = sizeof(int);
126 view->format = "i"; // integer
127 view->ndim = 1;
128 view->shape = &self->arr.length; // length-1 sequence of dimensions
129 view->strides = &view->itemsize; // for the simple case we can do this
130 view->suboffsets = NULL;
131 view->internal = NULL;
132
133 Py_INCREF(self); // need to increase the reference count
134 return 0;
135 }
136
137 static PyBufferProcs PyMyArray_as_buffer = {
138 #if PY_MAJOR_VERSION < 3
139 (readbufferproc)0,
140 (writebufferproc)0,
141 (segcountproc)0,
142 (charbufferproc)0,
143 #endif
144 (getbufferproc)PyMyArray_getbuffer,
145 (releasebufferproc)0, // we do not require any special release function
146 };
147
148
149 /* Here is the type structure: we put the above functions in the appropriate place
150 in order to actually define the Python object type */
151 static PyTypeObject PyMyArrayType = {
152 PyVarObject_HEAD_INIT(NULL, 0)
153 "pymyarray.PyMyArray", /* tp_name */
154 sizeof(PyMyArray), /* tp_basicsize */
155 0, /* tp_itemsize */
156 (destructor)PyMyArray_dealloc,/* tp_dealloc */
157 0, /* tp_print */
158 0, /* tp_getattr */
159 0, /* tp_setattr */
160 0, /* tp_reserved */
161 (reprfunc)PyMyArray_str, /* tp_repr */
162 0, /* tp_as_number */
163 0, /* tp_as_sequence */
164 0, /* tp_as_mapping */
165 0, /* tp_hash */
166 0, /* tp_call */
167 (reprfunc)PyMyArray_str, /* tp_str */
168 0, /* tp_getattro */
169 0, /* tp_setattro */
170 &PyMyArray_as_buffer, /* tp_as_buffer */
171 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */
172 "PyMyArray object", /* tp_doc */
173 0, /* tp_traverse */
174 0, /* tp_clear */
175 0, /* tp_richcompare */
176 0, /* tp_weaklistoffset */
177 0, /* tp_iter */
178 0, /* tp_iternext */
179 0, /* tp_methods */
180 0, /* tp_members */
181 0, /* tp_getset */
182 0, /* tp_base */
183 0, /* tp_dict */
184 0, /* tp_descr_get */
185 0, /* tp_descr_set */
186 0, /* tp_dictoffset */
187 (initproc)PyMyArray_init, /* tp_init */
188 };
189
190 static PyMethodDef buffer_functions[] = {
191 {NULL, NULL} /* Sentinel */
192 };
193
194 #if PY_MAJOR_VERSION >= 3
195 static struct PyModuleDef moduledef = {
196 PyModuleDef_HEAD_INIT,
197 "buffer_test",
198 "Module Doc",
199 -1,
200 buffer_functions;
201 NULL,
202 NULL,
203 NULL,
204 NULL,
205 };
206 #define INITERROR return NULL
207
208 /* Initialize this module. */
209 #ifdef __GNUC__
210 extern __attribute__((visibility("default")))
211 #else
212 extern __declspec(dllexport)
213 #endif
214
215 PyMODINIT_FUNC
216 PyInit_buffer_test(void)
217
218 #else
219
220 #define INITERROR return
221
222 /* Initialize this module. */
223 #ifdef __GNUC__
224 extern __attribute__((visibility("default")))
225 #else
226 #endif
227
228 PyMODINIT_FUNC
229 initbuffer_test(void)
230 #endif
231 {
232 #if PY_MAJOR_VERSION >= 3
233 PyObject *m= PyModule_Create(&moduledef);
234 #else
235 PyObject *m= Py_InitModule("buffer_test", buffer_functions);
236 #endif
237 if (m == NULL)
238 INITERROR;
239 PyMyArrayType.tp_new = PyType_GenericNew;
240 if (PyType_Ready(&PyMyArrayType) < 0)
241 INITERROR;
242 Py_INCREF(&PyMyArrayType);
243 PyModule_AddObject(m, "PyMyArray", (PyObject *)&PyMyArrayType);
244 #if PY_MAJOR_VERSION >=3
245 return m;
246 #endif
247 }
0 import py
0 import os
11 import pytest
22
33 def pytest_configure(config):
2020 def pytest_funcarg__api(request):
2121 return request.cls.api
2222
23 if os.name == 'nt':
24 @pytest.yield_fixture(autouse=True, scope='session')
25 def prevent_dialog_box():
26 """Do not open dreaded dialog box on segfault on Windows"""
27 import ctypes
28 SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN
29 old_err_mode = ctypes.windll.kernel32.GetErrorMode()
30 new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX
31 ctypes.windll.kernel32.SetErrorMode(new_err_mode)
32 yield
33 ctypes.windll.kernel32.SetErrorMode(old_err_mode)
00 #include "Python.h"
11 #include "structmember.h"
2
3 #if PY_MAJOR_VERSION >= 3
4 #define PyInt_FromLong PyLong_FromLong
5 #define PyInt_AsLong PyLong_AsLong
6 #define PyThing_FromStringAndSize PyUnicode_FromStringAndSize
7 #define PyThing_FromString PyUnicode_FromString
8 #define PyThing_Check PyUnicode_Check
9 #define _PyThing_AsString _PyUnicode_AsString
10 #else
11 #define PyThing_FromStringAndSize PyString_FromStringAndSize
12 #define PyThing_FromString PyString_FromString
13 #define PyThing_Check PyString_Check
14 #define _PyThing_AsString PyString_AsString
15 #endif
216
317 typedef struct {
418 PyObject_HEAD
4256
4357 /* foo methods */
4458
45 static void
46 foo_dealloc(fooobject *foop)
47 {
48 PyObject_Del(foop);
49 }
50
51
52 /* foo methods-as-attributes */
53
5459 static PyObject *
5560 foo_copy(fooobject *self)
5661 {
96101 static PyObject *
97102 foo_get_name(PyObject *self, void *closure)
98103 {
99 return PyString_FromStringAndSize("Foo Example", 11);
104 return PyThing_FromStringAndSize("Foo Example", 11);
100105 }
101106
102107 static PyObject *
122127 {
123128 PyObject *format;
124129
125 format = PyString_FromString("<Foo>");
130 format = PyThing_FromString("<Foo>");
126131 if (format == NULL) return NULL;
127132 return format;
128133 }
138143 foo_setattro(fooobject *self, PyObject *name, PyObject *value)
139144 {
140145 char *name_str;
141 if (!PyString_Check(name)) {
146 if (!PyThing_Check(name)) {
142147 PyErr_SetObject(PyExc_AttributeError, name);
143148 return -1;
144149 }
145 name_str = PyString_AsString(name);
150 name_str = _PyThing_AsString(name);
146151 if (strcmp(name_str, "set_foo") == 0)
147152 {
148153 long v = PyInt_AsLong(value);
194199 sizeof(fooobject), /*tp_size*/
195200 0, /*tp_itemsize*/
196201 /* methods */
197 (destructor)foo_dealloc, /*tp_dealloc*/
202 0, /*tp_dealloc*/
198203 0, /*tp_print*/
199204 0, /*tp_getattr*/
200205 0, /*tp_setattr*/
462467 PyTypeObject InitErrType = {
463468 PyObject_HEAD_INIT(NULL)
464469 0,
465 "foo.InitErr",
466 sizeof(PyObject),
467 0,
470 "foo.InitErrType",
471 sizeof(PyObject),/*tp_basicsize*/
472 0, /*tp_itemsize*/
468473 0, /*tp_dealloc*/
469474 0, /*tp_print*/
470475 0, /*tp_getattr*/
507512 0, /*tp_dictoffset*/
508513
509514 initerrtype_init, /*tp_init*/
510 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
515 0, /*tp_alloc*/
511516 0, /*tp_new*/
512 0, /*tp_free Low-level free-memory routine */
513 0, /*tp_is_gc For PyObject_IS_GC */
517 0, /*tp_free*/
518 0, /*tp_is_gc*/
514519 0, /*tp_bases*/
515 0, /*tp_mro method resolution order */
520 0, /*tp_mro*/
516521 0, /*tp_cache*/
517522 0, /*tp_subclasses*/
518523 0 /*tp_weaklist*/
628633 (destructor)custom_dealloc, /*tp_dealloc*/
629634 };
630635
636 static PyTypeObject TupleLike = {
637 PyObject_HEAD_INIT(NULL)
638 0,
639 "foo.TupleLike", /*tp_name*/
640 sizeof(PyObject), /*tp_size*/
641 };
642
643
631644 static PyObject *size_of_instances(PyObject *self, PyObject *t)
632645 {
633646 return PyInt_FromLong(((PyTypeObject *)t)->tp_basicsize);
647 }
648
649
650 static PyObject * is_TupleLike(PyObject *self, PyObject * t)
651 {
652 int tf = t->ob_type == &TupleLike;
653 if (t->ob_type->tp_itemsize == 0)
654 return PyInt_FromLong(-1);
655 return PyInt_FromLong(tf);
634656 }
635657
636658 /* List of functions exported by this module */
639661 {"new", (PyCFunction)foo_new, METH_NOARGS, NULL},
640662 {"newCustom", (PyCFunction)newCustom, METH_NOARGS, NULL},
641663 {"size_of_instances", (PyCFunction)size_of_instances, METH_O, NULL},
664 {"is_TupleLike", (PyCFunction)is_TupleLike, METH_O, NULL},
642665 {NULL, NULL} /* Sentinel */
643666 };
644667
668 #if PY_MAJOR_VERSION >= 3
669 static struct PyModuleDef moduledef = {
670 PyModuleDef_HEAD_INIT,
671 "foo",
672 "Module Doc",
673 -1,
674 foo_functions,
675 NULL,
676 NULL,
677 NULL,
678 NULL,
679 };
680 #define INITERROR return NULL
645681
646682 /* Initialize this module. */
647683 #ifdef __GNUC__
651687 #endif
652688
653689 PyMODINIT_FUNC
690 PyInit_foo(void)
691
692 #else
693
694 #define INITERROR return
695
696 /* Initialize this module. */
697 #ifdef __GNUC__
698 extern __attribute__((visibility("default")))
699 #else
700 extern __declspec(dllexport)
701 #endif
702
703 PyMODINIT_FUNC
654704 initfoo(void)
655 {
656 PyObject *m, *d;
705 #endif
706 {
707 PyObject *d;
708 #if PY_MAJOR_VERSION >= 3
709 PyObject *module = PyModule_Create(&moduledef);
710 #else
711 PyObject *module = Py_InitModule("foo", foo_functions);
712 #endif
713 if (module == NULL)
714 INITERROR;
657715
658716 footype.tp_new = PyType_GenericNew;
659717
662720 MetaType.tp_base = &PyType_Type;
663721
664722 if (PyType_Ready(&footype) < 0)
665 return;
723 INITERROR;
666724 if (PyType_Ready(&UnicodeSubtype) < 0)
667 return;
725 INITERROR;
668726 if (PyType_Ready(&UnicodeSubtype2) < 0)
669 return;
727 INITERROR;
670728 if (PyType_Ready(&MetaType) < 0)
671 return;
729 INITERROR;
672730 if (PyType_Ready(&InitErrType) < 0)
673 return;
731 INITERROR;
674732 if (PyType_Ready(&SimplePropertyType) < 0)
675 return;
733 INITERROR;
676734
677735 SimplePropertyType.tp_new = PyType_GenericNew;
678736 InitErrType.tp_new = PyType_GenericNew;
679737
680738 CustomType.ob_type = &MetaType;
681739 if (PyType_Ready(&CustomType) < 0)
682 return;
740 INITERROR;
683741
684742 UnicodeSubtype3.tp_flags = Py_TPFLAGS_DEFAULT;
685743 UnicodeSubtype3.tp_base = &UnicodeSubtype;
686744 UnicodeSubtype3.tp_bases = Py_BuildValue("(OO)", &UnicodeSubtype,
687745 &CustomType);
688746 if (PyType_Ready(&UnicodeSubtype3) < 0)
689 return;
690
691 m = Py_InitModule("foo", foo_functions);
692 if (m == NULL)
693 return;
694 d = PyModule_GetDict(m);
747 INITERROR;
748
749 TupleLike.tp_flags = Py_TPFLAGS_DEFAULT;
750 TupleLike.tp_base = &PyTuple_Type;
751 if (PyType_Ready(&TupleLike) < 0)
752 INITERROR;
753
754
755 d = PyModule_GetDict(module);
695756 if (d == NULL)
696 return;
757 INITERROR;
697758 if (PyDict_SetItemString(d, "fooType", (PyObject *)&footype) < 0)
698 return;
759 INITERROR;
699760 if (PyDict_SetItemString(d, "UnicodeSubtype", (PyObject *) &UnicodeSubtype) < 0)
700 return;
761 INITERROR;
701762 if (PyDict_SetItemString(d, "UnicodeSubtype2", (PyObject *) &UnicodeSubtype2) < 0)
702 return;
763 INITERROR;
703764 if (PyDict_SetItemString(d, "UnicodeSubtype3", (PyObject *) &UnicodeSubtype3) < 0)
704 return;
765 INITERROR;
705766 if (PyDict_SetItemString(d, "MetaType", (PyObject *) &MetaType) < 0)
706 return;
767 INITERROR;
707768 if (PyDict_SetItemString(d, "InitErrType", (PyObject *) &InitErrType) < 0)
708 return;
769 INITERROR;
709770 if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) < 0)
710 return;
771 INITERROR;
711772 if (PyDict_SetItemString(d, "Custom", (PyObject *) &CustomType) < 0)
712 return;
713 }
773 INITERROR;
774 if (PyDict_SetItemString(d, "TupleLike", (PyObject *) &TupleLike) < 0)
775 INITERROR;
776 #if PY_MAJOR_VERSION >=3
777 return module;
778 #endif
779 }
0 import os
1 import py
2 from sys import platform
3
4 if os.name != 'nt':
5 so_ext = 'so'
6 else:
7 so_ext = 'dll'
8
9 def c_compile(cfilenames, outputfilename,
10 compile_extra=None, link_extra=None,
11 include_dirs=None, libraries=None, library_dirs=None):
12 compile_extra = compile_extra or []
13 link_extra = link_extra or []
14 include_dirs = include_dirs or []
15 libraries = libraries or []
16 library_dirs = library_dirs or []
17 if platform == 'win32':
18 link_extra = link_extra + ['/DEBUG'] # generate .pdb file
19 if platform == 'darwin':
20 # support Fink & Darwinports
21 for s in ('/sw/', '/opt/local/'):
22 if (s + 'include' not in include_dirs
23 and os.path.exists(s + 'include')):
24 include_dirs.append(s + 'include')
25 if s + 'lib' not in library_dirs and os.path.exists(s + 'lib'):
26 library_dirs.append(s + 'lib')
27
28 outputfilename = py.path.local(outputfilename).new(ext=so_ext)
29 saved_environ = os.environ.copy()
30 try:
31 _build(
32 cfilenames, outputfilename,
33 compile_extra, link_extra,
34 include_dirs, libraries, library_dirs)
35 finally:
36 # workaround for a distutils bugs where some env vars can
37 # become longer and longer every time it is used
38 for key, value in saved_environ.items():
39 if os.environ.get(key) != value:
40 os.environ[key] = value
41 return outputfilename
42
43 def _build(cfilenames, outputfilename, compile_extra, link_extra,
44 include_dirs, libraries, library_dirs):
45 from distutils.ccompiler import new_compiler
46 from distutils import sysconfig
47 compiler = new_compiler(force=1)
48 sysconfig.customize_compiler(compiler) # XXX
49 objects = []
50 for cfile in cfilenames:
51 cfile = py.path.local(cfile)
52 old = cfile.dirpath().chdir()
53 try:
54 res = compiler.compile([cfile.basename],
55 include_dirs=include_dirs, extra_preargs=compile_extra)
56 assert len(res) == 1
57 cobjfile = py.path.local(res[0])
58 assert cobjfile.check()
59 objects.append(str(cobjfile))
60 finally:
61 old.chdir()
62
63 compiler.link_shared_object(
64 objects, str(outputfilename),
65 libraries=libraries,
66 extra_preargs=link_extra,
67 library_dirs=library_dirs)
7676 #assert s == "carray\n_reconstruct\np0\n(S'i'\np1\n(lp2\nI1\naI2\naI3\naI4\natp3\nRp4\n."
7777 rra = pickle.loads(s) # rra is arr backwards
7878 #assert arr.tolist() == rra.tolist()
79
80 def test_binop_mul_impl(self):
81 # check that rmul is called
82 module = self.import_module(name='array')
83 arr = module.array('i', [2])
84 res = [1, 2, 3] * arr
85 assert res == [1, 2, 3, 1, 2, 3]
86 module.switch_multiply()
87 res = [1, 2, 3] * arr
88 assert res == [2, 4, 6]
89
90 def test_subclass(self):
91 module = self.import_module(name='array')
92 class Sub(module.array):
93 pass
94
95 arr = Sub('i', [2])
96 res = [1, 2, 3] * arr
97 assert res == [1, 2, 3, 1, 2, 3]
98
00 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
1
12
23 class AppTestStringObject(AppTestCpythonExtensionBase):
34 def test_basic(self):
1516 """
1617 PyObject* s = PyByteArray_FromStringAndSize("Hello world", 12);
1718 int result = 0;
18 size_t expected_size;
1919
2020 if(PyByteArray_Size(s) == 12) {
2121 result = 1;
22 }
23 #ifdef PYPY_VERSION
24 expected_size = sizeof(void*)*3;
25 #elif defined Py_DEBUG
26 expected_size = 64;
27 #else
28 expected_size = 48;
29 #endif
30 if(s->ob_type->tp_basicsize != expected_size)
31 {
32 printf("tp_basicsize==%ld\\n",
33 (long)s->ob_type->tp_basicsize);
34 result = 0;
3522 }
3623 Py_DECREF(s);
3724 return PyBool_FromLong(result);
4027 """
4128 return PyBool_FromLong(PyByteArray_Check(PyTuple_GetItem(args, 0)));
4229 """)], prologue='#include <stdlib.h>')
43 assert module.get_hello1() == 'Hello world'
44 assert module.get_hello2() == 'Hello world\x00'
30 assert module.get_hello1() == b'Hello world'
31 assert module.get_hello2() == b'Hello world\x00'
4532 assert module.test_Size()
46 assert module.test_is_bytearray(bytearray(""))
33 assert module.test_is_bytearray(bytearray(b""))
4734 assert not module.test_is_bytearray(())
4835
4936 def test_bytearray_buffer_init(self):
5239 """
5340 PyObject *s, *t;
5441 char* c;
55 Py_ssize_t len;
5642
5743 s = PyByteArray_FromStringAndSize(NULL, 4);
5844 if (s == NULL)
7662 ])
7763 s = module.getbytearray()
7864 assert len(s) == 4
79 assert s == 'ab\x00c'
65 assert s == b'ab\x00c'
8066
8167 def test_bytearray_mutable(self):
8268 module = self.import_extension('foo', [
8369 ("mutable", "METH_NOARGS",
8470 """
8571 PyObject *base;
86 char * p_str;
8772 base = PyByteArray_FromStringAndSize("test", 10);
8873 if (PyByteArray_GET_SIZE(base) != 10)
8974 return PyLong_FromLong(-PyByteArray_GET_SIZE(base));
90 memcpy(PyByteArray_AS_STRING(base), "works", 6);
75 memcpy(PyByteArray_AS_STRING(base), "works", 6);
9176 Py_INCREF(base);
9277 return base;
9378 """),
9479 ])
9580 s = module.mutable()
96 if s == '\x00' * 10:
81 if s == b'\x00' * 10:
9782 assert False, "no RW access to bytearray"
98 assert s[:6] == 'works\x00'
83 assert s[:6] == b'works\x00'
9984
10085 def test_AsByteArray(self):
10186 module = self.import_extension('foo', [
10287 ("getbytearray", "METH_NOARGS",
10388 """
104 PyObject* s1 = PyByteArray_FromStringAndSize("test", 4);
89 const char *c;
90 PyObject *s2, *s1 = PyByteArray_FromStringAndSize("test", 4);
10591 if (s1 == NULL)
10692 return NULL;
107 const char* c = PyByteArray_AsString(s1);
108 PyObject* s2 = PyByteArray_FromStringAndSize(c, 4);
93 c = PyByteArray_AsString(s1);
94 s2 = PyByteArray_FromStringAndSize(c, 4);
10995 Py_DECREF(s1);
11096 return s2;
11197 """),
11298 ])
11399 s = module.getbytearray()
114 assert s == 'test'
100 assert s == b'test'
115101
116102 def test_manipulations(self):
103 import sys
117104 module = self.import_extension('foo', [
118 ("bytearray_from_string", "METH_VARARGS",
105 ("bytearray_from_bytes", "METH_VARARGS",
119106 '''
120 return PyByteArray_FromStringAndSize(PyString_AsString(
107 return PyByteArray_FromStringAndSize(PyBytes_AsString(
121108 PyTuple_GetItem(args, 0)), 4);
122109 '''
123110 ),
124 ("str_from_bytearray", "METH_VARARGS",
111 ("bytes_from_bytearray", "METH_VARARGS",
125112 '''
126113 char * buf;
127114 int n;
134121 return NULL;
135122 }
136123 n = PyByteArray_Size(obj);
137 return PyString_FromStringAndSize(buf, n);
124 return PyBytes_FromStringAndSize(buf, n);
138125 '''
139126 ),
140127 ("concat", "METH_VARARGS",
141128 """
142129 PyObject * ret, *right, *left;
143 PyObject *ba1, *ba2;
130 PyObject *ba1, *ba2;
144131 if (!PyArg_ParseTuple(args, "OO", &left, &right)) {
145 return PyString_FromString("parse failed");
132 return PyUnicode_FromString("parse failed");
146133 }
147134 ba1 = PyByteArray_FromObject(left);
148135 ba2 = PyByteArray_FromObject(right);
154141 ret = PyByteArray_Concat(ba1, ba2);
155142 return ret;
156143 """)])
157 assert module.bytearray_from_string("huheduwe") == "huhe"
158 assert module.str_from_bytearray(bytearray('abc')) == 'abc'
159 raises(ValueError, module.str_from_bytearray, 4.0)
160 ret = module.concat('abc', 'def')
161 assert ret == 'abcdef'
144 assert module.bytearray_from_bytes(b"huheduwe") == b"huhe"
145 assert module.bytes_from_bytearray(bytearray(b'abc')) == b'abc'
146 if '__pypy__' in sys.builtin_module_names:
147 # CPython only makes an assert.
148 raises(ValueError, module.bytes_from_bytearray, 4.0)
149 ret = module.concat(b'abc', b'def')
150 assert ret == b'abcdef'
162151 assert not isinstance(ret, str)
163152 assert isinstance(ret, bytearray)
164 raises(TypeError, module.concat, 'abc', u'def')
153 raises(TypeError, module.concat, b'abc', u'def')
165154
166155 def test_bytearray_resize(self):
167156 module = self.import_extension('foo', [
170159 PyObject *obj, *ba;
171160 int newsize, oldsize, ret;
172161 if (!PyArg_ParseTuple(args, "Oi", &obj, &newsize)) {
173 return PyString_FromString("parse failed");
162 return PyUnicode_FromString("parse failed");
174163 }
175
164
176165 ba = PyByteArray_FromObject(obj);
177166 if (ba == NULL)
178167 return NULL;
179168 oldsize = PyByteArray_Size(ba);
180169 if (oldsize == 0)
181170 {
182 return PyString_FromString("oldsize is 0");
171 return PyUnicode_FromString("oldsize is 0");
183172 }
184173 ret = PyByteArray_Resize(ba, newsize);
185174 if (ret != 0)
186175 {
187176 printf("ret, oldsize, newsize= %d, %d, %d\\n", ret, oldsize, newsize);
188177 return NULL;
189 }
178 }
190179 return ba;
191180 '''
192181 )])
193 ret = module.bytearray_resize('abc', 6)
182 ret = module.bytearray_resize(b'abc', 6)
194183 assert len(ret) == 6,"%s, len=%d" % (ret, len(ret))
195 assert ret == 'abc\x00\x00\x00'
196 ret = module.bytearray_resize('abcdefghi', 4)
184 assert ret == b'abc\x00\x00\x00'
185 ret = module.bytearray_resize(b'abcdefghi', 4)
197186 assert len(ret) == 4,"%s, len=%d" % (ret, len(ret))
198 assert ret == 'abcd'
199
187 assert ret == b'abcd'
11 from rpython.rtyper.lltypesystem import rffi, lltype
22 from pypy.module.cpyext.test.test_api import BaseApiTest
33 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
4 from pypy.module.cpyext.bytesobject import new_empty_str, PyStringObject
4 from pypy.module.cpyext.bytesobject import new_empty_str, PyBytesObject
55 from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP, generic_cpy_call
66 from pypy.module.cpyext.pyobject import Py_DecRef, from_ref, make_ref
77 from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr
99 import py
1010 import sys
1111
12 class AppTestStringObject(AppTestCpythonExtensionBase):
13 def test_stringobject(self):
12 class AppTestBytesObject(AppTestCpythonExtensionBase):
13 def test_bytesobject(self):
1414 module = self.import_extension('foo', [
1515 ("get_hello1", "METH_NOARGS",
1616 """
17 return PyString_FromStringAndSize(
17 return PyBytes_FromStringAndSize(
1818 "Hello world<should not be included>", 11);
1919 """),
2020 ("get_hello2", "METH_NOARGS",
2121 """
22 return PyString_FromString("Hello world");
22 return PyBytes_FromString("Hello world");
2323 """),
2424 ("test_Size", "METH_NOARGS",
2525 """
26 PyObject* s = PyString_FromString("Hello world");
27 int result = 0;
28 size_t expected_size;
29
30 if(PyString_Size(s) == 11) {
31 result = 1;
32 }
33 #ifdef PYPY_VERSION
34 expected_size = sizeof(void*)*7;
35 #elif defined Py_DEBUG
36 expected_size = 53;
37 #else
38 expected_size = 37;
39 #endif
40 if(s->ob_type->tp_basicsize != expected_size)
41 {
42 printf("tp_basicsize==%zd\\n", s->ob_type->tp_basicsize);
43 result = 0;
44 }
26 PyObject* s = PyBytes_FromString("Hello world");
27 int result = PyBytes_Size(s);
28
4529 Py_DECREF(s);
46 return PyBool_FromLong(result);
30 return PyLong_FromLong(result);
4731 """),
4832 ("test_Size_exception", "METH_NOARGS",
4933 """
5034 PyObject* f = PyFloat_FromDouble(1.0);
51 Py_ssize_t size = PyString_Size(f);
35 PyBytes_Size(f);
5236
5337 Py_DECREF(f);
5438 return NULL;
5539 """),
56 ("test_is_string", "METH_VARARGS",
57 """
58 return PyBool_FromLong(PyString_Check(PyTuple_GetItem(args, 0)));
40 ("test_is_bytes", "METH_VARARGS",
41 """
42 return PyBool_FromLong(PyBytes_Check(PyTuple_GetItem(args, 0)));
5943 """)], prologue='#include <stdlib.h>')
60 assert module.get_hello1() == 'Hello world'
61 assert module.get_hello2() == 'Hello world'
62 assert module.test_Size()
44 assert module.get_hello1() == b'Hello world'
45 assert module.get_hello2() == b'Hello world'
46 assert module.test_Size() == 11
6347 raises(TypeError, module.test_Size_exception)
6448
65 assert module.test_is_string("")
66 assert not module.test_is_string(())
67
68 def test_string_buffer_init(self):
69 module = self.import_extension('foo', [
70 ("getstring", "METH_NOARGS",
49 assert module.test_is_bytes(b"")
50 assert not module.test_is_bytes(())
51
52 def test_bytes_buffer_init(self):
53 module = self.import_extension('foo', [
54 ("getbytes", "METH_NOARGS",
7155 """
7256 PyObject *s, *t;
7357 char* c;
74 Py_ssize_t len;
75
76 s = PyString_FromStringAndSize(NULL, 4);
58
59 s = PyBytes_FromStringAndSize(NULL, 4);
7760 if (s == NULL)
7861 return NULL;
79 t = PyString_FromStringAndSize(NULL, 3);
62 t = PyBytes_FromStringAndSize(NULL, 3);
8063 if (t == NULL)
8164 return NULL;
8265 Py_DECREF(t);
83 c = PyString_AsString(s);
66 c = PyBytes_AS_STRING(s);
8467 c[0] = 'a';
8568 c[1] = 'b';
8669 c[2] = 0;
8871 return s;
8972 """),
9073 ])
91 s = module.getstring()
74 s = module.getbytes()
9275 assert len(s) == 4
93 assert s == 'ab\x00c'
94
95 def test_string_tp_alloc(self):
76 assert s == b'ab\x00c'
77
78 def test_bytes_tp_alloc(self):
9679 module = self.import_extension('foo', [
9780 ("tpalloc", "METH_NOARGS",
9881 """
9982 PyObject *base;
10083 PyTypeObject * type;
101 PyStringObject *obj;
102 char * p_str;
103 base = PyString_FromString("test");
104 if (PyString_GET_SIZE(base) != 4)
105 return PyLong_FromLong(-PyString_GET_SIZE(base));
84 PyBytesObject *obj;
85 base = PyBytes_FromString("test");
86 if (PyBytes_GET_SIZE(base) != 4)
87 return PyLong_FromLong(-PyBytes_GET_SIZE(base));
10688 type = base->ob_type;
10789 if (type->tp_itemsize != 1)
10890 return PyLong_FromLong(type->tp_itemsize);
109 obj = (PyStringObject*)type->tp_alloc(type, 10);
110 if (PyString_GET_SIZE(obj) != 10)
111 return PyLong_FromLong(PyString_GET_SIZE(obj));
91 obj = (PyBytesObject*)type->tp_alloc(type, 10);
92 if (PyBytes_GET_SIZE(obj) != 10)
93 return PyLong_FromLong(PyBytes_GET_SIZE(obj));
11294 /* cannot work, there is only RO access
113 memcpy(PyString_AS_STRING(obj), "works", 6); */
95 memcpy(PyBytes_AS_STRING(obj), "works", 6); */
11496 Py_INCREF(obj);
11597 return (PyObject*)obj;
11698 """),
117 ])
99 ('alloc_rw', "METH_NOARGS",
100 '''
101 PyObject *obj = _PyObject_NewVar(&PyBytes_Type, 10);
102 memcpy(PyBytes_AS_STRING(obj), "works", 6);
103 return (PyObject*)obj;
104 '''),
105 ])
106 s = module.alloc_rw()
107 assert s == b'works' + b'\x00' * 5
118108 s = module.tpalloc()
119 assert s == '\x00' * 10
109 assert s == b'\x00' * 10
120110
121111 def test_AsString(self):
122112 module = self.import_extension('foo', [
123 ("getstring", "METH_NOARGS",
124 """
125 PyObject* s1 = PyString_FromStringAndSize("test", 4);
126 char* c = PyString_AsString(s1);
127 PyObject* s2 = PyString_FromStringAndSize(c, 4);
113 ("getbytes", "METH_NOARGS",
114 """
115 char *c;
116 PyObject* s2, *s1 = PyBytes_FromStringAndSize("test", 4);
117 c = PyBytes_AsString(s1);
118 s2 = PyBytes_FromStringAndSize(c, 4);
128119 Py_DECREF(s1);
129120 return s2;
130121 """),
131122 ])
132 s = module.getstring()
133 assert s == 'test'
123 s = module.getbytes()
124 assert s == b'test'
134125
135126 def test_manipulations(self):
136127 module = self.import_extension('foo', [
137 ("string_as_string", "METH_VARARGS",
138 '''
139 return PyString_FromStringAndSize(PyString_AsString(
128 ("bytes_as_string", "METH_VARARGS",
129 '''
130 return PyBytes_FromStringAndSize(PyBytes_AsString(
140131 PyTuple_GetItem(args, 0)), 4);
141132 '''
142133 ),
146137 PyObject * left = PyTuple_GetItem(args, 0);
147138 Py_INCREF(left); /* the reference will be stolen! */
148139 v = &left;
149 PyString_Concat(v, PyTuple_GetItem(args, 1));
140 PyBytes_Concat(v, PyTuple_GetItem(args, 1));
150141 return *v;
151142 """)])
152 assert module.string_as_string("huheduwe") == "huhe"
153 ret = module.concat('abc', 'def')
154 assert ret == 'abcdef'
143 assert module.bytes_as_string(b"huheduwe") == b"huhe"
144 ret = module.concat(b'abc', b'def')
145 assert ret == b'abcdef'
155146 ret = module.concat('abc', u'def')
156147 assert not isinstance(ret, str)
157148 assert isinstance(ret, unicode)
158149 assert ret == 'abcdef'
159150
160 def test_py_string_as_string_None(self):
151 def test_py_bytes_as_string_None(self):
161152 module = self.import_extension('foo', [
162153 ("string_None", "METH_VARARGS",
163154 '''
164 if (PyString_AsString(Py_None)) {
155 if (PyBytes_AsString(Py_None)) {
165156 Py_RETURN_NONE;
166157 }
167158 return NULL;
171162
172163 def test_AsStringAndSize(self):
173164 module = self.import_extension('foo', [
174 ("getstring", "METH_NOARGS",
175 """
176 PyObject* s1 = PyString_FromStringAndSize("te\\0st", 5);
165 ("getbytes", "METH_NOARGS",
166 """
167 PyObject* s1 = PyBytes_FromStringAndSize("te\\0st", 5);
177168 char *buf;
178169 Py_ssize_t len;
179 if (PyString_AsStringAndSize(s1, &buf, &len) < 0)
170 if (PyBytes_AsStringAndSize(s1, &buf, &len) < 0)
180171 return NULL;
181172 if (len != 5) {
182173 PyErr_SetString(PyExc_AssertionError, "Bad Length");
183174 return NULL;
184175 }
185 if (PyString_AsStringAndSize(s1, &buf, NULL) >= 0) {
176 if (PyBytes_AsStringAndSize(s1, &buf, NULL) >= 0) {
186177 PyErr_SetString(PyExc_AssertionError, "Should Have failed");
187178 return NULL;
188179 }
192183 return Py_None;
193184 """),
194185 ])
195 module.getstring()
186 module.getbytes()
196187
197188 def test_py_string_as_string_Unicode(self):
198189 module = self.import_extension('foo', [
275266 PyObject *s = args;
276267 Py_INCREF(s);
277268 PyString_InternInPlace(&s);
278 if (((PyStringObject*)s)->ob_sstate == SSTATE_NOT_INTERNED)
269 if (((PyBytesObject*)s)->ob_sstate == SSTATE_NOT_INTERNED)
279270 {
280271 Py_DECREF(s);
281272 s = PyString_FromString("interned error");
293284 ("test_macro_invocations", "METH_NOARGS",
294285 """
295286 PyObject* o = PyString_FromString("");
296 PyStringObject* u = (PyStringObject*)o;
287 PyBytesObject* u = (PyBytesObject*)o;
297288
298289 PyString_GET_SIZE(u);
299290 PyString_GET_SIZE(o);
310301 ("test_hash", "METH_VARARGS",
311302 '''
312303 PyObject* obj = (PyTuple_GetItem(args, 0));
313 long hash = ((PyStringObject*)obj)->ob_shash;
314 return PyLong_FromLong(hash);
304 long hash = ((PyBytesObject*)obj)->ob_shash;
305 return PyLong_FromLong(hash);
315306 '''
316307 ),
317308 ("test_sstate", "METH_NOARGS",
318309 '''
319310 PyObject *s = PyString_FromString("xyz");
320 int sstate = ((PyStringObject*)s)->ob_sstate;
321 /*printf("sstate now %d\\n", sstate);*/
311 /*int sstate = ((PyBytesObject*)s)->ob_sstate;
312 printf("sstate now %d\\n", sstate);*/
322313 PyString_InternInPlace(&s);
323 sstate = ((PyStringObject*)s)->ob_sstate;
324 /*printf("sstate now %d\\n", sstate);*/
314 /*sstate = ((PyBytesObject*)s)->ob_sstate;
315 printf("sstate now %d\\n", sstate);*/
325316 Py_DECREF(s);
326317 return PyBool_FromLong(1);
327318 '''),
331322 # doesn't really test, but if printf is enabled will prove sstate
332323 assert module.test_sstate()
333324
334
335 class TestString(BaseApiTest):
336 def test_string_resize(self, space, api):
325 def test_subclass(self):
326 # taken from PyStringArrType_Type in numpy's scalartypes.c.src
327 module = self.import_extension('bar', [
328 ("newsubstr", "METH_O",
329 """
330 PyObject * obj;
331 char * data;
332 int len;
333 PyType_Ready(&PyStringArrType_Type);
334
335 data = PyString_AS_STRING(args);
336 len = PyString_GET_SIZE(args);
337 if (data == NULL || len < 1)
338 Py_RETURN_NONE;
339 obj = PyArray_Scalar(data, len);
340 return obj;
341 """),
342 ], prologue="""
343 #include <Python.h>
344 PyTypeObject PyStringArrType_Type = {
345 PyObject_HEAD_INIT(NULL)
346 0, /* ob_size */
347 "bar.string_", /* tp_name*/
348 sizeof(PyBytesObject), /* tp_basicsize*/
349 0 /* tp_itemsize */
350 };
351
352 static PyObject *
353 stringtype_repr(PyObject *self)
354 {
355 const char *dptr, *ip;
356 int len;
357 PyObject *new;
358
359 ip = dptr = PyString_AS_STRING(self);
360 len = PyString_GET_SIZE(self);
361 dptr += len-1;
362 while(len > 0 && *dptr-- == 0) {
363 len--;
364 }
365 new = PyString_FromStringAndSize(ip, len);
366 if (new == NULL) {
367 return PyString_FromString("");
368 }
369 return new;
370 }
371
372 static PyObject *
373 stringtype_str(PyObject *self)
374 {
375 const char *dptr, *ip;
376 int len;
377 PyObject *new;
378
379 ip = dptr = PyString_AS_STRING(self);
380 len = PyString_GET_SIZE(self);
381 dptr += len-1;
382 while(len > 0 && *dptr-- == 0) {
383 len--;
384 }
385 new = PyString_FromStringAndSize(ip, len);
386 if (new == NULL) {
387 return PyString_FromString("");
388 }
389 return new;
390 }
391
392 PyObject *
393 PyArray_Scalar(char *data, int n)
394 {
395 PyTypeObject *type = &PyStringArrType_Type;
396 PyObject *obj;
397 void *destptr;
398 int itemsize = n;
399 obj = type->tp_alloc(type, itemsize);
400 if (obj == NULL) {
401 return NULL;
402 }
403 destptr = PyString_AS_STRING(obj);
404 ((PyBytesObject *)obj)->ob_shash = -1;
405 memcpy(destptr, data, itemsize);
406 return obj;
407 }
408 """, more_init = '''
409 PyStringArrType_Type.tp_alloc = NULL;
410 PyStringArrType_Type.tp_free = NULL;
411
412 PyStringArrType_Type.tp_repr = stringtype_repr;
413 PyStringArrType_Type.tp_str = stringtype_str;
414 PyStringArrType_Type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
415 PyStringArrType_Type.tp_itemsize = sizeof(char);
416 PyStringArrType_Type.tp_base = &PyString_Type;
417 ''')
418
419 a = module.newsubstr('abc')
420 assert type(a).__name__ == 'string_'
421 assert a == 'abc'
422
423 class TestBytes(BaseApiTest):
424 def test_bytes_resize(self, space, api):
337425 py_str = new_empty_str(space, 10)
338426 ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
339 py_str.c_buffer[0] = 'a'
340 py_str.c_buffer[1] = 'b'
341 py_str.c_buffer[2] = 'c'
427 py_str.c_ob_sval[0] = 'a'
428 py_str.c_ob_sval[1] = 'b'
429 py_str.c_ob_sval[2] = 'c'
342430 ar[0] = rffi.cast(PyObject, py_str)
343431 api._PyString_Resize(ar, 3)
344 py_str = rffi.cast(PyStringObject, ar[0])
432 py_str = rffi.cast(PyBytesObject, ar[0])
345433 assert py_str.c_ob_size == 3
346 assert py_str.c_buffer[1] == 'b'
347 assert py_str.c_buffer[3] == '\x00'
434 assert py_str.c_ob_sval[1] == 'b'
435 assert py_str.c_ob_sval[3] == '\x00'
348436 # the same for growing
349437 ar[0] = rffi.cast(PyObject, py_str)
350438 api._PyString_Resize(ar, 10)
351 py_str = rffi.cast(PyStringObject, ar[0])
439 py_str = rffi.cast(PyBytesObject, ar[0])
352440 assert py_str.c_ob_size == 10
353 assert py_str.c_buffer[1] == 'b'
354 assert py_str.c_buffer[10] == '\x00'
441 assert py_str.c_ob_sval[1] == 'b'
442 assert py_str.c_ob_sval[10] == '\x00'
355443 Py_DecRef(space, ar[0])
356444 lltype.free(ar, flavor='raw')
357445
66 from pypy import pypydir
77 from pypy.interpreter import gateway
88 from rpython.rtyper.lltypesystem import lltype, ll2ctypes
9 from rpython.translator.tool.cbuild import ExternalCompilationInfo
10 from rpython.translator import platform
119 from rpython.translator.gensupp import uniquemodulename
1210 from rpython.tool.udir import udir
1311 from pypy.module.cpyext import api
1715 from rpython.tool import leakfinder
1816 from rpython.rlib import rawrefcount
1917
20 def setup_module(module):
21 if os.name == 'nt':
22 # Do not open dreaded dialog box on segfault
23 import ctypes
24 SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN
25 old_err_mode = ctypes.windll.kernel32.GetErrorMode()
26 new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX
27 ctypes.windll.kernel32.SetErrorMode(new_err_mode)
28 module.old_err_mode = old_err_mode
29
30 def teardown_module(module):
31 if os.name == 'nt':
32 import ctypes
33 ctypes.windll.kernel32.SetErrorMode(module.old_err_mode)
18 from .support import c_compile
3419
3520 @api.cpython_api([], api.PyObject)
3621 def PyPy_Crash1(space):
4530 assert 'PyModule_Check' in api.FUNCTIONS
4631 assert api.FUNCTIONS['PyModule_Check'].argtypes == [api.PyObject]
4732
48 def compile_extension_module(space, modname, include_dirs=[], **kwds):
33 def convert_sources_to_files(sources, dirname):
34 files = []
35 for i, source in enumerate(sources):
36 filename = dirname / ('source_%d.c' % i)
37 with filename.open('w') as f:
38 f.write(str(source))
39 files.append(filename)
40 return files
41
42 def create_so(modname, include_dirs, source_strings=None, source_files=None,
43 compile_extra=None, link_extra=None, libraries=None):
44 dirname = (udir/uniquemodulename('module')).ensure(dir=1)
45 if source_strings:
46 assert not source_files
47 files = convert_sources_to_files(source_strings, dirname)
48 source_files = files
49 soname = c_compile(source_files, outputfilename=str(dirname/modname),
50 compile_extra=compile_extra, link_extra=link_extra,
51 include_dirs=include_dirs,
52 libraries=libraries)
53 return soname
54
55 def compile_extension_module(space, modname, include_dirs=[],
56 source_files=None, source_strings=None):
4957 """
5058 Build an extension module and return the filename of the resulting native
5159 code file.
5967 state = space.fromcache(State)
6068 api_library = state.api_lib
6169 if sys.platform == 'win32':
62 kwds["libraries"] = [api_library]
70 libraries = [api_library]
6371 # '%s' undefined; assuming extern returning int
64 kwds["compile_extra"] = ["/we4013"]
72 compile_extra = ["/we4013"]
6573 # prevent linking with PythonXX.lib
6674 w_maj, w_min = space.fixedview(space.sys.get('version_info'), 5)[:2]
67 kwds["link_extra"] = ["/NODEFAULTLIB:Python%d%d.lib" %
75 link_extra = ["/NODEFAULTLIB:Python%d%d.lib" %
6876 (space.int_w(w_maj), space.int_w(w_min))]
69 elif sys.platform == 'darwin':
70 kwds["link_files"] = [str(api_library + '.dylib')]
7177 else:
72 kwds["link_files"] = [str(api_library + '.so')]
78 libraries = []
7379 if sys.platform.startswith('linux'):
74 kwds["compile_extra"]=["-Werror", "-g", "-O0"]
75 kwds["link_extra"]=["-g"]
80 compile_extra = ["-Werror", "-g", "-O0", "-Wp,-U_FORTIFY_SOURCE", "-fPIC"]
81 link_extra = ["-g"]
82 else:
83 compile_extra = link_extra = None
7684
7785 modname = modname.split('.')[-1]
78 eci = ExternalCompilationInfo(
79 include_dirs=api.include_dirs + include_dirs,
80 **kwds
81 )
82 eci = eci.convert_sources_to_files()
83 dirname = (udir/uniquemodulename('module')).ensure(dir=1)
84 soname = platform.platform.compile(
85 [], eci,
86 outputfilename=str(dirname/modname),
87 standalone=False)
86 soname = create_so(modname,
87 include_dirs=api.include_dirs + include_dirs,
88 source_files=source_files,
89 source_strings=source_strings,
90 compile_extra=compile_extra,
91 link_extra=link_extra,
92 libraries=libraries)
8893 from pypy.module.imp.importing import get_so_extension
8994 pydname = soname.new(purebasename=modname, ext=get_so_extension(space))
9095 soname.rename(pydname)
9196 return str(pydname)
9297
93 def compile_extension_module_applevel(space, modname, include_dirs=[], **kwds):
98 def compile_extension_module_applevel(space, modname, include_dirs=[],
99 source_files=None, source_strings=None):
94100 """
95101 Build an extension module and return the filename of the resulting native
96102 code file.
102108 build the module (so specify your source with one of those).
103109 """
104110 if sys.platform == 'win32':
105 kwds["compile_extra"] = ["/we4013"]
106 kwds["link_extra"] = ["/LIBPATH:" + os.path.join(sys.exec_prefix, 'libs')]
111 compile_extra = ["/we4013"]
112 link_extra = ["/LIBPATH:" + os.path.join(sys.exec_prefix, 'libs')]
107113 elif sys.platform == 'darwin':
114 compile_extra = link_extra = None
108115 pass
109116 elif sys.platform.startswith('linux'):
110 kwds["compile_extra"]=["-O0", "-g","-Werror=implicit-function-declaration"]
117 compile_extra = [
118 "-O0", "-g", "-Werror=implicit-function-declaration", "-fPIC"]
119 link_extra = None
111120
112121 modname = modname.split('.')[-1]
113 eci = ExternalCompilationInfo(
114 include_dirs = [space.include_dir] + include_dirs,
115 **kwds
116 )
117 eci = eci.convert_sources_to_files()
118 dirname = (udir/uniquemodulename('module')).ensure(dir=1)
119 soname = platform.platform.compile(
120 [], eci,
121 outputfilename=str(dirname/modname),
122 standalone=False)
123 return str(soname)
122 soname = create_so(modname,
123 include_dirs=[space.include_dir] + include_dirs,
124 source_files=source_files,
125 source_strings=source_strings,
126 compile_extra=compile_extra,
127 link_extra=link_extra)
128 from imp import get_suffixes, C_EXTENSION
129 pydname = soname
130 for suffix, mode, typ in get_suffixes():
131 if typ == C_EXTENSION:
132 pydname = soname.new(purebasename=modname, ext=suffix)
133 soname.rename(pydname)
134 break
135 return str(pydname)
124136
125137 def freeze_refcnts(self):
138 rawrefcount._dont_free_any_more()
126139 return #ZZZ
127140 state = self.space.fromcache(RefcountState)
128141 self.frozen_refcounts = {}
284297 separate_module_sources = []
285298 pydname = self.compile_extension_module(
286299 space, name,
287 separate_module_files=separate_module_files,
288 separate_module_sources=separate_module_sources)
300 source_files=separate_module_files,
301 source_strings=separate_module_sources)
289302 return space.wrap(pydname)
290303
291304 @gateway.unwrap_spec(name=str, init='str_or_None', body=str,
314327 /* fix for cpython 2.7 Python.h if running tests with -A
315328 since pypy compiles with -fvisibility-hidden */
316329 #undef PyMODINIT_FUNC
330 #ifdef __GNUC__
331 # define RPY_EXPORTED extern __attribute__((visibility("default")))
332 #else
333 # define RPY_EXPORTED extern __declspec(dllexport)
334 #endif
317335 #define PyMODINIT_FUNC RPY_EXPORTED void
318336
319337 %(body)s
325343 """ % dict(name=name, init=init, body=body,
326344 PY_SSIZE_T_CLEAN='#define PY_SSIZE_T_CLEAN'
327345 if PY_SSIZE_T_CLEAN else '')
328 kwds = dict(separate_module_sources=[code])
346 kwds = dict(source_strings=[code])
329347 else:
330348 assert not PY_SSIZE_T_CLEAN
331349 if filename is None:
332350 filename = name
333351 filename = py.path.local(pypydir) / 'module' \
334352 / 'cpyext'/ 'test' / (filename + ".c")
335 kwds = dict(separate_module_files=[filename])
336 kwds['include_dirs'] = include_dirs
337 mod = self.compile_extension_module(space, name, **kwds)
353 kwds = dict(source_files=[filename])
354 mod = self.compile_extension_module(space, name,
355 include_dirs=include_dirs, **kwds)
338356
339357 if load_it:
340358 if self.runappdirect:
347365 space.sys.get('modules'),
348366 space.wrap(name))
349367 else:
350 return os.path.dirname(mod)
368 path = os.path.dirname(mod)
369 if self.runappdirect:
370 return path
371 else:
372 return space.wrap(path)
351373
352374 @gateway.unwrap_spec(mod=str, name=str)
353375 def reimport_module(space, mod, name):
974996 ('bar', 'METH_NOARGS',
975997 '''
976998 /* reuse a name that is #defined in structmember.h */
977 int RO;
999 int RO = 0; (void)RO;
9781000 Py_RETURN_NONE;
9791001 '''
9801002 ),
141141 2000, 6, 6, 6, 6, 6, 6, Py_None,
142142 PyDateTimeAPI->DateTimeType);
143143 """),
144 ])
144 ], prologue='#include "datetime.h"\n')
145145 import datetime
146146 assert module.new_date() == datetime.date(2000, 6, 6)
147147 assert module.new_time() == datetime.time(6, 6, 6, 6)
175175 """),
176176 ("test_datetime_macros", "METH_NOARGS",
177177 """
178 PyDateTime_IMPORT;
179 if (!PyDateTimeAPI) {
180 PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
181 return NULL;
182 }
183 PyObject* obj = PyDateTime_FromDateAndTime(2000, 6, 6, 6, 6, 6, 6);
184 PyDateTime_DateTime* dt = (PyDateTime_DateTime*)obj;
178 PyObject* obj;
179 PyDateTime_DateTime *dt;
180 PyDateTime_IMPORT;
181 if (!PyDateTimeAPI) {
182 PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
183 return NULL;
184 }
185 obj = PyDateTime_FromDateAndTime(2000, 6, 6, 6, 6, 6, 6);
186 dt = (PyDateTime_DateTime*)obj;
185187
186188 PyDateTime_GET_YEAR(obj);
187189 PyDateTime_GET_YEAR(dt);
208210 """),
209211 ("test_time_macros", "METH_NOARGS",
210212 """
211 PyDateTime_IMPORT;
212 if (!PyDateTimeAPI) {
213 PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
214 return NULL;
215 }
216 PyObject* obj = PyTime_FromTime(6, 6, 6, 6);
217 PyDateTime_Time* t = (PyDateTime_Time*)obj;
213 PyObject* obj;
214 PyDateTime_Time* t;
215 PyDateTime_IMPORT;
216 if (!PyDateTimeAPI) {
217 PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
218 return NULL;
219 }
220 obj = PyTime_FromTime(6, 6, 6, 6);
221 t = (PyDateTime_Time*)obj;
218222
219223 PyDateTime_TIME_GET_HOUR(obj);
220224 PyDateTime_TIME_GET_HOUR(t);
232236 """),
233237 ("test_delta_macros", "METH_NOARGS",
234238 """
235 PyDateTime_IMPORT;
236 if (!PyDateTimeAPI) {
237 PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
238 return NULL;
239 }
240 PyObject* obj = PyDelta_FromDSU(6, 6, 6);
241 PyDateTime_Delta* delta = (PyDateTime_Delta*)obj;
242
239 PyObject* obj;
240 PyDateTime_Delta* delta;
241 PyDateTime_IMPORT;
242 if (!PyDateTimeAPI) {
243 PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
244 return NULL;
245 }
246 obj = PyDelta_FromDSU(6, 6, 6);
247 delta = (PyDateTime_Delta*)obj;
248
249 #if defined(PYPY_VERSION) || PY_VERSION_HEX >= 0x03030000
250 // These macros are only defined in CPython 3.x and PyPy.
251 // See: http://bugs.python.org/issue13727
243252 PyDateTime_DELTA_GET_DAYS(obj);
244253 PyDateTime_DELTA_GET_DAYS(delta);
245254
248257
249258 PyDateTime_DELTA_GET_MICROSECONDS(obj);
250259 PyDateTime_DELTA_GET_MICROSECONDS(delta);
251
252 return obj;
253 """),
254 ])
260 #endif
261 return obj;
262 """),
263 ], prologue='#include "datetime.h"\n')
255264 import datetime
256265 assert module.test_date_macros() == datetime.date(2000, 6, 6)
257266 assert module.test_datetime_macros() == datetime.datetime(
22 from pypy.module.cpyext.test.test_api import BaseApiTest
33 from pypy.module.cpyext.eval import (
44 Py_single_input, Py_file_input, Py_eval_input, PyCompilerFlags)
5 from pypy.module.cpyext.api import fopen, fclose, fileno, Py_ssize_tP
5 from pypy.module.cpyext.api import c_fopen, c_fclose, c_fileno, Py_ssize_tP
66 from pypy.interpreter.gateway import interp2app
77 from pypy.interpreter.astcompiler import consts
88 from rpython.tool.udir import udir
129129 def test_run_file(self, space, api):
130130 filepath = udir / "cpyext_test_runfile.py"
131131 filepath.write("raise ZeroDivisionError")
132 fp = fopen(str(filepath), "rb")
132 fp = c_fopen(str(filepath), "rb")
133133 filename = rffi.str2charp(str(filepath))
134134 w_globals = w_locals = space.newdict()
135135 api.PyRun_File(fp, filename, Py_file_input, w_globals, w_locals)
136 fclose(fp)
136 c_fclose(fp)
137137 assert api.PyErr_Occurred() is space.w_ZeroDivisionError
138138 api.PyErr_Clear()
139139
140140 # try again, but with a closed file
141 fp = fopen(str(filepath), "rb")
142 os.close(fileno(fp))
141 fp = c_fopen(str(filepath), "rb")
142 os.close(c_fileno(fp))
143143 api.PyRun_File(fp, filename, Py_file_input, w_globals, w_locals)
144 fclose(fp)
144 c_fclose(fp)
145145 assert api.PyErr_Occurred() is space.w_IOError
146146 api.PyErr_Clear()
147147
1212 PyObject *empty_string = PyString_FromString("");
1313 PyObject *empty_tuple = PyTuple_New(0);
1414 PyCodeObject *py_code;
15 PyFrameObject *py_frame;
15 PyFrameObject *py_frame = NULL;
1616
1717 py_code = PyCode_New(
1818 0, /*int argcount,*/
7474 """
7575 int check;
7676 PyObject *type, *value, *tb;
77 PyObject *ret = PyRun_String("XXX", Py_eval_input,
77 PyObject *ret = PyRun_String("XXX", Py_eval_input,
7878 Py_None, Py_None);
7979 if (ret) {
8080 Py_DECREF(ret);
148148 pybuffer = self.import_parser(
149149 '''
150150 Py_buffer buf1, buf2, buf3;
151 PyObject *result;
152151 if (!PyArg_ParseTuple(args, "s*s*s*", &buf1, &buf2, &buf3)) {
153152 return NULL;
154153 }
3838
3939 class AppTestImportLogic(AppTestCpythonExtensionBase):
4040 def test_import_logic(self):
41 skip("leak?")
4241 path = self.import_module(name='test_import_module', load_it=False)
4342 import sys
4443 sys.path.append(path)
6363 assert space.unwrap(w_s) == [2, 1]
6464
6565 class AppTestListObject(AppTestCpythonExtensionBase):
66 def test_listobject(self):
66 def test_basic_listobject(self):
6767 import sys
6868 module = self.import_extension('foo', [
6969 ("newlist", "METH_NOARGS",
103103 Py_RETURN_NONE;
104104 """
105105 ),
106 ('test_tp_as_', "METH_NOARGS",
107 '''
108 PyObject *l = PyList_New(3);
109 int ok = l->ob_type->tp_as_sequence != NULL; /* 1 */
110 ok += 2 * (l->ob_type->tp_as_number == NULL); /* 2 */
111 Py_DECREF(l);
112 return PyLong_FromLong(ok); /* should be 3 */
113 '''
114 ),
106115 ])
107116 l = module.newlist()
108117 assert l == [3, -5, 1000]
135144 l = [1, 2, 3]
136145 module.setlistitem(l,0)
137146 assert l == [None, 2, 3]
147
148 # tp_as_sequence should be filled, but tp_as_number should be NULL
149 assert module.test_tp_as_() == 3
138150
139151 def test_list_macros(self):
140152 """The PyList_* macros cast, and calls expecting that build."""
226226 """)])
227227 assert module.from_str() == 0
228228
229
229 def test_slots(self):
230 module = self.import_extension('foo', [
231 ("has_sub", "METH_NOARGS",
232 """
233 PyObject *ret, *obj = PyLong_FromLong(42);
234 if (obj->ob_type->tp_as_number->nb_subtract)
235 ret = obj->ob_type->tp_as_number->nb_subtract(obj, obj);
236 else
237 ret = PyLong_FromLong(-1);
238 Py_DECREF(obj);
239 return ret;
240 """),
241 ("has_pow", "METH_NOARGS",
242 """
243 PyObject *ret, *obj = PyLong_FromLong(42);
244 PyObject *one = PyLong_FromLong(1);
245 if (obj->ob_type->tp_as_number->nb_power)
246 ret = obj->ob_type->tp_as_number->nb_power(obj, one, one);
247 else
248 ret = PyLong_FromLong(-1);
249 Py_DECREF(obj);
250 return ret;
251 """),
252 ("has_hex", "METH_NOARGS",
253 """
254 PyObject *ret, *obj = PyLong_FromLong(42);
255 if (obj->ob_type->tp_as_number->nb_hex)
256 ret = obj->ob_type->tp_as_number->nb_hex(obj);
257 else
258 ret = PyLong_FromLong(-1);
259 Py_DECREF(obj);
260 return ret;
261 """),
262 ("has_oct", "METH_NOARGS",
263 """
264 PyObject *ret, *obj = PyLong_FromLong(42);
265 if (obj->ob_type->tp_as_number->nb_oct)
266 ret = obj->ob_type->tp_as_number->nb_oct(obj);
267 else
268 ret = PyLong_FromLong(-1);
269 Py_DECREF(obj);
270 return ret;
271 """)])
272 assert module.has_sub() == 0
273 assert module.has_pow() == 0
274 assert module.has_hex() == '0x2aL'
275 assert module.has_oct() == '052L'
276
00 import pytest
11 from pypy.module.cpyext.test.test_api import BaseApiTest
2 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
3
24
35 class TestMemoryViewObject(BaseApiTest):
46 def test_fromobject(self, space, api):
68 space.wrap((2, 7)))):
79 py.test.skip("unsupported before Python 2.7")
810
9 w_hello = space.wrap("hello")
11 w_hello = space.newbytes("hello")
12 assert api.PyObject_CheckBuffer(w_hello)
1013 w_view = api.PyMemoryView_FromObject(w_hello)
14 w_char = space.call_method(w_view, '__getitem__', space.wrap(0))
15 assert space.eq_w(w_char, space.wrap('h'))
1116 w_bytes = space.call_method(w_view, "tobytes")
1217 assert space.unwrap(w_bytes) == "hello"
1318
14 @pytest.mark.skipif(True, reason='write a test for this')
15 def test_get_base_and_get_buffer(self, space, api):
16 assert False # XXX test PyMemoryView_GET_BASE, PyMemoryView_GET_BUFFER
19
20 class AppTestBufferProtocol(AppTestCpythonExtensionBase):
21 def test_buffer_protocol(self):
22 import struct
23 module = self.import_module(name='buffer_test')
24 arr = module.PyMyArray(10)
25 y = memoryview(arr)
26 assert y.format == 'i'
27 assert y.shape == (10,)
28 s = y[3]
29 assert len(s) == struct.calcsize('i')
30 assert s == struct.pack('i', 3)
31
44 from rpython.rtyper.lltypesystem import rffi, lltype
55 from pypy.module.micronumpy.ndarray import W_NDimArray
66 from pypy.module.micronumpy.descriptor import get_dtype_cache
7 import pypy.module.micronumpy.constants as NPY
7 import pypy.module.micronumpy.constants as NPY
88
99 def scalar(space):
1010 dtype = get_dtype_cache(space).w_float64dtype
236236 except:
237237 skip('numpy not importable')
238238 else:
239 numpy_incl = os.path.abspath(os.path.dirname(__file__) +
239 numpy_incl = os.path.abspath(os.path.dirname(__file__) +
240240 '/../include/_numpypy')
241241 assert os.path.exists(numpy_incl)
242242 cls.w_numpy_include = cls.space.wrap([numpy_incl])
272272 {
273273 /* Should have failed */
274274 Py_DECREF(obj1);
275 return NULL;
275 return NULL;
276276 }
277277 return obj1;
278278 '''
299299 ),
300300 ("test_DescrFromType", "METH_O",
301301 """
302 Signed typenum = PyInt_AsLong(args);
302 long typenum = PyInt_AsLong(args);
303303 return PyArray_DescrFromType(typenum);
304304 """
305305 ),
306 ], include_dirs=self.numpy_include,
306 ], include_dirs=self.numpy_include,
307307 prologue='''
308308 #ifdef PYPY_VERSION
309 #include <pypy_numpy.h>
309 #include <pypy_numpy.h>
310310 #endif
311311 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
312312 #include <numpy/arrayobject.h>
314314 #define PyArray_FromObject _PyArray_FromObject
315315 #define PyArray_FromAny _PyArray_FromAny
316316 #endif
317 ''',
317 ''',
318318 more_init = '''
319319 #ifndef PYPY_VERSION
320320 import_array();
348348 Py_INCREF(obj);
349349 return obj;
350350 '''),
351 ], include_dirs=self.numpy_include,
351 ], include_dirs=self.numpy_include,
352352 prologue='''
353353 #ifdef PYPY_VERSION
354 #include <pypy_numpy.h>
354 #include <pypy_numpy.h>
355355 #endif
356356 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
357357 #include <numpy/arrayobject.h>
358 ''',
358 ''',
359359 more_init = '''
360360 #ifndef PYPY_VERSION
361361 import_array();
402402 void *array_data[] = {NULL, NULL};
403403 return PyUFunc_FromFuncAndDataAndSignature(funcs,
404404 array_data, types, 1, 1, 1, PyUFunc_None,
405 "float_3x3",
406 "a ufunc that tests a more complicated signature",
405 "float_3x3",
406 "a ufunc that tests a more complicated signature",
407407 0, "(m,m)->(m,m)");
408408 """),
409 ], include_dirs=self.numpy_include,
409 ], include_dirs=self.numpy_include,
410410 prologue='''
411411 #ifdef PYPY_VERSION
412 #include <pypy_numpy.h>
412 #include <pypy_numpy.h>
413413 #endif
414414 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
415415 #include <numpy/arrayobject.h>
479479 res += +10;
480480 *((float *)args[1]) = res;
481481 };
482
482
483483 ''', more_init = '''
484484 #ifndef PYPY_VERSION
485485 import_array();
1414 assert api.PyNumber_Check(space.wraplong(-12L))
1515 assert api.PyNumber_Check(space.wrap(12.1))
1616 assert not api.PyNumber_Check(space.wrap('12'))
17 assert not api.PyNumber_Check(space.wrap(1+3j))
17 assert api.PyNumber_Check(space.wrap(1+3j))
1818
1919 def test_number_long(self, space, api):
2020 w_l = api.PyNumber_Long(space.wrap(123))
143143 assert tupl[0] == 3.
144144 assert tupl[1] == 1.
145145 assert isinstance(tupl[0], float)'''
146
147 def test_PyNumber_Check(self):
148 mod = self.import_extension('foo', [
149 ("test_PyNumber_Check", "METH_VARARGS",
150 '''
151 PyObject *obj = PyTuple_GET_ITEM(args, 0);
152 int val = PyNumber_Check(obj);
153 return PyInt_FromLong(val);
154 ''')])
155 val = mod.test_PyNumber_Check(10)
156 assert val == 1
126126 test_compare(1, 2)
127127 test_compare(2, 2)
128128 test_compare('2', '1')
129
129
130130 w_i = space.wrap(1)
131131 assert api.PyObject_RichCompareBool(w_i, w_i, 123456) == -1
132132 assert api.PyErr_Occurred() is space.w_SystemError
133133 api.PyErr_Clear()
134
134
135135 def test_IsInstance(self, space, api):
136136 assert api.PyObject_IsInstance(space.wrap(1), space.w_int) == 1
137137 assert api.PyObject_IsInstance(space.wrap(1), space.w_float) == 0
164164 return File""")
165165 w_f = space.call_function(w_File)
166166 assert api.PyObject_AsFileDescriptor(w_f) == 42
167
167
168168 def test_hash(self, space, api):
169169 assert api.PyObject_Hash(space.wrap(72)) == 72
170 assert api.PyObject_Hash(space.wrap(-1)) == -1
170 assert api.PyObject_Hash(space.wrap(-1)) == -2
171171 assert (api.PyObject_Hash(space.wrap([])) == -1 and
172172 api.PyErr_Occurred() is space.w_TypeError)
173173 api.PyErr_Clear()
234234 assert type(x) is int
235235 assert x == -424344
236236
237 @pytest.mark.skipif(True, reason='realloc not fully implemented')
238237 def test_object_realloc(self):
238 if not self.runappdirect:
239 skip('no untranslated support for realloc')
239240 module = self.import_extension('foo', [
240241 ("realloctest", "METH_NOARGS",
241242 """
243244 char *copy, *orig = PyObject_MALLOC(12);
244245 memcpy(orig, "hello world", 12);
245246 copy = PyObject_REALLOC(orig, 15);
247 /* realloc() takes care of freeing orig, if changed */
246248 if (copy == NULL)
247249 Py_RETURN_NONE;
248250 ret = PyString_FromStringAndSize(copy, 12);
249 if (copy != orig)
250 PyObject_Free(copy);
251 PyObject_Free(orig);
252 return ret;
251 PyObject_Free(copy);
252 return ret;
253253 """)])
254254 x = module.realloctest()
255255 assert x == 'hello world\x00'
424424 """
425425 Py_buffer buf;
426426 PyObject *str = PyString_FromString("hello, world.");
427 PyObject *result;
428427
429428 if (PyBuffer_FillInfo(&buf, str, PyString_AsString(str), 13,
430429 1, PyBUF_WRITABLE)) {
0 from pypy.module.cpyext.api import fopen, fclose, fwrite
0 from pypy.conftest import option
11 from pypy.module.cpyext.test.test_api import BaseApiTest
2 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
23 from pypy.module.cpyext.object import Py_PRINT_RAW
34 from rpython.rtyper.lltypesystem import rffi, lltype
45 from rpython.tool.udir import udir
1718 assert api.PyFile_CheckExact(w_file)
1819 assert not api.PyFile_Check(space.wrap("text"))
1920
20 space.call_method(w_file, "write", space.wrap("text"))
21 space.call_method(w_file, "write", space.newbytes("text"))
2122 space.call_method(w_file, "close")
2223 assert (udir / "_test_file").read() == "text"
2324
110111 out, err = capfd.readouterr()
111112 out = out.replace('\r\n', '\n')
112113 assert out == " 1 23\n"
114
115
116 class AppTestPyFile(AppTestCpythonExtensionBase):
117
118 def setup_class(cls):
119 from rpython.tool.udir import udir
120 if option.runappdirect:
121 cls.w_udir = str(udir)
122 else:
123 cls.w_udir = cls.space.wrap(str(udir))
124
125 def test_file_tell(self):
126 module = self.import_extension('foo', [
127 ("get_c_tell", "METH_O",
128 """
129 FILE * fp = PyFile_AsFile(args);
130 if (fp == NULL)
131 return PyLong_FromLong(0);
132 return PyLong_FromLong(ftell(fp));
133 """),
134 ("read_10", "METH_O",
135 """
136 char s[10];
137 FILE * fp = PyFile_AsFile(args);
138 if (fp == NULL)
139 return PyLong_FromLong(0);
140 fread(s, 1, 10, fp);
141 return PyLong_FromLong(ftell(fp));
142 """),
143 ])
144 filename = self.udir + "/_test_file"
145 with open(filename, 'w') as fid:
146 fid.write('3' * 122)
147 with open(filename, 'r') as fid:
148 s = fid.read(80)
149 t_py = fid.tell()
150 assert t_py == 80
151 t_c = module.get_c_tell(fid)
152 assert t_c == t_py
153 print '-------- tell ',t_c
154 t_c = module.read_10(fid)
155 assert t_c == t_py + 10
156 print '-------- tell ',t_c
157 t_py = fid.tell()
158 assert t_c == t_py, 'after a fread, c level ftell(fp) %d but PyFile.tell() %d' % (t_c, t_py)
159
160
6969
7070 def test_get_slice(self, space, api):
7171 w_t = space.wrap([1, 2, 3, 4, 5])
72 assert space.unwrap(api.PySequence_GetSlice(w_t, 2, 4)) == [3, 4]
73 assert space.unwrap(api.PySequence_GetSlice(w_t, 1, -1)) == [2, 3, 4]
74
75 assert api.PySequence_DelSlice(w_t, 1, 4) == 0
76 assert space.eq_w(w_t, space.wrap([1, 5]))
77 assert api.PySequence_SetSlice(w_t, 1, 1, space.wrap((3,))) == 0
78 assert space.eq_w(w_t, space.wrap([1, 3, 5]))
79
80 def test_get_slice_fast(self, space, api):
81 w_t = space.wrap([1, 2, 3, 4, 5])
82 api.PySequence_Fast(w_t, "foo") # converts
7283 assert space.unwrap(api.PySequence_GetSlice(w_t, 2, 4)) == [3, 4]
7384 assert space.unwrap(api.PySequence_GetSlice(w_t, 1, -1)) == [2, 3, 4]
7485
225236 assert space.int_w(space.len(w_l)) == 10
226237
227238
228 class XAppTestSequenceObject(AppTestCpythonExtensionBase):
229 def test_sequenceobject(self):
239 class AppTestSequenceObject(AppTestCpythonExtensionBase):
240 def test_fast(self):
230241 module = self.import_extension('foo', [
231242 ("test_fast_sequence", "METH_VARARGS",
232243 """
233 PyObject * o = PyTuple_GetItem(args, 0);
244 int size, i;
245 PyTypeObject * common_type;
246 PyObject *foo, **objects;
247 PyObject * seq = PyTuple_GetItem(args, 0);
234248 /* XXX assert it is a tuple */
235 PyObject *foo = PySequence_Fast(o, "some string");
236 PyObject ** res = PySequence_Fast_ITEMS(foo);
237 /* XXX do some kind of test on res */
238 /* XXX now what? who manages res's refcount? */
249 if (seq == NULL)
250 Py_RETURN_NONE;
251 foo = PySequence_Fast(seq, "some string");
252 objects = PySequence_Fast_ITEMS(foo);
253 size = PySequence_Fast_GET_SIZE(seq);
254 common_type = size > 0 ? Py_TYPE(objects[0]) : NULL;
255 for (i = 1; i < size; ++i) {
256 if (Py_TYPE(objects[i]) != common_type) {
257 common_type = NULL;
258 break;
259 }
260 }
261 Py_DECREF(foo);
262 Py_DECREF(common_type);
239263 return PyBool_FromLong(1);
240264 """)])
241 assert module.test_fast_sequence([1, 2, 3, 4])
242
265 s = [1, 2, 3, 4]
266 assert module.test_fast_sequence(s[0:-1])
267 assert module.test_fast_sequence(s[::-1])
268
5050 api._PyTuple_Resize(ar, 10)
5151 assert api.PyTuple_Size(ar[0]) == 10
5252 for i in range(3, 10):
53 rffi.cast(PyTupleObject, py_tuple).c_ob_item[i] = make_ref(
53 rffi.cast(PyTupleObject, ar[0]).c_ob_item[i] = make_ref(
5454 space, space.wrap(42 + i))
5555 w_tuple = from_ref(space, ar[0])
5656 assert space.int_w(space.len(w_tuple)) == 10
129129 module = self.import_extension('foo', [
130130 ("run", "METH_NOARGS",
131131 """
132 long prev, next;
132 long prev;
133133 PyObject *t = PyTuple_New(1);
134134 prev = Py_True->ob_refcnt;
135135 Py_INCREF(Py_True);
150150 """),
151151 ])
152152 module.run()
153
154 def test_tuple_subclass(self):
155 module = self.import_module(name='foo')
156 a = module.TupleLike([1, 2, 3])
157 assert module.is_TupleLike(a) == 1
33 from pypy.module.cpyext.test.test_api import BaseApiTest
44 from pypy.module.cpyext.pyobject import make_ref, from_ref
55 from pypy.module.cpyext.typeobject import PyTypeObjectPtr
6
7 import sys
86
97 class AppTestTypeObject(AppTestCpythonExtensionBase):
108 def test_typeobject(self):
283281 args->ob_type->tp_dict, "copy");
284282 Py_INCREF(method);
285283 return method;
286 '''
287 )
284 '''),
285 ("get_type_dict", "METH_O",
286 '''
287 PyObject* value = args->ob_type->tp_dict;
288 if (value == NULL) value = Py_None;
289 Py_INCREF(value);
290 return value;
291 '''),
288292 ])
289293 obj = foo.new()
290294 assert module.read_tp_dict(obj) == foo.fooType.copy
295 d = module.get_type_dict(obj)
296 assert type(d) is dict
297 d["_some_attribute"] = 1
298 assert type(obj)._some_attribute == 1
299 del d["_some_attribute"]
300
301 class A(object):
302 pass
303 obj = A()
304 d = module.get_type_dict(obj)
305 assert type(d) is dict
306 d["_some_attribute"] = 1
307 assert type(obj)._some_attribute == 1
308 del d["_some_attribute"]
309
310 d = module.get_type_dict(1)
311 assert type(d) is dict
312 try:
313 d["_some_attribute"] = 1
314 except TypeError: # on PyPy, int.__dict__ is really immutable
315 pass
316 else:
317 assert int._some_attribute == 1
318 del d["_some_attribute"]
291319
292320 def test_custom_allocation(self):
293321 foo = self.import_module("foo")
355383 assert from_ref(space, py_type.c_tp_mro).wrappeditems is w_class.mro_w
356384
357385 api.Py_DecRef(ref)
386
387 def test_type_dict(self, space, api):
388 w_class = space.appexec([], """():
389 class A(object):
390 pass
391 return A
392 """)
393 ref = make_ref(space, w_class)
394
395 py_type = rffi.cast(PyTypeObjectPtr, ref)
396 w_dict = from_ref(space, py_type.c_tp_dict)
397 w_name = space.wrap('a')
398 space.setitem(w_dict, w_name, space.wrap(1))
399 assert space.int_w(space.getattr(w_class, w_name)) == 1
400 space.delitem(w_dict, w_name)
358401
359402 def test_multiple_inheritance(self, space, api):
360403 w_class = space.appexec([], """():
730773 x = list(it)
731774 assert x == [1]
732775
733 def test_bool(self):
776 def test_intlike(self):
734777 module = self.import_extension('foo', [
735778 ("newInt", "METH_VARARGS",
736779 """
737780 IntLikeObject *intObj;
738781 int intval;
739 PyObject *name;
740782
741783 if (!PyArg_ParseTuple(args, "i", &intval))
742784 return NULL;
743785
744 IntLike_Type.tp_flags |= Py_TPFLAGS_DEFAULT;
745 IntLike_Type.tp_as_number = &intlike_as_number;
746 intlike_as_number.nb_nonzero = intlike_nb_nonzero;
747 if (PyType_Ready(&IntLike_Type) < 0) return NULL;
748786 intObj = PyObject_New(IntLikeObject, &IntLike_Type);
749787 if (!intObj) {
750788 return NULL;
752790
753791 intObj->value = intval;
754792 return (PyObject *)intObj;
755 """)],
756 """
793 """),
794 ("check", "METH_VARARGS", """
795 IntLikeObject *intObj;
796 int intval, isint;
797
798 if (!PyArg_ParseTuple(args, "i", &intval))
799 return NULL;
800 intObj = PyObject_New(IntLikeObject, &IntLike_Type);
801 if (!intObj) {
802 return NULL;
803 }
804 intObj->value = intval;
805 isint = PyNumber_Check((PyObject*)intObj);
806 Py_DECREF((PyObject*)intObj);
807 return PyInt_FromLong(isint);
808 """),
809 ], prologue= """
757810 typedef struct
758811 {
759812 PyObject_HEAD
772825 return v->value;
773826 }
774827
828 static PyObject*
829 intlike_nb_int(PyObject* o)
830 {
831 IntLikeObject *v = (IntLikeObject*)o;
832 return PyInt_FromLong(v->value);
833 }
834
775835 PyTypeObject IntLike_Type = {
776836 PyObject_HEAD_INIT(0)
777837 /*ob_size*/ 0,
779839 /*tp_basicsize*/ sizeof(IntLikeObject),
780840 };
781841 static PyNumberMethods intlike_as_number;
842 """, more_init="""
843 IntLike_Type.tp_flags |= Py_TPFLAGS_DEFAULT;
844 IntLike_Type.tp_as_number = &intlike_as_number;
845 intlike_as_number.nb_nonzero = intlike_nb_nonzero;
846 intlike_as_number.nb_int = intlike_nb_int;
847 PyType_Ready(&IntLike_Type);
782848 """)
783849 assert not bool(module.newInt(0))
784850 assert bool(module.newInt(1))
785851 raises(SystemError, bool, module.newInt(-1))
786852 raises(ValueError, bool, module.newInt(-42))
853 val = module.check(10);
854 assert val == 1
787855
788856 def test_mathfunc(self):
789857 module = self.import_extension('foo', [
896964 module.footype("X", (object,), {})
897965
898966 def test_app_subclass_of_c_type(self):
899 # on cpython, the size changes (6 bytes added)
967 import sys
900968 module = self.import_module(name='foo')
901969 size = module.size_of_instances(module.fooType)
902970 class f1(object):
906974 class bar(f1, f2):
907975 pass
908976 assert bar.__base__ is f2
909 assert module.size_of_instances(bar) == size
977 # On cpython, the size changes.
978 if '__pypy__' in sys.builtin_module_names:
979 assert module.size_of_instances(bar) == size
980 else:
981 assert module.size_of_instances(bar) >= size
910982
911983 def test_app_cant_subclass_two_types(self):
912984 module = self.import_module(name='foo')
10571129 module = self.import_extension('foo', [
10581130 ("getMetaClass", "METH_NOARGS",
10591131 '''
1060 PyObject *obj;
10611132 FooType_Type.tp_flags = Py_TPFLAGS_DEFAULT;
10621133 FooType_Type.tp_base = &PyType_Type;
10631134 if (PyType_Ready(&FooType_Type) < 0) return NULL;
3434 ("test_GetSize_exception", "METH_NOARGS",
3535 """
3636 PyObject* f = PyFloat_FromDouble(1.0);
37 Py_ssize_t size = PyUnicode_GetSize(f);
37 PyUnicode_GetSize(f);
3838
3939 Py_DECREF(f);
4040 return NULL;
5656 """
5757 PyObject *s, *t;
5858 Py_UNICODE* c;
59 Py_ssize_t len;
6059
6160 s = PyUnicode_FromUnicode(NULL, 4);
6261 if (s == NULL)
8382 '''
8483 PyObject* obj = (PyTuple_GetItem(args, 0));
8584 long hash = ((PyUnicodeObject*)obj)->hash;
86 return PyLong_FromLong(hash);
85 return PyLong_FromLong(hash);
8786 '''
8887 ),
8988 ])
233232 w_res = api.PyUnicode_AsUTF8String(w_u)
234233 assert space.type(w_res) is space.w_str
235234 assert space.unwrap(w_res) == 'sp\tm'
236
235
237236 def test_decode_utf8(self, space, api):
238237 u = rffi.str2charp(u'sp\x134m'.encode("utf-8"))
239238 w_u = api.PyUnicode_DecodeUTF8(u, 5, None)
240239 assert space.type(w_u) is space.w_unicode
241240 assert space.unwrap(w_u) == u'sp\x134m'
242
241
243242 w_u = api.PyUnicode_DecodeUTF8(u, 2, None)
244243 assert space.type(w_u) is space.w_unicode
245244 assert space.unwrap(w_u) == 'sp'
404403 ustr = "abcdef"
405404 w_ustr = space.wrap(ustr.decode("ascii"))
406405 result = api.PyUnicode_AsASCIIString(w_ustr)
407
406
408407 assert space.eq_w(space.wrap(ustr), result)
409408
410409 w_ustr = space.wrap(u"abcd\xe9f")
11 from rpython.rtyper.lltypesystem import rffi, lltype
22 from rpython.rlib.debug import fatalerror_notb
33 from pypy.module.cpyext.api import (cpython_api, Py_ssize_t, CANNOT_FAIL,
4 build_type_checkers, PyObjectFields,
4 build_type_checkers, PyVarObjectFields,
55 cpython_struct, bootstrap_function)
66 from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, Py_DecRef,
7 make_ref, from_ref, decref,
7 make_ref, from_ref, decref, incref, pyobj_has_w_obj,
88 track_reference, make_typedescr, get_typedescr)
99 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
1010 from pypy.objspace.std.tupleobject import W_TupleObject
2828 PyTupleObjectStruct = lltype.ForwardReference()
2929 PyTupleObject = lltype.Ptr(PyTupleObjectStruct)
3030 ObjectItems = rffi.CArray(PyObject)
31 PyTupleObjectFields = PyObjectFields + \
32 (("ob_size", Py_ssize_t), ("ob_item", lltype.Ptr(ObjectItems)))
31 PyTupleObjectFields = PyVarObjectFields + \
32 (("ob_item", ObjectItems),)
3333 cpython_struct("PyTupleObject", PyTupleObjectFields, PyTupleObjectStruct)
3434
3535 @bootstrap_function
5555 tuple_realize() is called. Refcount of the result is 1.
5656 """
5757 typedescr = get_typedescr(space.w_tuple.layout.typedef)
58 py_obj = typedescr.allocate(space, space.w_tuple)
59 py_tup = rffi.cast(PyTupleObject, py_obj)
60
61 py_tup.c_ob_item = lltype.malloc(ObjectItems, length,
62 flavor='raw', zero=True,
63 add_memory_pressure=True)
64 py_tup.c_ob_size = length
65 return py_tup
58 py_obj = typedescr.allocate(space, space.w_tuple, length)
59 py_tup = rffi.cast(PyTupleObject, py_obj)
60 p = py_tup.c_ob_item
61 for i in range(py_tup.c_ob_size):
62 p[i] = lltype.nullptr(PyObject.TO)
63 return py_obj
6664
6765 def tuple_attach(space, py_obj, w_obj):
6866 """
7068 buffer must not be modified.
7169 """
7270 items_w = space.fixedview(w_obj)
73 l = len(items_w)
74 p = lltype.malloc(ObjectItems, l, flavor='raw',
75 add_memory_pressure=True)
71 py_tup = rffi.cast(PyTupleObject, py_obj)
72 length = len(items_w)
73 if py_tup.c_ob_size < length:
74 raise oefmt(space.w_ValueError,
75 "tuple_attach called on object with ob_size %d but trying to store %d",
76 py_tup.c_ob_size, length)
7677 i = 0
7778 try:
78 while i < l:
79 p[i] = make_ref(space, items_w[i])
79 while i < length:
80 py_tup.c_ob_item[i] = make_ref(space, items_w[i])
8081 i += 1
8182 except:
8283 while i > 0:
8384 i -= 1
84 decref(space, p[i])
85 lltype.free(p, flavor='raw')
85 ob = py_tup.c_ob_item[i]
86 py_tup.c_ob_item[i] = lltype.nullptr(PyObject.TO)
87 decref(space, ob)
8688 raise
87 py_tup = rffi.cast(PyTupleObject, py_obj)
88 py_tup.c_ob_size = l
89 py_tup.c_ob_item = p
9089
9190 def tuple_realize(space, py_obj):
9291 """
107106 "converting a PyTupleObject into a W_TupleObject, "
108107 "but found NULLs as items")
109108 items_w[i] = w_item
110 w_obj = space.newtuple(items_w)
109 w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type))
110 w_obj = space.allocate_instance(W_TupleObject, w_type)
111 w_obj.__init__(items_w)
111112 track_reference(space, py_obj, w_obj)
112113 return w_obj
113114
117118 """
118119 py_tup = rffi.cast(PyTupleObject, py_obj)
119120 p = py_tup.c_ob_item
120 if p:
121 for i in range(py_tup.c_ob_size):
122 decref(space, p[i])
123 lltype.free(p, flavor="raw")
124 from pypy.module.cpyext.object import PyObject_dealloc
125 PyObject_dealloc(space, py_obj)
121 for i in range(py_tup.c_ob_size):
122 decref(space, p[i])
123 from pypy.module.cpyext.object import _dealloc
124 _dealloc(space, py_obj)
126125
127126 #_______________________________________________________________________
128127
129128 @cpython_api([Py_ssize_t], PyObject, result_is_ll=True)
130129 def PyTuple_New(space, size):
131 return rffi.cast(PyObject, new_empty_tuple(space, size))
130 return new_empty_tuple(space, size)
132131
133132 @cpython_api([PyObject, Py_ssize_t, PyObject], rffi.INT_real, error=-1)
134133 def PyTuple_SetItem(space, ref, index, py_obj):
141140 ref = rffi.cast(PyTupleObject, ref)
142141 size = ref.c_ob_size
143142 if index < 0 or index >= size:
143 decref(space, py_obj)
144144 raise oefmt(space.w_IndexError, "tuple assignment index out of range")
145145 old_ref = ref.c_ob_item[index]
146146 ref.c_ob_item[index] = py_obj # consumes a reference
183183 ref = p_ref[0]
184184 if not tuple_check_ref(space, ref):
185185 PyErr_BadInternalCall(space)
186 ref = rffi.cast(PyTupleObject, ref)
187 oldsize = ref.c_ob_size
188 oldp = ref.c_ob_item
189 newp = lltype.malloc(ObjectItems, newsize, zero=True, flavor='raw',
190 add_memory_pressure=True)
186 oldref = rffi.cast(PyTupleObject, ref)
187 oldsize = oldref.c_ob_size
188 p_ref[0] = new_empty_tuple(space, newsize)
189 newref = rffi.cast(PyTupleObject, p_ref[0])
191190 try:
192191 if oldsize < newsize:
193192 to_cp = oldsize
194193 else:
195194 to_cp = newsize
196195 for i in range(to_cp):
197 newp[i] = oldp[i]
196 ob = oldref.c_ob_item[i]
197 incref(space, ob)
198 newref.c_ob_item[i] = ob
198199 except:
199 lltype.free(newp, flavor='raw')
200 decref(space, p_ref[0])
201 p_ref[0] = lltype.nullptr(PyObject.TO)
200202 raise
201 ref.c_ob_item = newp
202 ref.c_ob_size = newsize
203 lltype.free(oldp, flavor='raw')
204 # in this version, p_ref[0] never needs to be updated
203 finally:
204 decref(space, ref)
205205 return 0
206206
207207 @cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
1616 generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING,
1717 Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
1818 Py_TPFLAGS_HAVE_GETCHARBUFFER, build_type_checkers, StaticObjectBuilder,
19 PyObjectFields, Py_TPFLAGS_BASETYPE)
19 PyObjectFields, Py_TPFLAGS_BASETYPE, PyTypeObject, PyTypeObjectPtr,
20 Py_TPFLAGS_HAVE_NEWBUFFER, Py_TPFLAGS_CHECKTYPES,
21 Py_TPFLAGS_HAVE_INPLACEOPS)
2022 from pypy.module.cpyext.methodobject import (W_PyCClassMethodObject,
21 PyDescr_NewWrapper, PyCFunction_NewEx, PyCFunction_typedef, PyMethodDef,
23 W_PyCWrapperObject, PyCFunction_NewEx, PyCFunction_typedef, PyMethodDef,
2224 W_PyCMethodObject, W_PyCFunctionObject)
2325 from pypy.module.cpyext.modsupport import convert_method_defs
2426 from pypy.module.cpyext.pyobject import (
2931 from pypy.module.cpyext.state import State
3032 from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
3133 from pypy.module.cpyext.typeobjectdefs import (
32 PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc,
34 PyGetSetDef, PyMemberDef, newfunc,
3335 PyNumberMethods, PyMappingMethods, PySequenceMethods, PyBufferProcs)
3436 from pypy.objspace.std.typeobject import W_TypeObject, find_best_base
3537
166168 py_memberdescr.c_d_member = w_obj.member
167169
168170 def memberdescr_realize(space, obj):
169 # XXX NOT TESTED When is this ever called?
171 # XXX NOT TESTED When is this ever called?
170172 member = rffi.cast(lltype.Ptr(PyMemberDef), obj)
171173 w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
172174 w_obj = space.allocate_instance(W_MemberDescr, w_type)
191193 py_methoddescr.c_d_method = w_obj.ml
192194
193195 def classmethoddescr_realize(space, obj):
194 # XXX NOT TESTED When is this ever called?
196 # XXX NOT TESTED When is this ever called?
195197 method = rffi.cast(lltype.Ptr(PyMethodDef), obj)
196198 w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
197199 w_obj = space.allocate_instance(W_PyCClassMethodObject, w_type)
200202 return w_obj
201203
202204 def methoddescr_realize(space, obj):
203 # XXX NOT TESTED When is this ever called?
205 # XXX NOT TESTED When is this ever called?
204206 method = rffi.cast(lltype.Ptr(PyMethodDef), obj)
205207 w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
206208 w_obj = space.allocate_instance(W_PyCMethodObject, w_type)
237239 i += 1
238240
239241 def update_all_slots(space, w_type, pto):
240 # XXX fill slots in pto
242 # fill slots in pto
241243 # Not very sure about it, but according to
242244 # test_call_tp_dealloc_when_created_from_python, we should not
243245 # overwrite slots that are already set: these ones are probably
271273 if len(slot_names) == 1:
272274 if not getattr(pto, slot_names[0]):
273275 setattr(pto, slot_names[0], slot_func_helper)
276 elif (w_type.getname(space) in ('list', 'tuple') and
277 slot_names[0] == 'c_tp_as_number'):
278 # XXX hack - hwo can we generalize this? The problem is method
279 # names like __mul__ map to more than one slot, and we have no
280 # convenient way to indicate which slots CPython have filled
281 #
282 # We need at least this special case since Numpy checks that
283 # (list, tuple) do __not__ fill tp_as_number
284 pass
274285 else:
275286 assert len(slot_names) == 2
276287 struct = getattr(pto, slot_names[0])
295306 for method_name, slot_names, wrapper_func, wrapper_func_kwds, doc in slotdefs_for_wrappers:
296307 if method_name in dict_w:
297308 continue
309 offset = [rffi.offsetof(lltype.typeOf(pto).TO, slot_names[0])]
298310 if len(slot_names) == 1:
299311 func = getattr(pto, slot_names[0])
300312 else:
302314 struct = getattr(pto, slot_names[0])
303315 if not struct:
304316 continue
317 offset.append(rffi.offsetof(lltype.typeOf(struct).TO, slot_names[1]))
305318 func = getattr(struct, slot_names[1])
306319 func_voidp = rffi.cast(rffi.VOIDP, func)
307320 if not func:
308321 continue
309322 if wrapper_func is None and wrapper_func_kwds is None:
310323 continue
311 dict_w[method_name] = PyDescr_NewWrapper(space, pto, method_name, wrapper_func,
312 wrapper_func_kwds, doc, func_voidp)
324 w_obj = W_PyCWrapperObject(space, pto, method_name, wrapper_func,
325 wrapper_func_kwds, doc, func_voidp, offset=offset)
326 dict_w[method_name] = space.wrap(w_obj)
313327 if pto.c_tp_new:
314328 add_tp_new_wrapper(space, dict_w, pto)
315329
370384 # (minimally, if tp_basicsize is zero we copy it from the base)
371385 if not pto.c_tp_basicsize:
372386 pto.c_tp_basicsize = base_pto.c_tp_basicsize
387 if pto.c_tp_itemsize < base_pto.c_tp_itemsize:
388 pto.c_tp_itemsize = base_pto.c_tp_itemsize
389 pto.c_tp_flags |= base_pto.c_tp_flags & Py_TPFLAGS_CHECKTYPES
390 pto.c_tp_flags |= base_pto.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
373391 flags = rffi.cast(lltype.Signed, pto.c_tp_flags)
374392 base_object_pyo = make_ref(space, space.w_object)
375393 base_object_pto = rffi.cast(PyTypeObjectPtr, base_object_pyo)
563581 if space.is_w(w_type, space.w_str):
564582 # Special case: str doesn't support get_raw_address(), so we have a
565583 # custom get*buffer that instead gives the address of the char* in the
566 # PyStringObject*!
584 # PyBytesObject*!
567585 c_buf.c_bf_getreadbuffer = llhelper(
568586 str_getreadbuffer.api_func.functype,
569587 str_getreadbuffer.api_func.get_wrapper(space))
593611 bf_getwritebuffer.api_func.get_wrapper(space))
594612 pto.c_tp_as_buffer = c_buf
595613 pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
614 pto.c_tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER
596615
597616 @cpython_api([PyObject], lltype.Void, header=None)
598617 def type_dealloc(space, obj):
599 from pypy.module.cpyext.object import PyObject_dealloc
618 from pypy.module.cpyext.object import _dealloc
600619 obj_pto = rffi.cast(PyTypeObjectPtr, obj)
601620 base_pyo = rffi.cast(PyObject, obj_pto.c_tp_base)
602621 Py_DecRef(space, obj_pto.c_tp_bases)
607626 heaptype = rffi.cast(PyHeapTypeObject, obj)
608627 Py_DecRef(space, heaptype.c_ht_name)
609628 Py_DecRef(space, base_pyo)
610 PyObject_dealloc(space, obj)
629 _dealloc(space, obj)
611630
612631
613632 def type_alloc(space, w_metatype, itemsize=0):
656675 pto.c_tp_dealloc = llhelper(
657676 subtype_dealloc.api_func.functype,
658677 subtype_dealloc.api_func.get_wrapper(space))
678 if space.is_w(w_type, space.w_str):
679 pto.c_tp_itemsize = 1
680 elif space.is_w(w_type, space.w_tuple):
681 pto.c_tp_itemsize = rffi.sizeof(PyObject)
659682 # buffer protocol
660683 setup_buffer_procs(space, w_type, pto)
661684
694717 if pto.c_tp_base:
695718 if pto.c_tp_base.c_tp_basicsize > pto.c_tp_basicsize:
696719 pto.c_tp_basicsize = pto.c_tp_base.c_tp_basicsize
720 if pto.c_tp_itemsize < pto.c_tp_base.c_tp_itemsize:
721 pto.c_tp_itemsize = pto.c_tp_base.c_tp_itemsize
697722
698723 # will be filled later on with the correct value
699724 # may not be 0
721746 try:
722747 w_obj = _type_realize(space, py_obj)
723748 finally:
749 name = rffi.charp2str(pto.c_tp_name)
724750 pto.c_tp_flags &= ~Py_TPFLAGS_READYING
725751 pto.c_tp_flags |= Py_TPFLAGS_READY
726752 return w_obj
752778 pto.c_tp_setattro = base.c_tp_setattro
753779 if not pto.c_tp_getattro:
754780 pto.c_tp_getattro = base.c_tp_getattro
781 if not pto.c_tp_as_buffer:
782 pto.c_tp_as_buffer = base.c_tp_as_buffer
755783 finally:
756784 Py_DecRef(space, base_pyo)
757785
773801
774802 if py_type.c_ob_type:
775803 w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type))
776 else:
804 else:
777805 # Somehow the tp_base type is created with no ob_type, notably
778806 # PyString_Type and PyBaseString_Type
779807 # While this is a hack, cpython does it as well.
788816 # inheriting tp_as_* slots
789817 base = py_type.c_tp_base
790818 if base:
791 if not py_type.c_tp_as_number: py_type.c_tp_as_number = base.c_tp_as_number
792 if not py_type.c_tp_as_sequence: py_type.c_tp_as_sequence = base.c_tp_as_sequence
793 if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = base.c_tp_as_mapping
794 if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer
819 if not py_type.c_tp_as_number:
820 py_type.c_tp_as_number = base.c_tp_as_number
821 py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_CHECKTYPES
822 py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
823 if not py_type.c_tp_as_sequence:
824 py_type.c_tp_as_sequence = base.c_tp_as_sequence
825 py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS
826 if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = base.c_tp_as_mapping
827 if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer
795828
796829 return w_obj
797830
802835 base = pto.c_tp_base
803836 base_pyo = rffi.cast(PyObject, pto.c_tp_base)
804837 if base and not base.c_tp_flags & Py_TPFLAGS_READY:
805 type_realize(space, rffi.cast(PyObject, base_pyo))
838 name = rffi.charp2str(base.c_tp_name)
839 type_realize(space, base_pyo)
806840 if base and not pto.c_ob_type: # will be filled later
807841 pto.c_ob_type = base.c_ob_type
808842 if not pto.c_tp_bases:
837871
838872 if w_obj.is_cpytype():
839873 Py_DecRef(space, pto.c_tp_dict)
840 w_dict = w_obj.getdict(space)
841 pto.c_tp_dict = make_ref(space, w_dict)
874 w_dict = w_obj.getdict(space)
875 pto.c_tp_dict = make_ref(space, w_dict)
842876
843877 @cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL)
844878 def PyType_IsSubtype(space, a, b):
44 Py_TPFLAGS_READYING, Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE)
55 from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
66 from pypy.module.cpyext.modsupport import PyMethodDef
7 from pypy.module.cpyext.api import Py_bufferP
78
89
910 P, FT, PyO = Ptr, FuncType, PyObject
5758 writebufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
5859 segcountproc = P(FT([PyO, Py_ssize_tP], Py_ssize_t))
5960 charbufferproc = P(FT([PyO, Py_ssize_t, rffi.CCHARPP], Py_ssize_t))
60 ## We don't support new buffer interface for now
61 getbufferproc = rffi.VOIDP
61 getbufferproc = P(FT([PyO, Py_bufferP, rffi.INT_real], rffi.INT_real))
6262 releasebufferproc = rffi.VOIDP
6363
6464
7676 """
7777 py_uni = rffi.cast(PyUnicodeObject, py_obj)
7878 s = rffi.wcharpsize2unicode(py_uni.c_str, py_uni.c_length)
79 w_obj = space.wrap(s)
79 w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type))
80 w_obj = space.allocate_instance(unicodeobject.W_UnicodeObject, w_type)
81 w_obj.__init__(s)
8082 py_uni.c_hash = space.hash_w(w_obj)
8183 track_reference(space, py_obj, w_obj)
8284 return w_obj
8789 Py_DecRef(space, py_unicode.c_defenc)
8890 if py_unicode.c_str:
8991 lltype.free(py_unicode.c_str, flavor="raw")
90 from pypy.module.cpyext.object import PyObject_dealloc
91 PyObject_dealloc(space, py_obj)
92
93 from pypy.module.cpyext.object import _dealloc
94 _dealloc(space, py_obj)
9295
9396 @cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL)
9497 def Py_UNICODE_ISSPACE(space, ch):
368371 if not encoding:
369372 # This tracks CPython 2.7, in CPython 3.4 'utf-8' is hardcoded instead
370373 encoding = PyUnicode_GetDefaultEncoding(space)
374 w_str = space.newbytes(rffi.charpsize2str(s, size))
371375 w_encoding = space.wrap(rffi.charp2str(encoding))
372 w_str = space.wrap(rffi.charpsize2str(s, size))
373376 if errors:
374 w_errors = space.wrap(rffi.charp2str(errors))
377 w_errors = space.newbytes(rffi.charp2str(errors))
375378 else:
376379 w_errors = None
377380 return space.call_method(w_str, 'decode', w_encoding, w_errors)
423426 @cpython_api([CONST_STRING], PyObject)
424427 def PyUnicode_FromString(space, s):
425428 """Create a Unicode object from an UTF-8 encoded null-terminated char buffer"""
426 w_str = space.wrap(rffi.charp2str(s))
429 w_str = space.newbytes(rffi.charp2str(s))
427430 return space.call_method(w_str, 'decode', space.wrap("utf-8"))
428431
429432 @cpython_api([CONST_STRING, Py_ssize_t], PyObject, result_is_ll=True)
491494 encoded string s. Return NULL if an exception was raised by
492495 the codec.
493496 """
494 w_s = space.wrap(rffi.charpsize2str(s, size))
497 w_s = space.newbytes(rffi.charpsize2str(s, size))
495498 if errors:
496499 w_errors = space.wrap(rffi.charp2str(errors))
497500 else:
834834 data before the other iterator, it is faster to use list() instead
835835 of tee()
836836
837 Equivalent to :
837 If iter(iterable) has no method __copy__(), this is equivalent to:
838838
839839 def tee(iterable, n=2):
840840 def gen(next, data={}, cnt=[0]):
847847 yield item
848848 it = iter(iterable)
849849 return tuple([gen(it.next) for i in range(n)])
850
851 If iter(iterable) has a __copy__ method, though, we just return
852 a tuple t = (iterable, t[0].__copy__(), t[1].__copy__(), ...).
850853 """
851854 if n < 0:
852855 raise oefmt(space.w_ValueError, "n must be >= 0")
853856
854 if isinstance(w_iterable, W_TeeIterable): # optimization only
855 chained_list = w_iterable.chained_list
856 w_iterator = w_iterable.w_iterator
857 if space.findattr(w_iterable, space.wrap("__copy__")) is not None:
858 # In this case, we don't instantiate any W_TeeIterable.
859 # We just rely on doing repeated __copy__(). This case
860 # includes the situation where w_iterable is already
861 # a W_TeeIterable itself.
857862 iterators_w = [w_iterable] * n
858863 for i in range(1, n):
859 iterators_w[i] = space.wrap(W_TeeIterable(space, w_iterator,
860 chained_list))
864 w_iterable = space.call_method(w_iterable, "__copy__")
865 iterators_w[i] = w_iterable
861866 else:
862867 w_iterator = space.iter(w_iterable)
863868 chained_list = TeeChainedListNode()
889894 chained_list.w_obj = w_obj
890895 self.chained_list = chained_list.next
891896 return w_obj
897
898 def copy_w(self):
899 space = self.space
900 tee_iter = W_TeeIterable(space, self.w_iterator, self.chained_list)
901 return space.wrap(tee_iter)
892902
893903 def W_TeeIterable___new__(space, w_subtype, w_iterable):
894904 # Obscure and undocumented function. PyPy only supports w_iterable
905915 __new__ = interp2app(W_TeeIterable___new__),
906916 __iter__ = interp2app(W_TeeIterable.iter_w),
907917 next = interp2app(W_TeeIterable.next_w),
918 __copy__ = interp2app(W_TeeIterable.copy_w),
908919 __weakref__ = make_weakref_descr(W_TeeIterable),
909920 )
910921 W_TeeIterable.typedef.acceptable_as_base_class = False
700700 assert x == 'b'
701701 x = d.next()
702702 assert x == 'b'
703
704 def test_tee_defines_copy(self):
705 import itertools
706 a, b = itertools.tee('abc')
707 c = b.__copy__()
708 assert list(a) == ['a', 'b', 'c']
709 assert list(b) == ['a', 'b', 'c']
710 assert list(c) == ['a', 'b', 'c']
711 a, = itertools.tee('abc', 1)
712 x = a.next()
713 assert x == 'a'
714 b = a.__copy__()
715 x = a.next()
716 assert x == 'b'
717 x = b.next()
718 assert x == 'b'
719
720 def test_tee_function_uses_copy(self):
721 import itertools
722 class MyIterator(object):
723 def __iter__(self):
724 return self
725 def next(self):
726 raise NotImplementedError
727 def __copy__(self):
728 return iter('def')
729 my = MyIterator()
730 a, = itertools.tee(my, 1)
731 assert a is my
732 a, b = itertools.tee(my)
733 assert a is my
734 assert b is not my
735 assert list(b) == ['d', 'e', 'f']
736 # this gives AttributeError because it tries to call
737 # my.__copy__().__copy__() and there isn't one
738 raises(AttributeError, itertools.tee, my, 3)
739
740 def test_tee_function_empty(self):
741 import itertools
742 assert itertools.tee('abc', 0) == ()
743 a, = itertools.tee('abc', 1)
744 assert itertools.tee(a, 0) == ()
703745
704746
705747 class AppTestItertools26:
1818 UserDelAction)
1919 from pypy.interpreter.pyframe import PyFrame
2020
21
2221 class BogusBytecode(Exception):
2322 pass
2423
382381 # XXX even the hacks have hacks
383382 if s == 'size': # used in _array() but never called by tests
384383 return IntObject(0)
384 if s == '__buffer__':
385 # descr___buffer__ does not exist on W_Root
386 return self.w_None
385387 return getattr(w_obj, 'descr_' + s)(self, *args)
386388
387389 @specialize.arg(1)
703703 def get_raw_address(self):
704704 from rpython.rtyper.lltypesystem import rffi
705705 return rffi.ptradd(self.impl.storage, self.impl.start)
706
707 def getformat(self):
708 return self.impl.dtype.char
709
710 def getitemsize(self):
711 return self.impl.dtype.elsize
712
713 def getndim(self):
714 return len(self.impl.shape)
715
716 def getshape(self):
717 return self.impl.shape
718
719 def getstrides(self):
720 return self.impl.strides
721
722
467467 except OperationError as e:
468468 if not e.match(space, space.w_TypeError):
469469 raise
470 w_buffer = space.getattr(w_buffer, space.wrap('__buffer__'))
470 w_buffer = space.call_method(w_buffer, '__buffer__',
471 space.newint(space.BUF_FULL_RO))
471472 buf = _getbuffer(space, w_buffer)
472473
473474 ts = buf.getlength()
253253 idx = space.str_w(w_idx)
254254 return self.getfield(space, idx)
255255 if space.is_w(w_idx, space.w_Ellipsis):
256 return self
256 return self.descr_view(space, space.type(self))
257257 elif isinstance(w_idx, W_NDimArray) and w_idx.get_dtype().is_bool():
258258 if w_idx.ndims() > 0:
259259 w_ret = self.getitem_filter(space, w_idx)
26132613 import numpy as np
26142614 import sys
26152615 a = np.array(1.5)
2616 if '__pypy__' in sys.builtin_module_names:
2617 assert a[...] is a
2618 else:
2619 assert a[...].base is a
2616 assert a[...].base is a
26202617 a[...] = 2.5
26212618 assert a == 2.5
26222619 a = np.array([1, 2, 3])
2623 if '__pypy__' in sys.builtin_module_names:
2624 assert a[...] is a
2625 else:
2626 assert a[...].base is a
2620 assert a[...].base is a
26272621 a[...] = 4
26282622 assert (a == [4, 4, 4]).all()
26292623 assert a[..., 0] == 4
36313625 assert str(exc.value) == "assignment destination is read-only"
36323626
36333627 class A(object):
3634 __buffer__ = 'abc'
3628 def __buffer__(self, flags):
3629 return 'abc'
36353630
36363631 data = A()
36373632 a = np.frombuffer(data, 'c')
36383633 #assert a.base is data.__buffer__
36393634 assert a.tostring() == 'abc'
3635
3636 def test_memoryview(self):
3637 import numpy as np
3638 import sys
3639 if sys.version_info[:2] > (3, 2):
3640 # In Python 3.3 the representation of empty shape, strides and sub-offsets
3641 # is an empty tuple instead of None.
3642 # http://docs.python.org/dev/whatsnew/3.3.html#api-changes
3643 EMPTY = ()
3644 else:
3645 EMPTY = None
3646 x = np.array([1, 2, 3, 4, 5], dtype='i')
3647 y = memoryview('abc')
3648 assert y.format == 'B'
3649 y = memoryview(x)
3650 assert y.format == 'i'
3651 assert y.shape == (5,)
3652 assert y.ndim == 1
3653 assert y.strides == (4,)
3654 assert y.suboffsets == EMPTY
3655 assert y.itemsize == 4
36403656
36413657 def test_fromstring(self):
36423658 import sys
33 from rpython.rlib import rposix, rposix_stat
44 from rpython.rlib import objectmodel, rurandom
55 from rpython.rlib.objectmodel import specialize
6 from rpython.rlib.rarithmetic import r_longlong, intmask
6 from rpython.rlib.rarithmetic import r_longlong, intmask, r_uint
77 from rpython.rlib.unroll import unrolling_iterable
88
99 from pypy.interpreter.gateway import unwrap_spec
1919
2020 c_int = "c_int"
2121
22 # CPython 2.7 semantics are too messy to follow exactly,
23 # e.g. setuid(-2) works on 32-bit but not on 64-bit. As a result,
24 # we decided to just accept any 'int', i.e. any C signed long, and
25 # check that they are in range(-2**31, 2**32). In other words, we
26 # accept any number that is either a signed or an unsigned C int.
27 c_uid_t = int
28 c_gid_t = int
29 if sys.maxint == 2147483647:
30 def check_uid_range(space, num):
31 pass
32 else:
33 def check_uid_range(space, num):
34 if num < -(1 << 31) or num >= (1 << 32):
35 raise oefmt(space.w_OverflowError, "integer out of range")
22 # CPython 2.7 semantics used to be too messy, differing on 32-bit vs
23 # 64-bit, but this was cleaned up in recent 2.7.x. Now, any function
24 # taking a uid_t or gid_t accepts numbers in range(-1, 2**32) as an
25 # r_uint, with -1 being equivalent to 2**32-1. Any function that
26 # returns a uid_t or gid_t returns either an int or a long, depending
27 # on whether it fits or not, but always positive.
28 c_uid_t = 'c_uid_t'
29 c_gid_t = 'c_uid_t'
30
31 def wrap_uid(space, uid):
32 if uid <= r_uint(sys.maxint):
33 return space.wrap(intmask(uid))
34 else:
35 return space.wrap(uid) # an unsigned number
36 wrap_gid = wrap_uid
3637
3738 def fsencode_w(space, w_obj):
3839 if space.isinstance_w(w_obj, space.w_unicode):
543544 raise oefmt(space.w_ValueError,
544545 "the environment variable is longer than %d bytes",
545546 _MAX_ENV)
547 if _WIN32 and not objectmodel.we_are_translated() and value == '':
548 # special case: on Windows, _putenv("NAME=") really means that
549 # we want to delete NAME. So that's what the os.environ[name]=''
550 # below will do after translation. But before translation, it
551 # will cache the environment value '' instead of <missing> and
552 # then return that. We need to avoid that.
553 del os.environ[name]
554 return
546555 try:
547556 os.environ[name] = value
548557 except OSError as e:
580589 "decode", w_fs_encoding)
581590 except OperationError as e:
582591 # fall back to the original byte string
592 if e.async(space):
593 raise
583594 result_w[i] = w_bytes
584595 return space.newlist(result_w)
585596 else:
903914
904915 Return the current process's user id.
905916 """
906 return space.wrap(os.getuid())
917 return wrap_uid(space, os.getuid())
907918
908919 @unwrap_spec(arg=c_uid_t)
909920 def setuid(space, arg):
911922
912923 Set the current process's user id.
913924 """
914 check_uid_range(space, arg)
915925 try:
916926 os.setuid(arg)
917927 except OSError as e:
918928 raise wrap_oserror(space, e)
919 return space.w_None
920929
921930 @unwrap_spec(arg=c_uid_t)
922931 def seteuid(space, arg):
924933
925934 Set the current process's effective user id.
926935 """
927 check_uid_range(space, arg)
928936 try:
929937 os.seteuid(arg)
930938 except OSError as e:
931939 raise wrap_oserror(space, e)
932 return space.w_None
933940
934941 @unwrap_spec(arg=c_gid_t)
935942 def setgid(space, arg):
937944
938945 Set the current process's group id.
939946 """
940 check_uid_range(space, arg)
941947 try:
942948 os.setgid(arg)
943949 except OSError as e:
944950 raise wrap_oserror(space, e)
945 return space.w_None
946951
947952 @unwrap_spec(arg=c_gid_t)
948953 def setegid(space, arg):
950955
951956 Set the current process's effective group id.
952957 """
953 check_uid_range(space, arg)
954958 try:
955959 os.setegid(arg)
956960 except OSError as e:
957961 raise wrap_oserror(space, e)
958 return space.w_None
959962
960963 @unwrap_spec(path='str0')
961964 def chroot(space, path):
974977
975978 Return the current process's group id.
976979 """
977 return space.wrap(os.getgid())
980 return wrap_gid(space, os.getgid())
978981
979982 def getegid(space):
980983 """ getegid() -> gid
981984
982985 Return the current process's effective group id.
983986 """
984 return space.wrap(os.getegid())
987 return wrap_gid(space, os.getegid())
985988
986989 def geteuid(space):
987990 """ geteuid() -> euid
988991
989992 Return the current process's effective user id.
990993 """
991 return space.wrap(os.geteuid())
994 return wrap_uid(space, os.geteuid())
992995
993996 def getgroups(space):
994997 """ getgroups() -> list of group IDs
9991002 list = os.getgroups()
10001003 except OSError as e:
10011004 raise wrap_oserror(space, e)
1002 return space.newlist([space.wrap(e) for e in list])
1005 return space.newlist([wrap_gid(space, e) for e in list])
10031006
10041007 def setgroups(space, w_list):
10051008 """ setgroups(list)
10081011 """
10091012 list = []
10101013 for w_gid in space.unpackiterable(w_list):
1011 gid = space.int_w(w_gid)
1012 check_uid_range(space, gid)
1013 list.append(gid)
1014 list.append(space.c_uid_t_w(w_gid))
10141015 try:
10151016 os.setgroups(list[:])
10161017 except OSError as e:
10841085
10851086 Set the current process's real and effective user ids.
10861087 """
1087 check_uid_range(space, ruid)
1088 check_uid_range(space, euid)
10891088 try:
10901089 os.setreuid(ruid, euid)
10911090 except OSError as e:
10921091 raise wrap_oserror(space, e)
1093 return space.w_None
10941092
10951093 @unwrap_spec(rgid=c_gid_t, egid=c_gid_t)
10961094 def setregid(space, rgid, egid):
10981096
10991097 Set the current process's real and effective group ids.
11001098 """
1101 check_uid_range(space, rgid)
1102 check_uid_range(space, egid)
11031099 try:
11041100 os.setregid(rgid, egid)
11051101 except OSError as e:
11061102 raise wrap_oserror(space, e)
1107 return space.w_None
11081103
11091104 @unwrap_spec(pid=c_int)
11101105 def getsid(space, pid):
11411136 raise wrap_oserror(space, e)
11421137 return space.wrap(pgid)
11431138
1144 @unwrap_spec(fd=c_int, pgid=c_gid_t)
1139 @unwrap_spec(fd=c_int, pgid=c_int)
11451140 def tcsetpgrp(space, fd, pgid):
11461141 """ tcsetpgrp(fd, pgid)
11471142
11611156 (ruid, euid, suid) = os.getresuid()
11621157 except OSError as e:
11631158 raise wrap_oserror(space, e)
1164 return space.newtuple([space.wrap(ruid),
1165 space.wrap(euid),
1166 space.wrap(suid)])
1159 return space.newtuple([wrap_uid(space, ruid),
1160 wrap_uid(space, euid),
1161 wrap_uid(space, suid)])
11671162
11681163 def getresgid(space):
11691164 """ getresgid() -> (rgid, egid, sgid)
11741169 (rgid, egid, sgid) = os.getresgid()
11751170 except OSError as e:
11761171 raise wrap_oserror(space, e)
1177 return space.newtuple([space.wrap(rgid),
1178 space.wrap(egid),
1179 space.wrap(sgid)])
1172 return space.newtuple([wrap_gid(space, rgid),
1173 wrap_gid(space, egid),
1174 wrap_gid(space, sgid)])
11801175
11811176 @unwrap_spec(ruid=c_uid_t, euid=c_uid_t, suid=c_uid_t)
11821177 def setresuid(space, ruid, euid, suid):
12751270 @unwrap_spec(path='str0', uid=c_uid_t, gid=c_gid_t)
12761271 def chown(space, path, uid, gid):
12771272 """Change the owner and group id of path to the numeric uid and gid."""
1278 check_uid_range(space, uid)
1279 check_uid_range(space, gid)
12801273 try:
12811274 os.chown(path, uid, gid)
12821275 except OSError as e:
12861279 def lchown(space, path, uid, gid):
12871280 """Change the owner and group id of path to the numeric uid and gid.
12881281 This function will not follow symbolic links."""
1289 check_uid_range(space, uid)
1290 check_uid_range(space, gid)
12911282 try:
12921283 os.lchown(path, uid, gid)
12931284 except OSError as e:
12981289 """Change the owner and group id of the file given by file descriptor
12991290 fd to the numeric uid and gid."""
13001291 fd = space.c_filedescriptor_w(w_fd)
1301 check_uid_range(space, uid)
1302 check_uid_range(space, gid)
13031292 try:
13041293 os.fchown(fd, uid, gid)
13051294 except OSError as e:
1212 import sys
1313 import signal
1414
15 USEMODULES = ['binascii', 'posix', 'struct', 'time']
16 if os.name != 'nt':
17 USEMODULES += ['fcntl']
18 else:
19 # On windows, os.popen uses the subprocess module
20 USEMODULES += ['_rawffi', 'thread', 'signal']
21
1522 def setup_module(mod):
16 usemodules = ['binascii', 'posix', 'struct', 'time']
17 if os.name != 'nt':
18 usemodules += ['fcntl']
19 else:
20 # On windows, os.popen uses the subprocess module
21 usemodules += ['_rawffi', 'thread', 'signal']
22 mod.space = gettestobjspace(usemodules=usemodules)
23 mod.space = gettestobjspace(usemodules=USEMODULES)
2324 mod.path = udir.join('posixtestfile.txt')
2425 mod.path.write("this is a test")
2526 mod.path2 = udir.join('test_posix2-')
4849
4950
5051 class AppTestPosix:
52 spaceconfig = {'usemodules': USEMODULES}
5153
5254 def setup_class(cls):
53 cls.space = space
55 space = cls.space
5456 cls.w_runappdirect = space.wrap(cls.runappdirect)
5557 cls.w_posix = space.appexec([], GET_POSIX)
5658 cls.w_path = space.wrap(str(path))
616618 assert os.geteuid() == self.geteuid
617619
618620 if hasattr(os, 'setuid'):
621 @py.test.mark.skipif("sys.version_info < (2, 7, 4)")
619622 def test_os_setuid_error(self):
620623 os = self.posix
621 raises(OverflowError, os.setuid, -2**31-1)
624 raises(OverflowError, os.setuid, -2)
622625 raises(OverflowError, os.setuid, 2**32)
626 raises(OSError, os.setuid, -1)
623627
624628 if hasattr(os, 'getgid'):
625629 def test_os_getgid(self):
662666 raises(OSError, os.getpgid, 1234567)
663667
664668 if hasattr(os, 'setgid'):
669 @py.test.mark.skipif("sys.version_info < (2, 7, 4)")
665670 def test_os_setgid_error(self):
666671 os = self.posix
667 raises(OverflowError, os.setgid, -2**31-1)
672 raises(OverflowError, os.setgid, -2)
668673 raises(OverflowError, os.setgid, 2**32)
674 raises(OSError, os.setgid, -1)
675 raises(OSError, os.setgid, -1L)
676 raises(OSError, os.setgid, 2**32-1)
669677
670678 if hasattr(os, 'getsid'):
671679 def test_os_getsid(self):
11441152
11451153 class AppTestEnvironment(object):
11461154 def setup_class(cls):
1147 cls.space = space
1148 cls.w_posix = space.appexec([], "(): import %s as m ; return m" % os.name)
1149 cls.w_os = space.appexec([], "(): import os; return os")
11501155 cls.w_path = space.wrap(str(path))
11511156
11521157 def test_environ(self):
1153 posix = self.posix
1154 os = self.os
1158 import posix
11551159 assert posix.environ['PATH']
11561160 del posix.environ['PATH']
11571161 def fn(): posix.environ['PATH']
11591163
11601164 if hasattr(__import__(os.name), "unsetenv"):
11611165 def test_unsetenv_nonexisting(self):
1162 os = self.os
1166 import os
11631167 os.unsetenv("XYZABC") #does not raise
11641168 try:
11651169 os.environ["ABCABC"]
11771181
11781182 class AppTestPosixUnicode:
11791183 def setup_class(cls):
1180 cls.space = space
1181 cls.w_posix = space.appexec([], GET_POSIX)
11821184 if cls.runappdirect:
11831185 # Can't change encoding
11841186 try:
11861188 except UnicodeEncodeError:
11871189 py.test.skip("encoding not good enough")
11881190 else:
1189 cls.save_fs_encoding = space.sys.filesystemencoding
1190 space.sys.filesystemencoding = "utf-8"
1191 cls.save_fs_encoding = cls.space.sys.filesystemencoding
1192 cls.space.sys.filesystemencoding = "utf-8"
11911193
11921194 def teardown_class(cls):
11931195 try:
11971199
11981200 def test_stat_unicode(self):
11991201 # test that passing unicode would not raise UnicodeDecodeError
1200 try:
1201 self.posix.stat(u"ą")
1202 import posix
1203 try:
1204 posix.stat(u"ą")
12021205 except OSError:
12031206 pass
12041207
12051208 def test_open_unicode(self):
12061209 # Ensure passing unicode doesn't raise UnicodeEncodeError
1207 try:
1208 self.posix.open(u"ą", self.posix.O_WRONLY)
1210 import posix
1211 try:
1212 posix.open(u"ą", posix.O_WRONLY)
12091213 except OSError:
12101214 pass
12111215
12121216 def test_remove_unicode(self):
12131217 # See 2 above ;)
1214 try:
1215 self.posix.remove(u"ą")
1218 import posix
1219 try:
1220 posix.remove(u"ą")
12161221 except OSError:
12171222 pass
12181223
55 from rpython.rlib.rarithmetic import r_uint, intmask
66 from rpython.rlib.jit import JitDriver, hint, we_are_jitted, dont_look_inside
77 from rpython.rlib import jit, jit_hooks
8 from rpython.rlib.rjitlog import rjitlog as jl
89 from rpython.rlib.jit import current_trace_length, unroll_parameters,\
910 JitHookInterface
1011 from rpython.rtyper.annlowlevel import cast_instance_to_gcref
4041 from rpython.rlib import rvmprof
4142 return rvmprof.get_unique_id(bytecode)
4243
44 @jl.returns(jl.MP_FILENAME, jl.MP_LINENO,
45 jl.MP_SCOPE, jl.MP_INDEX, jl.MP_OPCODE)
46 def get_location(next_instr, is_being_profiled, bytecode):
47 from pypy.tool.stdlib_opcode import opcode_method_names
48 from rpython.tool.error import offset2lineno
49 bcindex = ord(bytecode.co_code[next_instr])
50 opname = ""
51 if 0 <= bcindex < len(opcode_method_names):
52 opname = opcode_method_names[bcindex]
53 name = bytecode.co_name
54 if not name:
55 name = ""
56 line = offset2lineno(bytecode, intmask(next_instr))
57 return (bytecode.co_filename, line,
58 name, intmask(next_instr), opname)
4359
4460 def should_unroll_one_iteration(next_instr, is_being_profiled, bytecode):
4561 return (bytecode.co_flags & CO_GENERATOR) != 0
5066 virtualizables = ['frame']
5167
5268 pypyjitdriver = PyPyJitDriver(get_printable_location = get_printable_location,
69 get_location = get_location,
5370 get_unique_id = get_unique_id,
5471 should_unroll_one_iteration =
5572 should_unroll_one_iteration,
5656 cmdline.append(str(self.filepath))
5757 #
5858 env = os.environ.copy()
59 # TODO old logging system
5960 env['PYPYLOG'] = self.log_string + ':' + str(logfile)
61 jitlogfile = str(logfile) + '.jlog'
62 env['JITLOG'] = str(jitlogfile)
6063 pipe = subprocess.Popen(cmdline,
6164 env=env,
6265 stdout=subprocess.PIPE,
8386 log = Log(rawtraces)
8487 log.result = eval(stdout)
8588 log.logfile = str(logfile)
89 log.jitlogfile = jitlogfile
8690 #
8791 summaries = logparser.extract_category(rawlog, 'jit-summary')
8892 if len(summaries) > 0:
422422 guard_false(i114, descr=...)
423423 --TICK--
424424 i123 = arraylen_gc(p67, descr=<ArrayP .>)
425 i119 = call_i(ConstClass(_ll_1_raw_malloc_varsize__Signed), 6, descr=<Calli . i EF=5 OS=110>)
425 i119 = call_i(ConstClass(_ll_1_raw_malloc_varsize_zero__Signed), 6, descr=<Calli . i EF=5 OS=110>)
426 check_memory_error(i119)
426427 raw_store(i119, 0, i160, descr=<ArrayS 2>)
427428 raw_store(i119, 2, i160, descr=<ArrayS 2>)
428429 raw_store(i119, 4, i160, descr=<ArrayS 2>)
66 from rpython.tool.jitlogparser.parser import (import_log, parse_log_counts,
77 mangle_descr)
88 from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
9
109
1110 class TestLogParser(BaseTestPyPyC):
1211 log_string = 'jit-log-opt,jit-backend'
162162 guard_not_invalidated(descr=...)
163163 i32 = float_ne(f31, 0.000000)
164164 guard_true(i32, descr=...)
165 i34 = getarrayitem_raw_i(#, #, descr=<ArrayU 1>) # XXX what are these?
166 guard_value(i34, #, descr=...) # XXX don't appear in
167 i35 = getarrayitem_raw_i(#, #, descr=<ArrayU 1>) # XXX equiv test_zjit
168165 i36 = int_add(i24, 1)
169166 i37 = int_add(i29, 8)
170167 i38 = int_ge(i36, i30)
171168 guard_false(i38, descr=...)
172 guard_value(i35, #, descr=...) # XXX
173169 jump(..., descr=...)
174170 """)
175171
2222 guard_true(i14, descr=...)
2323 guard_not_invalidated(descr=...)
2424 i16 = int_eq(i6, %d)
25 i19 = call_i(ConstClass(ll_int_mod__Signed_Signed), i6, i10, descr=<Calli . ii EF=0 OS=14>)
25 i19 = call_i(ConstClass(ll_int_py_mod__Signed_Signed), i6, i10, descr=<Calli . ii EF=0 OS=14>)
2626 i21 = int_lt(i19, 0)
2727 guard_false(i21, descr=...)
2828 i22 = int_ge(i19, i10)
1818 def setup_method(self, meth):
1919 self.w_sockets = self.space.wrap([])
2020 if platform.machine().startswith('arm'):
21 self.w_timeout = self.space.wrap(0.06)
22 if platform.machine().startswith('s390x'):
23 # s390x is not slow, but it seems there is one case when epoll
24 # modify method is called that takes longer on s390x
2125 self.w_timeout = self.space.wrap(0.06)
2226 else:
2327 self.w_timeout = self.space.wrap(0.02)
00 from pypy.interpreter.mixedmodule import MixedModule
11 from pypy.interpreter.error import OperationError
22 from rpython.rlib.objectmodel import we_are_translated
3 from rpython.rlib import rdynload
34 import sys
45
56 _WIN = sys.platform == 'win32'
1819 self.defaultencoding = "ascii"
1920 self.filesystemencoding = None
2021 self.debug = True
22 self.track_resources = False
23 self.dlopenflags = rdynload._dlopen_default_mode()
2124
2225 interpleveldefs = {
2326 '__name__' : '(space.wrap("sys"))',
5255 '_current_frames' : 'currentframes._current_frames',
5356 'setrecursionlimit' : 'vm.setrecursionlimit',
5457 'getrecursionlimit' : 'vm.getrecursionlimit',
58 'pypy_set_track_resources' : 'vm.set_track_resources',
59 'pypy_get_track_resources' : 'vm.get_track_resources',
5560 'setcheckinterval' : 'vm.setcheckinterval',
5661 'getcheckinterval' : 'vm.getcheckinterval',
5762 'exc_info' : 'vm.exc_info',
8489
8590 'float_info' : 'system.get_float_info(space)',
8691 'long_info' : 'system.get_long_info(space)',
87 'float_repr_style' : 'system.get_float_repr_style(space)'
92 'float_repr_style' : 'system.get_float_repr_style(space)',
93 'getdlopenflags' : 'system.getdlopenflags',
94 'setdlopenflags' : 'system.setdlopenflags',
8895 }
8996
9097 if sys.platform == 'win32':
5757
5858 def get_float_repr_style(space):
5959 return space.wrap("short")
60
61 def getdlopenflags(space):
62 return space.wrap(space.sys.dlopenflags)
63
64 def setdlopenflags(space, w_flags):
65 space.sys.dlopenflags = space.int_w(w_flags)
444444
445445 def test_dlopenflags(self):
446446 import sys
447 if hasattr(sys, "setdlopenflags"):
448 assert hasattr(sys, "getdlopenflags")
449 raises(TypeError, sys.getdlopenflags, 42)
450 oldflags = sys.getdlopenflags()
451 raises(TypeError, sys.setdlopenflags)
452 sys.setdlopenflags(oldflags+1)
453 assert sys.getdlopenflags() == oldflags+1
454 sys.setdlopenflags(oldflags)
447 raises(TypeError, sys.getdlopenflags, 42)
448 oldflags = sys.getdlopenflags()
449 raises(TypeError, sys.setdlopenflags)
450 sys.setdlopenflags(oldflags+1)
451 assert sys.getdlopenflags() == oldflags+1
452 sys.setdlopenflags(oldflags)
455453
456454 def test_refcount(self):
457455 import sys
609607 class AppTestSysSettracePortedFromCpython(object):
610608 def test_sys_settrace(self):
611609 import sys
612
610
613611 class Tracer:
614612 def __init__(self):
615613 self.events = []
99 #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
1010 CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h
1111
12 PYPY_VERSION = (5, 3, 1, "final", 0) #XXX # sync patchlevel.h
12 PYPY_VERSION = (5, 4, 0, "final", 0) #XXX # sync patchlevel.h
1313
1414
1515 import pypy
5959 """Return the last value set by setrecursionlimit().
6060 """
6161 return space.wrap(space.sys.recursionlimit)
62
63 @unwrap_spec(flag=bool)
64 def set_track_resources(space, flag):
65 space.sys.track_resources = flag
66
67 def get_track_resources(space):
68 return space.wrap(space.sys.track_resources)
6269
6370 @unwrap_spec(interval=int)
6471 def setcheckinterval(space, interval):
129129 cls.module = str(udir.join('testownlib.dll'))
130130 else:
131131 subprocess.check_call(
132 'gcc testownlib.c -shared -fPIC -o testownlib.so',
132 'cc testownlib.c -shared -fPIC -o testownlib.so',
133133 cwd=str(udir), shell=True)
134134 cls.module = str(udir.join('testownlib.so'))
135135
851851 assert str(e2.value) == "foo0() takes no arguments (2 given)"
852852 assert str(e3.value) == "foo1() takes exactly one argument (0 given)"
853853 assert str(e4.value) == "foo1() takes exactly one argument (2 given)"
854 assert str(e5.value) == "foo2() takes exactly 2 arguments (0 given)"
855 assert str(e6.value) == "foo2() takes exactly 2 arguments (1 given)"
856 assert str(e7.value) == "foo2() takes exactly 2 arguments (3 given)"
854 assert str(e5.value) in ["foo2 expected 2 arguments, got 0",
855 "foo2() takes exactly 2 arguments (0 given)"]
856 assert str(e6.value) in ["foo2 expected 2 arguments, got 1",
857 "foo2() takes exactly 2 arguments (1 given)"]
858 assert str(e7.value) in ["foo2 expected 2 arguments, got 3",
859 "foo2() takes exactly 2 arguments (3 given)"]
857860
858861 def test_address_of_function():
859862 ffi = FFI()
19151918 ffi.cdef("bool f(void);")
19161919 lib = verify(ffi, "test_bool_in_cpp", "char f(void) { return 2; }")
19171920 assert lib.f() == 1
1921
1922 def test_bool_in_cpp_2():
1923 ffi = FFI()
1924 ffi.cdef('int add(int a, int b);')
1925 lib = verify(ffi, "test_bool_bug_cpp", '''
1926 typedef bool _Bool; /* there is a Windows header with this line */
1927 int add(int a, int b)
1928 {
1929 return a + b;
1930 }''', source_extension='.cpp')
1931 c = lib.add(2, 3)
1932 assert c == 5
1933
1934 def test_struct_field_opaque():
1935 ffi = FFI()
1936 ffi.cdef("struct a { struct b b; };")
1937 e = py.test.raises(TypeError, verify,
1938 ffi, "test_struct_field_opaque", "?")
1939 assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
1940 " type (not declared in cdef())")
1941 ffi = FFI()
1942 ffi.cdef("struct a { struct b b[2]; };")
1943 e = py.test.raises(TypeError, verify,
1944 ffi, "test_struct_field_opaque", "?")
1945 assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
1946 " type (not declared in cdef())")
1947 ffi = FFI()
1948 ffi.cdef("struct a { struct b b[]; };")
1949 e = py.test.raises(TypeError, verify,
1950 ffi, "test_struct_field_opaque", "?")
1951 assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
1952 " type (not declared in cdef())")
1953
1954 def test_function_arg_opaque():
1955 py.test.skip("can currently declare a function with an opaque struct "
1956 "as argument, but AFAICT it's impossible to call it later")
1957
1958 def test_function_returns_opaque():
1959 ffi = FFI()
1960 ffi.cdef("struct a foo(int);")
1961 e = py.test.raises(TypeError, verify,
1962 ffi, "test_function_returns_opaque", "?")
1963 assert str(e.value) == ("function foo: 'struct a' is used as result type,"
1964 " but is opaque")
1965
1966 def test_function_returns_union():
1967 ffi = FFI()
1968 ffi.cdef("union u1 { int a, b; }; union u1 f1(int);")
1969 lib = verify(ffi, "test_function_returns_union", """
1970 union u1 { int a, b; };
1971 static union u1 f1(int x) { union u1 u; u.b = x; return u; }
1972 """)
1973 assert lib.f1(51).a == 51
1974
1975 def test_function_returns_partial_struct():
1976 ffi = FFI()
1977 ffi.cdef("struct a { int a; ...; }; struct a f1(int);")
1978 lib = verify(ffi, "test_function_returns_partial_struct", """
1979 struct a { int b, a, c; };
1980 static struct a f1(int x) { struct a s = {0}; s.a = x; return s; }
1981 """)
1982 assert lib.f1(52).a == 52
132132 # You cannot assing character format codes as restype any longer
133133 raises(TypeError, setattr, f, "restype", "i")
134134
135 def test_unicode_function_name(self):
136 f = dll[u'_testfunc_i_bhilfd']
137 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
138 f.restype = c_int
139 result = f(1, 2, 3, 4, 5.0, 6.0)
140 assert result == 21
135141
136142 def test_truncate_python_longs(self):
137143 f = dll._testfunc_i_bhilfd
264264 class A(object):
265265 _byref = byref
266266 A._byref(c_int(5))
267
268 def test_byref_with_offset(self):
269 c = c_int()
270 d = byref(c)
271 base = cast(d, c_void_p).value
272 for i in [0, 1, 4, 1444, -10293]:
273 assert cast(byref(c, i), c_void_p).value == base + i
314314 class sub(datetime.timedelta): pass
315315 assert type(+sub()) is datetime.timedelta
316316
317 def test_subclass_date(self):
318 # replace() should return a subclass but not call __new__ or __init__.
319 class MyDate(datetime.date):
320 forbidden = False
321 def __new__(cls):
322 if cls.forbidden: FAIL
323 return datetime.date.__new__(cls, 2016, 2, 3)
324 def __init__(self, *args):
325 if self.forbidden: FAIL
326 d = MyDate()
327 d.forbidden = True
328 d2 = d.replace(day=5)
329 assert type(d2) is MyDate
330 assert d2 == datetime.date(2016, 2, 5)
331
332 def test_subclass_time(self):
333 # replace() should return a subclass but not call __new__ or __init__.
334 class MyTime(datetime.time):
335 forbidden = False
336 def __new__(cls):
337 if cls.forbidden: FAIL
338 return datetime.time.__new__(cls, 1, 2, 3)
339 def __init__(self, *args):
340 if self.forbidden: FAIL
341 d = MyTime()
342 d.forbidden = True
343 d2 = d.replace(hour=5)
344 assert type(d2) is MyTime
345 assert d2 == datetime.time(5, 2, 3)
346
347 def test_subclass_datetime(self):
348 # replace() should return a subclass but not call __new__ or __init__.
349 class MyDatetime(datetime.datetime):
350 forbidden = False
351 def __new__(cls):
352 if cls.forbidden: FAIL
353 return datetime.datetime.__new__(cls, 2016, 4, 5, 1, 2, 3)
354 def __init__(self, *args):
355 if self.forbidden: FAIL
356 d = MyDatetime()
357 d.forbidden = True
358 d2 = d.replace(hour=7)
359 assert type(d2) is MyDatetime
360 assert d2 == datetime.datetime(2016, 4, 5, 7, 2, 3)
361
317362
318363 class TestDatetimeHost(BaseTestDatetime):
319364 def setup_class(cls):
1414 assert len(g) == 2
1515 del g['abc']
1616 assert len(g) == 1
17
18 def test_unicode():
19 path = unicode(udir.join('test_gdm_unicode'))
20 g = gdbm.open(path, 'c') # does not crash
00 from __future__ import absolute_import
1 import sys
12
23 import os
34 if os.name != 'posix':
4445
4546 def test_setrlimit():
4647 # minimal "does not crash" test
47 x = resource.getrlimit(resource.RLIMIT_CPU)
48 resource.setrlimit(resource.RLIMIT_CPU, x)
48 x, y = resource.getrlimit(resource.RLIMIT_CPU)
49 resource.setrlimit(resource.RLIMIT_CPU, (x, y))
50 # sometimes, x and y are very large (more than 53 bits).
51 # for these huge values, int(float(x)) > x...
52 xf = x + (0.2 if x >= 0 else -0.2)
53 yf = y + (0.3 if y >= 0 else -0.3)
54 if int(xf) == x and int(yf) == y:
55 resource.setrlimit(resource.RLIMIT_CPU, (x, y)) # truncated to ints
88 from pypy.interpreter.gateway import interp2app, unwrap_spec
99 from pypy.interpreter.typedef import TypeDef
1010 from pypy.interpreter.error import oefmt
11 from rpython.rlib.rarithmetic import r_longlong
11 from rpython.rlib.rarithmetic import r_longlong, ovfcheck_float_to_longlong
1212
13
14 LONGLONG_MAX = r_longlong(2 ** (r_longlong.BITS-1) - 1)
15 TIMEOUT_MAX = LONGLONG_MAX
1613
1714 RPY_LOCK_FAILURE, RPY_LOCK_ACQUIRED, RPY_LOCK_INTR = range(3)
1815
2926 microseconds = -1
3027 else:
3128 timeout *= 1e6
32 if timeout > float(TIMEOUT_MAX):
29 try:
30 microseconds = ovfcheck_float_to_longlong(timeout)
31 except OverflowError:
3332 raise oefmt(space.w_OverflowError, "timeout value is too large")
34 microseconds = r_longlong(timeout)
3533 return microseconds
3634
3735
4442 # Run signal handlers if we were interrupted
4543 space.getexecutioncontext().checksignals()
4644 if microseconds >= 0:
47 microseconds = r_longlong(endtime - (time.time() * 1e6))
45 microseconds = r_longlong((endtime - (time.time() * 1e6))
46 + 0.999)
4847 # Check for negative values, since those mean block
4948 # forever
5049 if microseconds <= 0:
6262 lock._py3k_acquire(True, .01)
6363 else:
6464 assert self.runappdirect, "missing lock._py3k_acquire()"
65
66 def test_py3k_acquire_timeout_overflow(self):
67 import thread
68 lock = thread.allocate_lock()
69 if not hasattr(lock, '_py3k_acquire'):
70 skip("missing lock._py3k_acquire()")
71 maxint = 2**63 - 1
72 boundary = int(maxint * 1e-6)
73 for i in [-100000, -10000, -1000, -100, -10, -1, 0,
74 1, 10, 100, 1000, 10000, 100000]:
75 timeout = (maxint + i) * 1e-6
76 try:
77 lock._py3k_acquire(True, timeout=timeout)
78 except OverflowError:
79 got_ovf = True
80 else:
81 got_ovf = False
82 lock.release()
83 assert (i, got_ovf) == (i, int(timeout * 1e6) > maxint)
6584
6685 @py.test.mark.xfail(machine()=='s390x', reason='may fail under heavy load')
6786 def test_ping_pong(self):
408408 if not e.match(space, space.w_StopIteration):
409409 raise
410410 return space.w_False
411 if space.eq_w(w_next, w_item):
411 if space.eq_w(w_item, w_next):
412412 return space.w_True
413413
414414 def hash(space, w_obj):
423423 raise oefmt(space.w_TypeError,
424424 "'%T' objects are unhashable", w_obj)
425425 w_result = space.get_and_call_function(w_hash, w_obj)
426 w_resulttype = space.type(w_result)
427 if space.is_w(w_resulttype, space.w_int):
428 return w_result
429 elif space.is_w(w_resulttype, space.w_long):
430 return space.hash(w_result)
431 elif space.isinstance_w(w_result, space.w_int):
432 # be careful about subclasses of 'int'...
433 return space.wrap(space.int_w(w_result))
426
427 # issue 2346 : returns now -2 for hashing -1 like cpython
428 if space.isinstance_w(w_result, space.w_int):
429 h = space.int_w(w_result)
434430 elif space.isinstance_w(w_result, space.w_long):
435 # be careful about subclasses of 'long'...
436431 bigint = space.bigint_w(w_result)
437 return space.wrap(bigint.hash())
432 h = bigint.hash()
438433 else:
439434 raise oefmt(space.w_TypeError,
440435 "__hash__() should return an int or long")
436 # turn -1 into -2 without using a condition, which would
437 # create a potential bridge in the JIT
438 h -= (h == -1)
439 return space.wrap(h)
441440
442441 def cmp(space, w_v, w_w):
443442
507506 @specialize.arg_or_var(2)
508507 def isinstance(space, w_inst, w_type):
509508 return space.wrap(space.isinstance_w(w_inst, w_type))
510
511 def issubtype_allow_override(space, w_sub, w_type):
512 w_check = space.lookup(w_type, "__subclasscheck__")
513 if w_check is None:
514 raise oefmt(space.w_TypeError, "issubclass not supported here")
515 return space.get_and_call_function(w_check, w_type, w_sub)
516
517 def isinstance_allow_override(space, w_inst, w_type):
518 if space.type(w_inst) is w_type:
519 return space.w_True # fast path copied from cpython
520 w_check = space.lookup(w_type, "__instancecheck__")
521 if w_check is not None:
522 return space.get_and_call_function(w_check, w_type, w_inst)
523 else:
524 return space.isinstance(w_inst, w_type)
525509
526510
527511 # helpers
4343
4444 def str_w(self, space):
4545 return NonConstant("foobar")
46 identifier_w = bytes_w = str_w
4647
4748 def unicode_w(self, space):
4849 return NonConstant(u"foobar")
194195 "NOT_RPYTHON"
195196 raise NotImplementedError
196197
197 def wrapbytes(self, x):
198 def newbytes(self, x):
199 return w_some_obj()
200
201 def newunicode(self, x):
198202 return w_some_obj()
199203
200204 def wrap(self, x):
416420 class FakeModule(W_Root):
417421 def __init__(self):
418422 self.w_dict = w_some_obj()
419
420423 def get(self, name):
421424 name + "xx" # check that it's a string
422425 return w_some_obj()
423426 FakeObjSpace.sys = FakeModule()
424427 FakeObjSpace.sys.filesystemencoding = 'foobar'
425428 FakeObjSpace.sys.defaultencoding = 'ascii'
429 FakeObjSpace.sys.dlopenflags = 123
430 FakeObjSpace.sys.track_resources = False
426431 FakeObjSpace.builtin = FakeModule()
1717 from pypy.objspace.std.unicodeobject import (
1818 decode_object, unicode_from_encoded_object,
1919 unicode_from_string, getdefaultencoding)
20 from pypy.objspace.std.util import IDTAG_SPECIAL, IDTAG_SHIFT
2021
2122
2223 class W_AbstractBytesObject(W_Root):
2930 return True
3031 if self.user_overridden_class or w_other.user_overridden_class:
3132 return False
32 return space.str_w(self) is space.str_w(w_other)
33 s1 = space.str_w(self)
34 s2 = space.str_w(w_other)
35 if len(s2) > 1:
36 return s1 is s2
37 else: # strings of len <= 1 are unique-ified
38 return s1 == s2
3339
3440 def immutable_unique_id(self, space):
3541 if self.user_overridden_class:
3642 return None
37 return space.wrap(compute_unique_id(space.str_w(self)))
43 s = space.str_w(self)
44 if len(s) > 1:
45 uid = compute_unique_id(s)
46 else: # strings of len <= 1 are unique-ified
47 if len(s) == 1:
48 base = ord(s[0]) # base values 0-255
49 else:
50 base = 256 # empty string: base value 256
51 uid = (base << IDTAG_SHIFT) | IDTAG_SPECIAL
52 return space.wrap(uid)
3853
3954 def unicode_w(self, space):
4055 # Use the default encoding.
418433 of the specified width. The string S is never truncated.
419434 """
420435
421
422436 class W_BytesObject(W_AbstractBytesObject):
423437 import_from_mixin(StringMethods)
424438 _immutable_fields_ = ['_value']
447461 def writebuf_w(self, space):
448462 raise oefmt(space.w_TypeError,
449463 "Cannot use string as modifiable buffer")
464
465 def descr_getbuffer(self, space, w_flags):
466 #from pypy.objspace.std.bufferobject import W_Buffer
467 #return W_Buffer(StringBuffer(self._value))
468 return self
450469
451470 charbuf_w = str_w
452471
563582 def descr_str(self, space):
564583 if type(self) is W_BytesObject:
565584 return self
566 return wrapstr(space, self._value)
585 return W_BytesObject(self._value)
567586
568587 def descr_hash(self, space):
569588 x = compute_hash(self._value)
709728 l = space.listview_bytes(w_list)
710729 if l is not None:
711730 if len(l) == 1:
712 return space.wrap(l[0])
713 return space.wrap(self._val(space).join(l))
731 return space.newbytes(l[0])
732 return space.newbytes(self._val(space).join(l))
714733 return self._StringMethods_descr_join(space, w_list)
715734
716735 _StringMethods_descr_split = descr_split
840859 return [s for s in value]
841860
842861 W_BytesObject.EMPTY = W_BytesObject('')
843
844
845 def wrapstr(space, s):
846 return W_BytesObject(s)
847862
848863
849864 W_BytesObject.typedef = TypeDef(
913928 translate = interpindirect2app(W_AbstractBytesObject.descr_translate),
914929 upper = interpindirect2app(W_AbstractBytesObject.descr_upper),
915930 zfill = interpindirect2app(W_AbstractBytesObject.descr_zfill),
931 __buffer__ = interp2app(W_BytesObject.descr_getbuffer),
916932
917933 format = interpindirect2app(W_BytesObject.descr_format),
918934 __format__ = interpindirect2app(W_BytesObject.descr__format__),
0 from rpython.rlib import rerased
1 from rpython.rlib.objectmodel import iteritems_with_hash
2
3 from pypy.interpreter.error import OperationError, oefmt
4 from pypy.objspace.std.dictmultiobject import (
5 DictStrategy, create_iterator_classes)
6 from pypy.objspace.std.typeobject import unwrap_cell
7
8
9 class ClassDictStrategy(DictStrategy):
10 erase, unerase = rerased.new_erasing_pair("dictproxy")
11 erase = staticmethod(erase)
12 unerase = staticmethod(unerase)
13
14 def __init__(self, space):
15 DictStrategy.__init__(self, space)
16
17 def getitem(self, w_dict, w_key):
18 space = self.space
19 w_lookup_type = space.type(w_key)
20 if (space.is_w(w_lookup_type, space.w_str) or # Most common path first
21 space.abstract_issubclass_w(w_lookup_type, space.w_str)):
22 return self.getitem_str(w_dict, space.str_w(w_key))
23 elif space.abstract_issubclass_w(w_lookup_type, space.w_unicode):
24 try:
25 w_key = space.str(w_key)
26 except OperationError as e:
27 if not e.match(space, space.w_UnicodeEncodeError):
28 raise
29 # non-ascii unicode is never equal to a byte string
30 return None
31 return self.getitem_str(w_dict, space.str_w(w_key))
32 else:
33 return None
34
35 def getitem_str(self, w_dict, key):
36 return self.unerase(w_dict.dstorage).getdictvalue(self.space, key)
37
38 def setitem(self, w_dict, w_key, w_value):
39 space = self.space
40 if space.is_w(space.type(w_key), space.w_str):
41 self.setitem_str(w_dict, self.space.str_w(w_key), w_value)
42 else:
43 raise oefmt(space.w_TypeError,
44 "cannot add non-string keys to dict of a type")
45
46 def setitem_str(self, w_dict, key, w_value):
47 w_type = self.unerase(w_dict.dstorage)
48 try:
49 w_type.setdictvalue(self.space, key, w_value)
50 except OperationError as e:
51 if not e.match(self.space, self.space.w_TypeError):
52 raise
53 if not w_type.is_cpytype():
54 raise
55 # Allow cpyext to write to type->tp_dict even in the case
56 # of a builtin type.
57 # Like CPython, we assume that this is only done early
58 # after the type is created, and we don't invalidate any
59 # cache. User code shoud call PyType_Modified().
60 w_type.dict_w[key] = w_value
61
62 def setdefault(self, w_dict, w_key, w_default):
63 w_result = self.getitem(w_dict, w_key)
64 if w_result is not None:
65 return w_result
66 self.setitem(w_dict, w_key, w_default)
67 return w_default
68
69 def delitem(self, w_dict, w_key):
70 space = self.space
71 w_key_type = space.type(w_key)
72 if space.is_w(w_key_type, space.w_str):
73 key = self.space.str_w(w_key)
74 if not self.unerase(w_dict.dstorage).deldictvalue(space, key):
75 raise KeyError
76 else:
77 raise KeyError
78
79 def length(self, w_dict):
80 return len(self.unerase(w_dict.dstorage).dict_w)
81
82 def w_keys(self, w_dict):
83 space = self.space
84 return space.newlist_bytes(self.unerase(w_dict.dstorage).dict_w.keys())
85
86 def values(self, w_dict):
87 return [unwrap_cell(self.space, w_value) for w_value in
88 self.unerase(w_dict.dstorage).dict_w.itervalues()]
89
90 def items(self, w_dict):
91 space = self.space
92 return [space.newtuple([space.wrap(key), unwrap_cell(self.space, w_value)])
93 for (key, w_value) in self.unerase(w_dict.dstorage).dict_w.iteritems()]
94
95 def clear(self, w_dict):
96 space = self.space
97 w_type = self.unerase(w_dict.dstorage)
98 if not w_type.is_heaptype():
99 raise oefmt(space.w_TypeError,
100 "can't clear dictionary of type '%N'", w_type)
101 w_type.dict_w.clear()
102 w_type.mutated(None)
103
104 def getiterkeys(self, w_dict):
105 return self.unerase(w_dict.dstorage).dict_w.iterkeys()
106
107 def getitervalues(self, w_dict):
108 return self.unerase(w_dict.dstorage).dict_w.itervalues()
109
110 def getiteritems_with_hash(self, w_dict):
111 return iteritems_with_hash(self.unerase(w_dict.dstorage).dict_w)
112
113 def wrapkey(space, key):
114 return space.wrap(key)
115
116 def wrapvalue(space, value):
117 return unwrap_cell(space, value)
118
119 create_iterator_classes(ClassDictStrategy)
0 from rpython.rlib import rerased
1 from rpython.rlib.objectmodel import iteritems_with_hash
0 """
1 Read-only proxy for mappings.
22
3 from pypy.interpreter.error import OperationError, oefmt
4 from pypy.objspace.std.dictmultiobject import (
5 DictStrategy, create_iterator_classes)
6 from pypy.objspace.std.typeobject import unwrap_cell
3 Its main use is as the return type of cls.__dict__.
4 """
5
6 from pypy.interpreter.baseobjspace import W_Root
7 from pypy.interpreter.error import oefmt
8 from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
9 from pypy.interpreter.typedef import TypeDef, interp2app
10
11 class W_DictProxyObject(W_Root):
12 "Read-only proxy for mappings."
13
14 def __init__(self, w_mapping):
15 self.w_mapping = w_mapping
16
17 @staticmethod
18 def descr_new(space, w_type, w_mapping):
19 raise oefmt(space.w_TypeError, "Cannot create 'dictproxy' instances")
20
21 def descr_init(self, space, __args__):
22 pass
23
24 def descr_len(self, space):
25 return space.len(self.w_mapping)
26
27 def descr_getitem(self, space, w_key):
28 return space.getitem(self.w_mapping, w_key)
29
30 def descr_contains(self, space, w_key):
31 return space.contains(self.w_mapping, w_key)
32
33 def descr_iter(self, space):
34 return space.iter(self.w_mapping)
35
36 def descr_str(self, space):
37 return space.str(self.w_mapping)
38
39 def descr_repr(self, space):
40 return space.wrap("dict_proxy(%s)" %
41 (space.str_w(space.repr(self.w_mapping)),))
42
43 @unwrap_spec(w_default=WrappedDefault(None))
44 def get_w(self, space, w_key, w_default):
45 return space.call_method(self.w_mapping, "get", w_key, w_default)
46
47 def keys_w(self, space):
48 return space.call_method(self.w_mapping, "keys")
49
50 def descr_iterkeys(self, space):
51 return space.call_method(self.w_mapping, "iterkeys")
52
53 def values_w(self, space):
54 return space.call_method(self.w_mapping, "values")
55
56 def descr_itervalues(self, space):
57 return space.call_method(self.w_mapping, "itervalues")
58
59 def items_w(self, space):
60 return space.call_method(self.w_mapping, "items")
61
62 def descr_iteritems(self, space):
63 return space.call_method(self.w_mapping, "iteritems")
64
65 def copy_w(self, space):
66 return space.call_method(self.w_mapping, "copy")
67
68 cmp_methods = {}
69 def make_cmp_method(op):
70 def descr_op(self, space, w_other):
71 return getattr(space, op)(self.w_mapping, w_other)
72 descr_name = 'descr_' + op
73 descr_op.__name__ = descr_name
74 setattr(W_DictProxyObject, descr_name, descr_op)
75 cmp_methods['__%s__' % op] = interp2app(getattr(W_DictProxyObject, descr_name))
76
77 for op in ['eq', 'ne', 'gt', 'ge', 'lt', 'le']:
78 make_cmp_method(op)
779
880
9 class DictProxyStrategy(DictStrategy):
10 erase, unerase = rerased.new_erasing_pair("dictproxy")
11 erase = staticmethod(erase)
12 unerase = staticmethod(unerase)
13
14 def __init__(self, space):
15 DictStrategy.__init__(self, space)
16
17 def getitem(self, w_dict, w_key):
18 space = self.space
19 w_lookup_type = space.type(w_key)
20 if (space.is_w(w_lookup_type, space.w_str) or # Most common path first
21 space.abstract_issubclass_w(w_lookup_type, space.w_str)):
22 return self.getitem_str(w_dict, space.str_w(w_key))
23 elif space.abstract_issubclass_w(w_lookup_type, space.w_unicode):
24 try:
25 w_key = space.str(w_key)
26 except OperationError as e:
27 if not e.match(space, space.w_UnicodeEncodeError):
28 raise
29 # non-ascii unicode is never equal to a byte string
30 return None
31 return self.getitem_str(w_dict, space.str_w(w_key))
32 else:
33 return None
34
35 def getitem_str(self, w_dict, key):
36 return self.unerase(w_dict.dstorage).getdictvalue(self.space, key)
37
38 def setitem(self, w_dict, w_key, w_value):
39 space = self.space
40 if space.is_w(space.type(w_key), space.w_str):
41 self.setitem_str(w_dict, self.space.str_w(w_key), w_value)
42 else:
43 raise oefmt(space.w_TypeError,
44 "cannot add non-string keys to dict of a type")
45
46 def setitem_str(self, w_dict, key, w_value):
47 w_type = self.unerase(w_dict.dstorage)
48 try:
49 w_type.setdictvalue(self.space, key, w_value)
50 except OperationError as e:
51 if not e.match(self.space, self.space.w_TypeError):
52 raise
53 if not w_type.is_cpytype():
54 raise
55 # Allow cpyext to write to type->tp_dict even in the case
56 # of a builtin type.
57 # Like CPython, we assume that this is only done early
58 # after the type is created, and we don't invalidate any
59 # cache. User code shoud call PyType_Modified().
60 w_type.dict_w[key] = w_value
61
62 def setdefault(self, w_dict, w_key, w_default):
63 w_result = self.getitem(w_dict, w_key)
64 if w_result is not None:
65 return w_result
66 self.setitem(w_dict, w_key, w_default)
67 return w_default
68
69 def delitem(self, w_dict, w_key):
70 space = self.space
71 w_key_type = space.type(w_key)
72 if space.is_w(w_key_type, space.w_str):
73 key = self.space.str_w(w_key)
74 if not self.unerase(w_dict.dstorage).deldictvalue(space, key):
75 raise KeyError
76 else:
77 raise KeyError
78
79 def length(self, w_dict):
80 return len(self.unerase(w_dict.dstorage).dict_w)
81
82 def w_keys(self, w_dict):
83 space = self.space
84 return space.newlist_bytes(self.unerase(w_dict.dstorage).dict_w.keys())
85
86 def values(self, w_dict):
87 return [unwrap_cell(self.space, w_value) for w_value in self.unerase(w_dict.dstorage).dict_w.itervalues()]
88
89 def items(self, w_dict):
90 space = self.space
91 return [space.newtuple([space.wrap(key), unwrap_cell(self.space, w_value)])
92 for (key, w_value) in self.unerase(w_dict.dstorage).dict_w.iteritems()]
93
94 def clear(self, w_dict):
95 space = self.space
96 w_type = self.unerase(w_dict.dstorage)
97 if not w_type.is_heaptype():
98 raise oefmt(space.w_TypeError,
99 "can't clear dictionary of type '%N'", w_type)
100 w_type.dict_w.clear()
101 w_type.mutated(None)
102
103 def getiterkeys(self, w_dict):
104 return self.unerase(w_dict.dstorage).dict_w.iterkeys()
105 def getitervalues(self, w_dict):
106 return self.unerase(w_dict.dstorage).dict_w.itervalues()
107 def getiteritems_with_hash(self, w_dict):
108 return iteritems_with_hash(self.unerase(w_dict.dstorage).dict_w)
109 def wrapkey(space, key):
110 return space.wrap(key)
111 def wrapvalue(space, value):
112 return unwrap_cell(space, value)
113
114 create_iterator_classes(DictProxyStrategy)
81 W_DictProxyObject.typedef = TypeDef(
82 'dictproxy',
83 __new__=interp2app(W_DictProxyObject.descr_new),
84 __init__=interp2app(W_DictProxyObject.descr_init),
85 __len__=interp2app(W_DictProxyObject.descr_len),
86 __getitem__=interp2app(W_DictProxyObject.descr_getitem),
87 __contains__=interp2app(W_DictProxyObject.descr_contains),
88 __iter__=interp2app(W_DictProxyObject.descr_iter),
89 __str__=interp2app(W_DictProxyObject.descr_str),
90 __repr__=interp2app(W_DictProxyObject.descr_repr),
91 get=interp2app(W_DictProxyObject.get_w),
92 keys=interp2app(W_DictProxyObject.keys_w),
93 iterkeys=interp2app(W_DictProxyObject.descr_iterkeys),
94 values=interp2app(W_DictProxyObject.values_w),
95 itervalues=interp2app(W_DictProxyObject.descr_itervalues),
96 items=interp2app(W_DictProxyObject.items_w),
97 iteritems=interp2app(W_DictProxyObject.descr_iteritems),
98 copy=interp2app(W_DictProxyObject.copy_w),
99 **cmp_methods
100 )
361361 return _new_int(space, w_inttype, w_x, w_base)
362362
363363 def descr_hash(self, space):
364 # unlike CPython, we don't special-case the value -1 in most of
365 # our hash functions, so there is not much sense special-casing
366 # it here either. Make sure this is consistent with the hash of
367 # floats and longs.
368 return self.int(space)
364 # For compatibility with CPython, we special-case -1
365 h = self.intval
366 h -= (h == -1) # No explicit condition, to avoid JIT bridges
367 return wrapint(space, h)
369368
370369 def _int(self, space):
371370 return self.int(space)
794794 tp = space.type(w_item)
795795 while i < stop and i < w_list.length():
796796 find_jmp.jit_merge_point(tp=tp)
797 if space.eq_w(w_list.getitem(i), w_item):
797 if space.eq_w(w_item, w_list.getitem(i)):
798798 return i
799799 i += 1
800800 raise ValueError
129129
130130 descr_repr = _make_descr_unaryop('repr')
131131 descr_str = _make_descr_unaryop('str')
132 descr_hash = _make_descr_unaryop('hash')
132
133 def descr_hash(self, space):
134 h = self.asbigint().hash()
135 h -= (h == -1)
136 return space.newint(h)
137
133138 descr_oct = _make_descr_unaryop('oct')
134139 descr_hex = _make_descr_unaryop('hex')
135140
386391 def _make_generic_descr_binop(opname):
387392 if opname not in COMMUTATIVE_OPS:
388393 raise Exception("Not supported")
389
394
390395 methname = opname + '_' if opname in ('and', 'or') else opname
391396 descr_rname = 'descr_r' + opname
392397 op = getattr(rbigint, methname)
393398 intop = getattr(rbigint, "int_" + methname)
394
399
395400 @func_renamer('descr_' + opname)
396401 def descr_binop(self, space, w_other):
397402 if isinstance(w_other, W_AbstractIntObject):
411416 return W_LongObject(op(w_other.asbigint(), self.num))
412417
413418 return descr_binop, descr_rbinop
414
419
415420 descr_add, descr_radd = _make_generic_descr_binop('add')
416421 descr_sub, descr_rsub = _make_generic_descr_binop_noncommutative('sub')
417422 descr_mul, descr_rmul = _make_generic_descr_binop('mul')
453458 except OverflowError: # b too big
454459 raise oefmt(space.w_OverflowError, "shift count too large")
455460 return W_LongObject(self.num.lshift(shift))
456
461
457462 def _int_lshift(self, space, w_other):
458463 if w_other < 0:
459464 raise oefmt(space.w_ValueError, "negative shift count")
460465 return W_LongObject(self.num.lshift(w_other))
461
466
462467 descr_lshift, descr_rlshift = _make_descr_binop(_lshift, _int_lshift)
463468
464469 def _rshift(self, space, w_other):
469474 except OverflowError: # b too big # XXX maybe just return 0L instead?
470475 raise oefmt(space.w_OverflowError, "shift count too large")
471476 return newlong(space, self.num.rshift(shift))
472
477
473478 def _int_rshift(self, space, w_other):
474479 if w_other < 0:
475480 raise oefmt(space.w_ValueError, "negative shift count")
484489 raise oefmt(space.w_ZeroDivisionError,
485490 "long division or modulo by zero")
486491 return newlong(space, z)
487
492
488493 def _floordiv(self, space, w_other):
489494 try:
490495 z = self.num.floordiv(w_other.asbigint())
504509 raise oefmt(space.w_ZeroDivisionError,
505510 "long division or modulo by zero")
506511 return newlong(space, z)
507
512
508513 def _int_mod(self, space, w_other):
509514 try:
510515 z = self.num.int_mod(w_other)
220220 stack_index = 0
221221 while True:
222222 current = self
223 number_to_readd = 0
224223 number_to_readd, attr = self._find_branch_to_move_into(name, index)
225224 # we found the attributes further up, need to save the
226225 # previous values of the attributes we passed
992991 if index != INVALID:
993992 attr = map.find_map_attr(attrname, index)
994993 if attr is not None:
995 # Note that if map.terminator is a DevolvedDictTerminator,
994 # Note that if map.terminator is a DevolvedDictTerminator
995 # or the class provides its own dict, not using mapdict, then:
996996 # map.find_map_attr will always return None if index==DICT.
997997 _fill_cache(pycode, nameindex, map, version_tag, attr.storageindex)
998998 return w_obj._mapdict_read_storage(attr.storageindex)
10141014
10151015 def LOOKUP_METHOD_mapdict_fill_cache_method(space, pycode, name, nameindex,
10161016 w_obj, w_type, w_method):
1017 # if the layout has a dict itself, then mapdict is not used for normal
1018 # attributes. Then the cache won't be able to spot changes to the dict.
1019 # Thus we don't cache. see test_bug_builtin_types_callmethod
1020 if w_type.layout.typedef.hasdict:
1021 return
1022
10171023 if w_method is None or isinstance(w_method, MutableCell):
10181024 # don't cache the MutableCell XXX could be fixed
10191025 return
7272
7373 def descr_getitem(self, space, w_index):
7474 start, stop, step, size = space.decode_index4(w_index, self.getlength())
75 itemsize = self.buf.getitemsize()
76 if itemsize > 1:
77 start *= itemsize
78 size *= itemsize
79 stop = start + size
80 if step == 0:
81 step = 1
82 if stop > self.getlength():
83 raise oefmt(space.w_IndexError, 'index out of range')
7584 if step not in (0, 1):
7685 raise oefmt(space.w_NotImplementedError, "")
7786 if step == 0: # index only
8493 if self.buf.readonly:
8594 raise oefmt(space.w_TypeError, "cannot modify read-only memory")
8695 start, stop, step, size = space.decode_index4(w_index, self.getlength())
96 itemsize = self.buf.getitemsize()
97 if itemsize > 1:
98 start *= itemsize
99 size *= itemsize
100 stop = start + size
101 if step == 0:
102 step = 1
103 if stop > self.getlength():
104 raise oefmt(space.w_IndexError, 'index out of range')
87105 if step not in (0, 1):
88106 raise oefmt(space.w_NotImplementedError, "")
89107 value = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
99117 return space.wrap(self.buf.getlength())
100118
101119 def w_get_format(self, space):
102 return space.wrap("B")
120 return space.wrap(self.buf.getformat())
103121
104122 def w_get_itemsize(self, space):
105 return space.wrap(1)
123 return space.wrap(self.buf.getitemsize())
106124
107125 def w_get_ndim(self, space):
108 return space.wrap(1)
126 return space.wrap(self.buf.getndim())
109127
110128 def w_is_readonly(self, space):
111 return space.wrap(self.buf.readonly)
129 return space.newbool(bool(self.buf.readonly))
112130
113131 def w_get_shape(self, space):
114 return space.newtuple([space.wrap(self.getlength())])
132 return space.newtuple([space.wrap(x) for x in self.buf.getshape()])
115133
116134 def w_get_strides(self, space):
117 return space.newtuple([space.wrap(1)])
135 return space.newtuple([space.wrap(x) for x in self.buf.getstrides()])
118136
119137 def w_get_suboffsets(self, space):
120138 # I've never seen anyone filling this field
1515 from pypy.objspace.std.boolobject import W_BoolObject
1616 from pypy.objspace.std.bufferobject import W_Buffer
1717 from pypy.objspace.std.bytearrayobject import W_BytearrayObject
18 from pypy.objspace.std.bytesobject import W_AbstractBytesObject, W_BytesObject, wrapstr
18 from pypy.objspace.std.bytesobject import W_AbstractBytesObject, W_BytesObject
1919 from pypy.objspace.std.complexobject import W_ComplexObject
2020 from pypy.objspace.std.dictmultiobject import W_DictMultiObject, W_DictObject
2121 from pypy.objspace.std.floatobject import W_FloatObject
3030 from pypy.objspace.std.sliceobject import W_SliceObject
3131 from pypy.objspace.std.tupleobject import W_AbstractTupleObject, W_TupleObject
3232 from pypy.objspace.std.typeobject import W_TypeObject, TypeCache
33 from pypy.objspace.std.unicodeobject import W_UnicodeObject, wrapunicode
33 from pypy.objspace.std.unicodeobject import W_UnicodeObject
3434
3535
3636 class StdObjSpace(ObjSpace):
127127 assert typedef is not None
128128 return self.fromcache(TypeCache).getorbuild(typedef)
129129
130 def wrapbytes(self, x):
131 return wrapstr(self, x)
132
133130 @specialize.argtype(1)
134131 def wrap(self, x):
135132 "Wraps the Python value 'x' into one of the wrapper classes."
150147 else:
151148 return self.newint(x)
152149 if isinstance(x, str):
153 return wrapstr(self, x)
150 return self.newbytes(x)
154151 if isinstance(x, unicode):
155 return wrapunicode(self, x)
152 return self.newunicode(x)
156153 if isinstance(x, float):
157154 return W_FloatObject(x)
158155 if isinstance(x, W_Root):
321318
322319 def newbuffer(self, w_obj):
323320 return W_Buffer(w_obj)
321
322 def newbytes(self, s):
323 return W_BytesObject(s)
324
325 def newunicode(self, uni):
326 return W_UnicodeObject(uni)
324327
325328 def type(self, w_obj):
326329 jit.promote(w_obj.__class__)
55 from pypy.objspace.std.bytesobject import W_BytesObject
66 from pypy.objspace.std.intobject import W_IntObject
77 from pypy.objspace.std.unicodeobject import W_UnicodeObject
8 from pypy.objspace.std.util import IDTAG_SPECIAL, IDTAG_SHIFT
89
910 from rpython.rlib.objectmodel import r_dict
1011 from rpython.rlib.objectmodel import iterkeys_with_hash, contains_with_hash
573574
574575 class W_FrozensetObject(W_BaseSetObject):
575576 hash = 0
577
578 def is_w(self, space, w_other):
579 if not isinstance(w_other, W_FrozensetObject):
580 return False
581 if self is w_other:
582 return True
583 if self.user_overridden_class or w_other.user_overridden_class:
584 return False
585 # empty frozensets are unique-ified
586 return 0 == w_other.length() == self.length()
587
588 def immutable_unique_id(self, space):
589 if self.user_overridden_class or self.length() > 0:
590 return None
591 # empty frozenset: base value 259
592 uid = (259 << IDTAG_SHIFT) | IDTAG_SPECIAL
593 return space.wrap(uid)
576594
577595 def _newobj(self, space, w_iterable):
578596 """Make a new frozenset by taking ownership of 'w_iterable'."""
6161 value = getattr(self, 'value%s' % i)
6262 if typetuple[i] == object:
6363 y = space.int_w(space.hash(value))
64 elif typetuple[i] == int:
65 # mimic cpythons behavior of a hash value of -2 for -1
66 y = value
67 if y == -1:
68 y = -2
6469 elif typetuple[i] == float:
6570 # get the correct hash for float which is an
6671 # integer & other less frequent cases
33 def test_init(self):
44 import sys
55 class A(object):
6 def __buffer__(self):
6 def __buffer__(self, flags):
77 return buffer('123')
88 if '__pypy__' not in sys.builtin_module_names:
99 raises(TypeError, buffer, A())
22 def teardown_method(self, method):
33 pass
44
5 def test_str_w(self):
6 assert self.space.str_w(self.space.wrap("foo")) == "foo"
5 def test_bytes_w(self):
6 assert self.space.bytes_w(self.space.newbytes("foo")) == "foo"
77
88 def test_equality(self):
9 w = self.space.wrap
9 w = self.space.newbytes
1010 assert self.space.eq_w(w('abc'), w('abc'))
1111 assert not self.space.eq_w(w('abc'), w('def'))
1212
1313 def test_order_cmp(self):
1414 space = self.space
15 w = space.wrap
15 w = space.newbytes
1616 assert self.space.is_true(space.lt(w('a'), w('b')))
1717 assert self.space.is_true(space.lt(w('a'), w('ab')))
1818 assert self.space.is_true(space.le(w('a'), w('a')))
1919 assert self.space.is_true(space.gt(w('a'), w('')))
2020
2121 def test_truth(self):
22 w = self.space.wrap
22 w = self.space.newbytes
2323 assert self.space.is_true(w('non-empty'))
2424 assert not self.space.is_true(w(''))
2525
2626 def test_getitem(self):
2727 space = self.space
2828 w = space.wrap
29 w_str = w('abc')
29 w_str = space.newbytes('abc')
3030 assert self.space.eq_w(space.getitem(w_str, w(0)), w('a'))
3131 assert self.space.eq_w(space.getitem(w_str, w(-1)), w('c'))
3232 self.space.raises_w(space.w_IndexError,
3737 def test_slice(self):
3838 space = self.space
3939 w = space.wrap
40 w_str = w('abc')
40 wb = space.newbytes
41 w_str = wb('abc')
4142
4243 w_slice = space.newslice(w(0), w(0), space.w_None)
43 assert self.space.eq_w(space.getitem(w_str, w_slice), w(''))
44 assert self.space.eq_w(space.getitem(w_str, w_slice), wb(''))
4445
4546 w_slice = space.newslice(w(0), w(1), space.w_None)
46 assert self.space.eq_w(space.getitem(w_str, w_slice), w('a'))
47 assert self.space.eq_w(space.getitem(w_str, w_slice), wb('a'))
4748
4849 w_slice = space.newslice(w(0), w(10), space.w_None)
49 assert self.space.eq_w(space.getitem(w_str, w_slice), w('abc'))
50 assert self.space.eq_w(space.getitem(w_str, w_slice), wb('abc'))
5051
5152 w_slice = space.newslice(space.w_None, space.w_None, space.w_None)
52 assert self.space.eq_w(space.getitem(w_str, w_slice), w('abc'))
53 assert self.space.eq_w(space.getitem(w_str, w_slice), wb('abc'))
5354
5455 w_slice = space.newslice(space.w_None, w(-1), space.w_None)
55 assert self.space.eq_w(space.getitem(w_str, w_slice), w('ab'))
56 assert self.space.eq_w(space.getitem(w_str, w_slice), wb('ab'))
5657
5758 w_slice = space.newslice(w(-1), space.w_None, space.w_None)
58 assert self.space.eq_w(space.getitem(w_str, w_slice), w('c'))
59 assert self.space.eq_w(space.getitem(w_str, w_slice), wb('c'))
5960
6061 def test_extended_slice(self):
6162 space = self.space
6566 return
6667 w_None = space.w_None
6768 w = space.wrap
68 w_str = w('hello')
69 wb = space.newbytes
70 w_str = wb('hello')
6971
7072 w_slice = space.newslice(w_None, w_None, w(1))
71 assert self.space.eq_w(space.getitem(w_str, w_slice), w('hello'))
73 assert self.space.eq_w(space.getitem(w_str, w_slice), wb('hello'))
7274
7375 w_slice = space.newslice(w_None, w_None, w(-1))
74 assert self.space.eq_w(space.getitem(w_str, w_slice), w('olleh'))
76 assert self.space.eq_w(space.getitem(w_str, w_slice), wb('olleh'))
7577
7678 w_slice = space.newslice(w_None, w_None, w(2))
77 assert self.space.eq_w(space.getitem(w_str, w_slice), w('hlo'))
79 assert self.space.eq_w(space.getitem(w_str, w_slice), wb('hlo'))
7880
7981 w_slice = space.newslice(w(1), w_None, w(2))
80 assert self.space.eq_w(space.getitem(w_str, w_slice), w('el'))
82 assert self.space.eq_w(space.getitem(w_str, w_slice), wb('el'))
8183
8284 def test_listview_bytes(self):
83 w_str = self.space.wrap('abcd')
84 assert self.space.listview_bytes(w_str) == list("abcd")
85 w_bytes = self.space.newbytes('abcd')
86 assert self.space.listview_bytes(w_bytes) == list("abcd")
8587
8688 class AppTestBytesObject:
8789
109111 assert str(exc_info.value) == expected
110112
111113 def test_split(self):
112 assert "".split() == []
113 assert "".split('x') == ['']
114 assert " ".split() == []
115 assert "a".split() == ['a']
114 assert b"".split() == []
115 assert b"".split(b'x') == [b'']
116 assert b" ".split() == []
117 assert b"a".split() == [b'a']
116118 assert "a".split("a", 1) == ['', '']
117 assert " ".split(" ", 1) == ['', '']
118 assert "aa".split("a", 2) == ['', '', '']
119 assert " a ".split() == ['a']
120 assert "a b c".split() == ['a','b','c']
121 assert 'this is the split function'.split() == ['this', 'is', 'the', 'split', 'function']
122 assert 'a|b|c|d'.split('|') == ['a', 'b', 'c', 'd']
123 assert 'a|b|c|d'.split('|', 2) == ['a', 'b', 'c|d']
124 assert 'a b c d'.split(None, 1) == ['a', 'b c d']
125 assert 'a b c d'.split(None, 2) == ['a', 'b', 'c d']
126 assert 'a b c d'.split(None, 3) == ['a', 'b', 'c', 'd']
127 assert 'a b c d'.split(None, 4) == ['a', 'b', 'c', 'd']
128 assert 'a b c d'.split(None, 0) == ['a b c d']
129 assert 'a b c d'.split(None, 2) == ['a', 'b', 'c d']
130 assert 'a b c d '.split() == ['a', 'b', 'c', 'd']
131 assert 'a//b//c//d'.split('//') == ['a', 'b', 'c', 'd']
132 assert 'endcase test'.split('test') == ['endcase ', '']
133 raises(ValueError, 'abc'.split, '')
119 assert b" ".split(b" ", 1) == [b'', b'']
120 assert b"aa".split(b"a", 2) == [b'', b'', b'']
121 assert b" a ".split() == [b'a']
122 assert b"a b c".split() == [b'a',b'b',b'c']
123 assert b'this is the split function'.split() == [
124 b'this', b'is', b'the', b'split', b'function']
125 assert b'a|b|c|d'.split(b'|') == [b'a', b'b', b'c', b'd']
126 assert b'a|b|c|d'.split(b'|', 2) == [b'a', b'b', b'c|d']
127 assert b'a b c d'.split(None, 1) == [b'a', b'b c d']
128 assert b'a b c d'.split(None, 2) == [b'a', b'b', b'c d']
129 assert b'a b c d'.split(None, 3) == [b'a', b'b', b'c', b'd']
130 assert b'a b c d'.split(None, 4) == [b'a', b'b', b'c', b'd']
131 assert b'a b c d'.split(None, 0) == [b'a b c d']
132 assert b'a b c d'.split(None, 2) == [b'a', b'b', b'c d']
133 assert b'a b c d '.split() == [b'a', b'b', b'c', b'd']
134 assert b'a//b//c//d'.split(b'//') == [b'a', b'b', b'c', b'd']
135 assert b'endcase test'.split(b'test') == [b'endcase ', b'']
136 raises(ValueError, b'abc'.split, b'')
134137
135138 def test_rsplit(self):
136139 assert "".rsplit() == []
140143 assert " ".rsplit(" ", 1) == ['', '']
141144 assert "aa".rsplit("a", 2) == ['', '', '']
142145 assert " a ".rsplit() == ['a']
143 assert "a b c".rsplit() == ['a','b','c']
146 assert b"a b c".rsplit() == [b'a',b'b',b'c']
144147 assert 'this is the rsplit function'.rsplit() == ['this', 'is', 'the', 'rsplit', 'function']
145 assert 'a|b|c|d'.rsplit('|') == ['a', 'b', 'c', 'd']
146 assert 'a|b|c|d'.rsplit('|', 2) == ['a|b', 'c', 'd']
147 assert 'a b c d'.rsplit(None, 1) == ['a b c', 'd']
148 assert 'a b c d'.rsplit(None, 2) == ['a b', 'c', 'd']
149 assert 'a b c d'.rsplit(None, 3) == ['a', 'b', 'c', 'd']
150 assert 'a b c d'.rsplit(None, 4) == ['a', 'b', 'c', 'd']
151 assert 'a b c d'.rsplit(None, 0) == ['a b c d']
152 assert 'a b c d'.rsplit(None, 2) == ['a b', 'c', 'd']
153 assert 'a b c d '.rsplit() == ['a', 'b', 'c', 'd']
154 assert 'a//b//c//d'.rsplit('//') == ['a', 'b', 'c', 'd']
155 assert 'endcase test'.rsplit('test') == ['endcase ', '']
156 raises(ValueError, 'abc'.rsplit, '')
148 assert b'a|b|c|d'.rsplit(b'|') == [b'a', b'b', b'c', b'd']
149 assert b'a|b|c|d'.rsplit(b'|', 2) == [b'a|b', b'c', b'd']
150 assert b'a b c d'.rsplit(None, 1) == [b'a b c', b'd']
151 assert b'a b c d'.rsplit(None, 2) == [b'a b', b'c', b'd']
152 assert b'a b c d'.rsplit(None, 3) == [b'a', b'b', b'c', b'd']
153 assert b'a b c d'.rsplit(None, 4) == [b'a', b'b', b'c', b'd']
154 assert b'a b c d'.rsplit(None, 0) == [b'a b c d']
155 assert b'a b c d'.rsplit(None, 2) == [b'a b', b'c', b'd']
156 assert b'a b c d '.rsplit() == [b'a', b'b', b'c', b'd']
157 assert b'a//b//c//d'.rsplit(b'//') == [b'a', b'b', b'c', b'd']
158 assert b'endcase test'.rsplit(b'test') == [b'endcase ', b'']
159 raises(ValueError, b'abc'.rsplit, b'')
157160
158161 def test_split_splitchar(self):
159162 assert "/a/b/c".split('/') == ['','a','b','c']
160163
161164 def test_title(self):
162 assert "brown fox".title() == "Brown Fox"
163 assert "!brown fox".title() == "!Brown Fox"
164 assert "bROWN fOX".title() == "Brown Fox"
165 assert "Brown Fox".title() == "Brown Fox"
166 assert "bro!wn fox".title() == "Bro!Wn Fox"
165 assert b"brown fox".title() == b"Brown Fox"
166 assert b"!brown fox".title() == b"!Brown Fox"
167 assert b"bROWN fOX".title() == b"Brown Fox"
168 assert b"Brown Fox".title() == b"Brown Fox"
169 assert b"bro!wn fox".title() == b"Bro!Wn Fox"
167170
168171 def test_istitle(self):
169 assert "".istitle() == False
170 assert "!".istitle() == False
171 assert "!!".istitle() == False
172 assert "brown fox".istitle() == False
173 assert "!brown fox".istitle() == False
174 assert "bROWN fOX".istitle() == False
175 assert "Brown Fox".istitle() == True
176 assert "bro!wn fox".istitle() == False
177 assert "Bro!wn fox".istitle() == False
178 assert "!brown Fox".istitle() == False
179 assert "!Brown Fox".istitle() == True
180 assert "Brow&&&&N Fox".istitle() == True
181 assert "!Brow&&&&n Fox".istitle() == False
172 assert b"".istitle() == False
173 assert b"!".istitle() == False
174 assert b"!!".istitle() == False
175 assert b"brown fox".istitle() == False
176 assert b"!brown fox".istitle() == False
177 assert b"bROWN fOX".istitle() == False
178 assert b"Brown Fox".istitle() == True
179 assert b"bro!wn fox".istitle() == False
180 assert b"Bro!wn fox".istitle() == False
181 assert b"!brown Fox".istitle() == False
182 assert b"!Brown Fox".istitle() == True
183 assert b"Brow&&&&N Fox".istitle() == True
184 assert b"!Brow&&&&n Fox".istitle() == False
182185
183186 def test_capitalize(self):
184 assert "brown fox".capitalize() == "Brown fox"
185 assert ' hello '.capitalize() == ' hello '
186 assert 'Hello '.capitalize() == 'Hello '
187 assert 'hello '.capitalize() == 'Hello '
188 assert 'aaaa'.capitalize() == 'Aaaa'
189 assert 'AaAa'.capitalize() == 'Aaaa'
187 assert b"brown fox".capitalize() == b"Brown fox"
188 assert b' hello '.capitalize() == b' hello '
189 assert b'Hello '.capitalize() == b'Hello '
190 assert b'hello '.capitalize() == b'Hello '
191 assert b'aaaa'.capitalize() == b'Aaaa'
192 assert b'AaAa'.capitalize() == b'Aaaa'
190193
191194 def test_rjust(self):
192 s = "abc"
195 s = b"abc"
193196 assert s.rjust(2) == s
194197 assert s.rjust(3) == s
195 assert s.rjust(4) == " " + s
196 assert s.rjust(5) == " " + s
197 assert 'abc'.rjust(10) == ' abc'
198 assert 'abc'.rjust(6) == ' abc'
199 assert 'abc'.rjust(3) == 'abc'
200 assert 'abc'.rjust(2) == 'abc'
201 assert 'abc'.rjust(5, '*') == '**abc' # Python 2.4
198 assert s.rjust(4) == b" " + s
199 assert s.rjust(5) == b" " + s
200 assert b'abc'.rjust(10) == b' abc'
201 assert b'abc'.rjust(6) == b' abc'
202 assert b'abc'.rjust(3) == b'abc'
203 assert b'abc'.rjust(2) == b'abc'
204 assert b'abc'.rjust(5, b'*') == b'**abc' # Python 2.4
202205 raises(TypeError, 'abc'.rjust, 5, 'xx')
203206
204207 def test_ljust(self):
205 s = "abc"
208 s = b"abc"
206209 assert s.ljust(2) == s
207210 assert s.ljust(3) == s
208 assert s.ljust(4) == s + " "
209 assert s.ljust(5) == s + " "
210 assert 'abc'.ljust(10) == 'abc '
211 assert 'abc'.ljust(6) == 'abc '
212 assert 'abc'.ljust(3) == 'abc'
213 assert 'abc'.ljust(2) == 'abc'
214 assert 'abc'.ljust(5, '*') == 'abc**' # Python 2.4
211 assert s.ljust(4) == s + b" "
212 assert s.ljust(5) == s + b" "
213 assert b'abc'.ljust(10) == b'abc '
214 assert b'abc'.ljust(6) == b'abc '
215 assert b'abc'.ljust(3) == b'abc'
216 assert b'abc'.ljust(2) == b'abc'
217 assert b'abc'.ljust(5, b'*') == b'abc**' # Python 2.4
215218 raises(TypeError, 'abc'.ljust, 6, '')
216219
217220 def test_replace(self):
218 assert 'one!two!three!'.replace('!', '@', 1) == 'one@two!three!'
219 assert 'one!two!three!'.replace('!', '') == 'onetwothree'
220 assert 'one!two!three!'.replace('!', '@', 2) == 'one@two@three!'
221 assert 'one!two!three!'.replace('!', '@', 3) == 'one@two@three@'
222 assert 'one!two!three!'.replace('!', '@', 4) == 'one@two@three@'
223 assert 'one!two!three!'.replace('!', '@', 0) == 'one!two!three!'
224 assert 'one!two!three!'.replace('!', '@') == 'one@two@three@'
225 assert 'one!two!three!'.replace('x', '@') == 'one!two!three!'
226 assert 'one!two!three!'.replace('x', '@', 2) == 'one!two!three!'
227 assert 'abc'.replace('', '-') == '-a-b-c-'
228 assert 'abc'.replace('', '-', 3) == '-a-b-c'
229 assert 'abc'.replace('', '-', 0) == 'abc'
230 assert ''.replace('', '') == ''
231 assert ''.replace('', 'a') == 'a'
232 assert 'abc'.replace('ab', '--', 0) == 'abc'
233 assert 'abc'.replace('xy', '--') == 'abc'
234 assert '123'.replace('123', '') == ''
235 assert '123123'.replace('123', '') == ''
236 assert '123x123'.replace('123', '') == 'x'
221 assert b'one!two!three!'.replace(b'!', b'@', 1) == b'one@two!three!'
222 assert b'one!two!three!'.replace(b'!', b'') == b'onetwothree'
223 assert b'one!two!three!'.replace(b'!', b'@', 2) == b'one@two@three!'
224 assert b'one!two!three!'.replace(b'!', b'@', 3) == b'one@two@three@'
225 assert b'one!two!three!'.replace(b'!', b'@', 4) == b'one@two@three@'
226 assert b'one!two!three!'.replace(b'!', b'@', 0) == b'one!two!three!'
227 assert b'one!two!three!'.replace(b'!', b'@') == b'one@two@three@'
228 assert b'one!two!three!'.replace(b'x', b'@') == b'one!two!three!'
229 assert b'one!two!three!'.replace(b'x', b'@', 2) == b'one!two!three!'
230 assert b'abc'.replace(b'', b'-') == b'-a-b-c-'
231 assert b'abc'.replace(b'', b'-', 3) == b'-a-b-c'
232 assert b'abc'.replace(b'', b'-', 0) == b'abc'
233 assert b''.replace(b'', b'') == b''
234 assert b''.replace(b'', b'a') == b'a'
235 assert b'abc'.replace(b'ab', b'--', 0) == b'abc'
236 assert b'abc'.replace(b'xy', b'--') == b'abc'
237 assert b'123'.replace(b'123', b'') == b''
238 assert b'123123'.replace(b'123', b'') == b''
239 assert b'123x123'.replace(b'123', b'') == b'x'
237240
238241 def test_replace_buffer(self):
239242 assert 'one'.replace(buffer('o'), buffer('n'), 1) == 'nne'
244247 assert s.strip() == "a b"
245248 assert s.rstrip() == " a b"
246249 assert s.lstrip() == "a b "
247 assert 'xyzzyhelloxyzzy'.strip('xyz') == 'hello'
248 assert 'xyzzyhelloxyzzy'.lstrip('xyz') == 'helloxyzzy'
249 assert 'xyzzyhelloxyzzy'.rstrip('xyz') == 'xyzzyhello'
250 assert b'xyzzyhelloxyzzy'.strip(b'xyz') == b'hello'
251 assert b'xyzzyhelloxyzzy'.lstrip(b'xyz') == b'helloxyzzy'
252 assert b'xyzzyhelloxyzzy'.rstrip(b'xyz') == b'xyzzyhello'
250253
251254 def test_zfill(self):
252 assert '123'.zfill(2) == '123'
253 assert '123'.zfill(3) == '123'
254 assert '123'.zfill(4) == '0123'
255 assert '+123'.zfill(3) == '+123'
256 assert '+123'.zfill(4) == '+123'
257 assert '+123'.zfill(5) == '+0123'
258 assert '-123'.zfill(3) == '-123'
259 assert '-123'.zfill(4) == '-123'
260 assert '-123'.zfill(5) == '-0123'
261 assert ''.zfill(3) == '000'
262 assert '34'.zfill(1) == '34'
263 assert '34'.zfill(4) == '0034'
255 assert b'123'.zfill(2) == b'123'
256 assert b'123'.zfill(3) == b'123'
257 assert b'123'.zfill(4) == b'0123'
258 assert b'+123'.zfill(3) == b'+123'
259 assert b'+123'.zfill(4) == b'+123'
260 assert b'+123'.zfill(5) == b'+0123'
261 assert b'-123'.zfill(3) == b'-123'
262 assert b'-123'.zfill(4) == b'-123'
263 assert b'-123'.zfill(5) == b'-0123'
264 assert b''.zfill(3) == b'000'
265 assert b'34'.zfill(1) == b'34'
266 assert b'34'.zfill(4) == b'0034'
264267
265268 def test_center(self):
266269 s="a b"
274277 assert s.center(7) == " a b "
275278 assert s.center(8) == " a b "
276279 assert s.center(9) == " a b "
277 assert 'abc'.center(10) == ' abc '
278 assert 'abc'.center(6) == ' abc '
279 assert 'abc'.center(3) == 'abc'
280 assert 'abc'.center(2) == 'abc'
281 assert 'abc'.center(5, '*') == '*abc*' # Python 2.4
282 raises(TypeError, 'abc'.center, 4, 'cba')
283 assert ' abc'.center(7) == ' abc '
280 assert b'abc'.center(10) == b' abc '
281 assert b'abc'.center(6) == b' abc '
282 assert b'abc'.center(3) == b'abc'
283 assert b'abc'.center(2) == b'abc'
284 assert b'abc'.center(5, b'*') == b'*abc*' # Python 2.4
285 raises(TypeError, b'abc'.center, 4, b'cba')
286 assert b' abc'.center(7) == b' abc '
284287
285288 def test_count(self):
286 assert "".count("x") ==0
287 assert "".count("") ==1
288 assert "Python".count("") ==7
289 assert "ab aaba".count("ab") ==2
290 assert 'aaa'.count('a') == 3
291 assert 'aaa'.count('b') == 0
292 assert 'aaa'.count('a', -1) == 1
293 assert 'aaa'.count('a', -10) == 3
294 assert 'aaa'.count('a', 0, -1) == 2
295 assert 'aaa'.count('a', 0, -10) == 0
296 assert 'ababa'.count('aba') == 1
289 assert b"".count(b"x") ==0
290 assert b"".count(b"") ==1
291 assert b"Python".count(b"") ==7
292 assert b"ab aaba".count(b"ab") ==2
293 assert b'aaa'.count(b'a') == 3
294 assert b'aaa'.count(b'b') == 0
295 assert b'aaa'.count(b'a', -1) == 1
296 assert b'aaa'.count(b'a', -10) == 3
297 assert b'aaa'.count(b'a', 0, -1) == 2
298 assert b'aaa'.count(b'a', 0, -10) == 0
299 assert b'ababa'.count(b'aba') == 1
297300
298301 def test_startswith(self):
299 assert 'ab'.startswith('ab') is True
300 assert 'ab'.startswith('a') is True
301 assert 'ab'.startswith('') is True
302 assert 'x'.startswith('a') is False
303 assert 'x'.startswith('x') is True
304 assert ''.startswith('') is True
305 assert ''.startswith('a') is False
306 assert 'x'.startswith('xx') is False
307 assert 'y'.startswith('xx') is False
302 assert b'ab'.startswith(b'ab') is True
303 assert b'ab'.startswith(b'a') is True
304 assert b'ab'.startswith(b'') is True
305 assert b'x'.startswith(b'a') is False
306 assert b'x'.startswith(b'x') is True
307 assert b''.startswith(b'') is True
308 assert b''.startswith(b'a') is False
309 assert b'x'.startswith(b'xx') is False
310 assert b'y'.startswith(b'xx') is False
308311
309312 def test_startswith_more(self):
310 assert 'ab'.startswith('a', 0) is True
311 assert 'ab'.startswith('a', 1) is False
312 assert 'ab'.startswith('b', 1) is True
313 assert 'abc'.startswith('bc', 1, 2) is False
314 assert 'abc'.startswith('c', -1, 4) is True
313 assert b'ab'.startswith(b'a', 0) is True
314 assert b'ab'.startswith(b'a', 1) is False
315 assert b'ab'.startswith(b'b', 1) is True
316 assert b'abc'.startswith(b'bc', 1, 2) is False
317 assert b'abc'.startswith(b'c', -1, 4) is True
315318
316319 def test_startswith_too_large(self):
317 assert 'ab'.startswith('b', 1) is True
318 assert 'ab'.startswith('', 2) is True
319 assert 'ab'.startswith('', 3) is False
320 assert 'ab'.endswith('b', 1) is True
321 assert 'ab'.endswith('', 2) is True
322 assert 'ab'.endswith('', 3) is False
320 assert b'ab'.startswith(b'b', 1) is True
321 assert b'ab'.startswith(b'', 2) is True
322 assert b'ab'.startswith(b'', 3) is False
323 assert b'ab'.endswith(b'b', 1) is True
324 assert b'ab'.endswith(b'', 2) is True
325 assert b'ab'.endswith(b'', 3) is False
323326
324327 def test_startswith_tuples(self):
325 assert 'hello'.startswith(('he', 'ha'))
326 assert not 'hello'.startswith(('lo', 'llo'))
327 assert 'hello'.startswith(('hellox', 'hello'))
328 assert not 'hello'.startswith(())
329 assert 'helloworld'.startswith(('hellowo', 'rld', 'lowo'), 3)
330 assert not 'helloworld'.startswith(('hellowo', 'ello', 'rld'), 3)
331 assert 'hello'.startswith(('lo', 'he'), 0, -1)
332 assert not 'hello'.startswith(('he', 'hel'), 0, 1)
333 assert 'hello'.startswith(('he', 'hel'), 0, 2)
334 raises(TypeError, 'hello'.startswith, (42,))
328 assert b'hello'.startswith((b'he', b'ha'))
329 assert not b'hello'.startswith((b'lo', b'llo'))
330 assert b'hello'.startswith((b'hellox', b'hello'))
331 assert not b'hello'.startswith(())
332 assert b'helloworld'.startswith((b'hellowo', b'rld', b'lowo'), 3)
333 assert not b'helloworld'.startswith((b'hellowo', b'ello', b'rld'), 3)
334 assert b'hello'.startswith((b'lo', b'he'), 0, -1)
335 assert not b'hello'.startswith((b'he', b'hel'), 0, 1)
336 assert b'hello'.startswith((b'he', b'hel'), 0, 2)
337 raises(TypeError, b'hello'.startswith, (42,))
335338
336339 def test_endswith(self):
337 assert 'ab'.endswith('ab') is True
338 assert 'ab'.endswith('b') is True
339 assert 'ab'.endswith('') is True
340 assert 'x'.endswith('a') is False
341 assert 'x'.endswith('x') is True
342 assert ''.endswith('') is True
343 assert ''.endswith('a') is False
344 assert 'x'.endswith('xx') is False
345 assert 'y'.endswith('xx') is False
340 assert b'ab'.endswith(b'ab') is True
341 assert b'ab'.endswith(b'b') is True
342 assert b'ab'.endswith(b'') is True
343 assert b'x'.endswith(b'a') is False
344 assert b'x'.endswith(b'x') is True
345 assert b''.endswith(b'') is True
346 assert b''.endswith(b'a') is False
347 assert b'x'.endswith(b'xx') is False
348 assert b'y'.endswith(b'xx') is False
346349
347350 def test_endswith_more(self):
348 assert 'abc'.endswith('ab', 0, 2) is True
349 assert 'abc'.endswith('bc', 1) is True
350 assert 'abc'.endswith('bc', 2) is False
351 assert 'abc'.endswith('b', -3, -1) is True
351 assert b'abc'.endswith(b'ab', 0, 2) is True
352 assert b'abc'.endswith(b'bc', 1) is True
353 assert b'abc'.endswith(b'bc', 2) is False
354 assert b'abc'.endswith(b'b', -3, -1) is True
352355
353356 def test_endswith_tuple(self):
354 assert not 'hello'.endswith(('he', 'ha'))
355 assert 'hello'.endswith(('lo', 'llo'))
356 assert 'hello'.endswith(('hellox', 'hello'))
357 assert not 'hello'.endswith(())
358 assert 'helloworld'.endswith(('hellowo', 'rld', 'lowo'), 3)
359 assert not 'helloworld'.endswith(('hellowo', 'ello', 'rld'), 3, -1)
360 assert 'hello'.endswith(('hell', 'ell'), 0, -1)
361 assert not 'hello'.endswith(('he', 'hel'), 0, 1)
362 assert 'hello'.endswith(('he', 'hell'), 0, 4)
363 raises(TypeError, 'hello'.endswith, (42,))
357 assert not b'hello'.endswith((b'he', b'ha'))
358 assert b'hello'.endswith((b'lo', b'llo'))
359 assert b'hello'.endswith((b'hellox', b'hello'))
360 assert not b'hello'.endswith(())
361 assert b'helloworld'.endswith((b'hellowo', b'rld', b'lowo'), 3)
362 assert not b'helloworld'.endswith((b'hellowo', b'ello', b'rld'), 3, -1)
363 assert b'hello'.endswith((b'hell', b'ell'), 0, -1)
364 assert not b'hello'.endswith((b'he', b'hel'), 0, 1)
365 assert b'hello'.endswith((b'he', b'hell'), 0, 4)
366 raises(TypeError, b'hello'.endswith, (42,))
364367
365368 def test_expandtabs(self):
366369 import sys
367370
368 assert 'abc\rab\tdef\ng\thi'.expandtabs() == 'abc\rab def\ng hi'
369 assert 'abc\rab\tdef\ng\thi'.expandtabs(8) == 'abc\rab def\ng hi'
370 assert 'abc\rab\tdef\ng\thi'.expandtabs(4) == 'abc\rab def\ng hi'
371 assert 'abc\r\nab\tdef\ng\thi'.expandtabs(4) == 'abc\r\nab def\ng hi'
372 assert 'abc\rab\tdef\ng\thi'.expandtabs() == 'abc\rab def\ng hi'
373 assert 'abc\rab\tdef\ng\thi'.expandtabs(8) == 'abc\rab def\ng hi'
374 assert 'abc\r\nab\r\ndef\ng\r\nhi'.expandtabs(4) == 'abc\r\nab\r\ndef\ng\r\nhi'
375
376 s = 'xy\t'
377 assert s.expandtabs() == 'xy '
378
379 s = '\txy\t'
380 assert s.expandtabs() == ' xy '
381 assert s.expandtabs(1) == ' xy '
382 assert s.expandtabs(2) == ' xy '
383 assert s.expandtabs(3) == ' xy '
384
385 assert 'xy'.expandtabs() == 'xy'
386 assert ''.expandtabs() == ''
387
388 raises(OverflowError, "t\tt\t".expandtabs, sys.maxint)
371 assert b'abc\rab\tdef\ng\thi'.expandtabs() == b'abc\rab def\ng hi'
372 assert b'abc\rab\tdef\ng\thi'.expandtabs(8) == b'abc\rab def\ng hi'
373 assert b'abc\rab\tdef\ng\thi'.expandtabs(4) == b'abc\rab def\ng hi'
374 assert b'abc\r\nab\tdef\ng\thi'.expandtabs(4) == b'abc\r\nab def\ng hi'
375 assert b'abc\rab\tdef\ng\thi'.expandtabs() == b'abc\rab def\ng hi'
376 assert b'abc\rab\tdef\ng\thi'.expandtabs(8) == b'abc\rab def\ng hi'
377 assert b'abc\r\nab\r\ndef\ng\r\nhi'.expandtabs(4) == b'abc\r\nab\r\ndef\ng\r\nhi'
378
379 s = b'xy\t'
380 assert s.expandtabs() == b'xy '
381
382 s = b'\txy\t'
383 assert s.expandtabs() == b' xy '
384 assert s.expandtabs(1) == b' xy '
385 assert s.expandtabs(2) == b' xy '
386 assert s.expandtabs(3) == b' xy '
387
388 assert b'xy'.expandtabs() == b'xy'
389 assert b''.expandtabs() == b''
390
391 raises(OverflowError, b"t\tt\t".expandtabs, sys.maxint)
389392
390393 def test_expandtabs_overflows_gracefully(self):
391394 import sys
392395 if sys.maxint > (1 << 32):
393396 skip("Wrong platform")
394 raises((MemoryError, OverflowError), 't\tt\t'.expandtabs, sys.maxint)
397 raises((MemoryError, OverflowError), b't\tt\t'.expandtabs, sys.maxint)
395398
396399 def test_expandtabs_0(self):
397400 assert 'x\ty'.expandtabs(0) == 'xy'
398401 assert 'x\ty'.expandtabs(-42) == 'xy'
399402
400403 def test_splitlines(self):
401 s = ""
404 s = b""
402405 assert s.splitlines() == []
403406 assert s.splitlines() == s.splitlines(1)
404 s = "a + 4"
405 assert s.splitlines() == ['a + 4']
407 s = b"a + 4"
408 assert s.splitlines() == [b'a + 4']
406409 # The following is true if no newline in string.
407410 assert s.splitlines() == s.splitlines(1)
408 s = "a + 4\nb + 2"
409 assert s.splitlines() == ['a + 4', 'b + 2']
410 assert s.splitlines(1) == ['a + 4\n', 'b + 2']
411 s="ab\nab\n \n x\n\n\n"
412 assert s.splitlines() ==['ab', 'ab', ' ', ' x', '', '']
411 s = b"a + 4\nb + 2"
412 assert s.splitlines() == [b'a + 4', b'b + 2']
413 assert s.splitlines(1) == [b'a + 4\n', b'b + 2']
414 s = b"ab\nab\n \n x\n\n\n"
415 assert s.splitlines() ==[b'ab', b'ab', b' ', b' x', b'', b'']
413416 assert s.splitlines() ==s.splitlines(0)
414 assert s.splitlines(1) ==['ab\n', 'ab\n', ' \n', ' x\n', '\n', '\n']
415 s="\none\n\two\nthree\n\n"
416 assert s.splitlines() ==['', 'one', '\two', 'three', '']
417 assert s.splitlines(1) ==['\n', 'one\n', '\two\n', 'three\n', '\n']
417 assert s.splitlines(1) ==[b'ab\n', b'ab\n', b' \n', b' x\n', b'\n', b'\n']
418 s = b"\none\n\two\nthree\n\n"
419 assert s.splitlines() ==[b'', b'one', b'\two', b'three', b'']
420 assert s.splitlines(1) ==[b'\n', b'one\n', b'\two\n', b'three\n', b'\n']
418421 # Split on \r and \r\n too
419 assert '12\r34\r\n56'.splitlines() == ['12', '34', '56']
420 assert '12\r34\r\n56'.splitlines(1) == ['12\r', '34\r\n', '56']
422 assert b'12\r34\r\n56'.splitlines() == [b'12', b'34', b'56']
423 assert b'12\r34\r\n56'.splitlines(1) == [b'12\r', b'34\r\n', b'56']
421424
422425 def test_find(self):
423 assert 'abcdefghiabc'.find('abc') == 0
424 assert 'abcdefghiabc'.find('abc', 1) == 9
425 assert 'abcdefghiabc'.find('def', 4) == -1
426 assert 'abcdef'.find('', 13) == -1
427 assert 'abcdefg'.find('def', 5, None) == -1
428 assert 'abcdef'.find('d', 6, 0) == -1
429 assert 'abcdef'.find('d', 3, 3) == -1
430 raises(TypeError, 'abcdef'.find, 'd', 1.0)
426 assert b'abcdefghiabc'.find(b'abc') == 0
427 assert b'abcdefghiabc'.find(b'abc', 1) == 9
428 assert b'abcdefghiabc'.find(b'def', 4) == -1
429 assert b'abcdef'.find(b'', 13) == -1
430 assert b'abcdefg'.find(b'def', 5, None) == -1
431 assert b'abcdef'.find(b'd', 6, 0) == -1
432 assert b'abcdef'.find(b'd', 3, 3) == -1
433 raises(TypeError, b'abcdef'.find, b'd', 1.0)
431434
432435 def test_index(self):
433436 from sys import maxint
434 assert 'abcdefghiabc'.index('') == 0
435 assert 'abcdefghiabc'.index('def') == 3
436 assert 'abcdefghiabc'.index('abc') == 0
437 assert 'abcdefghiabc'.index('abc', 1) == 9
438 assert 'abcdefghiabc'.index('def', -4*maxint, 4*maxint) == 3
439 assert 'abcdefgh'.index('def', 2, None) == 3
440 assert 'abcdefgh'.index('def', None, None) == 3
441 raises(ValueError, 'abcdefghiabc'.index, 'hib')
442 raises(ValueError, 'abcdefghiab'.index, 'abc', 1)
443 raises(ValueError, 'abcdefghi'.index, 'ghi', 8)
444 raises(ValueError, 'abcdefghi'.index, 'ghi', -1)
445 raises(TypeError, 'abcdefghijklmn'.index, 'abc', 0, 0.0)
446 raises(TypeError, 'abcdefghijklmn'.index, 'abc', -10.0, 30)
437 assert b'abcdefghiabc'.index(b'') == 0
438 assert b'abcdefghiabc'.index(b'def') == 3
439 assert b'abcdefghiabc'.index(b'abc') == 0
440 assert b'abcdefghiabc'.index(b'abc', 1) == 9
441 assert b'abcdefghiabc'.index(b'def', -4*maxint, 4*maxint) == 3
442 assert b'abcdefgh'.index(b'def', 2, None) == 3
443 assert b'abcdefgh'.index(b'def', None, None) == 3
444 raises(ValueError, b'abcdefghiabc'.index, b'hib')
445 raises(ValueError, b'abcdefghiab'.index, b'abc', 1)
446 raises(ValueError, b'abcdefghi'.index, b'ghi', 8)
447 raises(ValueError, b'abcdefghi'.index, b'ghi', -1)
448 raises(TypeError, b'abcdefghijklmn'.index, b'abc', 0, 0.0)
449 raises(TypeError, b'abcdefghijklmn'.index, b'abc', -10.0, 30)
447450
448451 def test_rfind(self):
449 assert 'abc'.rfind('', 4) == -1
450 assert 'abcdefghiabc'.rfind('abc') == 9
451 assert 'abcdefghiabc'.rfind('') == 12
452 assert 'abcdefghiabc'.rfind('abcd') == 0
453 assert 'abcdefghiabc'.rfind('abcz') == -1
454 assert 'abc'.rfind('', 0) == 3
455 assert 'abc'.rfind('', 3) == 3
456 assert 'abcdefgh'.rfind('def', 2, None) == 3
452 assert b'abc'.rfind(b'', 4) == -1
453 assert b'abcdefghiabc'.rfind(b'abc') == 9
454 assert b'abcdefghiabc'.rfind(b'') == 12
455 assert b'abcdefghiabc'.rfind(b'abcd') == 0
456 assert b'abcdefghiabc'.rfind(b'abcz') == -1
457 assert b'abc'.rfind(b'', 0) == 3
458 assert b'abc'.rfind(b'', 3) == 3
459 assert b'abcdefgh'.rfind(b'def', 2, None) == 3
457460
458461 def test_rindex(self):
459462 from sys import maxint
460 assert 'abcdefghiabc'.rindex('') == 12
461 assert 'abcdefghiabc'.rindex('def') == 3
462 assert 'abcdefghiabc'.rindex('abc') == 9
463 assert 'abcdefghiabc'.rindex('abc', 0, -1) == 0
464 assert 'abcdefghiabc'.rindex('abc', -4*maxint, 4*maxint) == 9
465 raises(ValueError, 'abcdefghiabc'.rindex, 'hib')
466 raises(ValueError, 'defghiabc'.rindex, 'def', 1)
467 raises(ValueError, 'defghiabc'.rindex, 'abc', 0, -1)
468 raises(ValueError, 'abcdefghi'.rindex, 'ghi', 0, 8)
469 raises(ValueError, 'abcdefghi'.rindex, 'ghi', 0, -1)
470 raises(TypeError, 'abcdefghijklmn'.rindex, 'abc', 0, 0.0)
471 raises(TypeError, 'abcdefghijklmn'.rindex, 'abc', -10.0, 30)
463 assert b'abcdefghiabc'.rindex(b'') == 12
464 assert b'abcdefghiabc'.rindex(b'def') == 3
465 assert b'abcdefghiabc'.rindex(b'abc') == 9
466 assert b'abcdefghiabc'.rindex(b'abc', 0, -1) == 0
467 assert b'abcdefghiabc'.rindex(b'abc', -4*maxint, 4*maxint) == 9
468 raises(ValueError, b'abcdefghiabc'.rindex, b'hib')
469 raises(ValueError, b'defghiabc'.rindex, b'def', 1)
470 raises(ValueError, b'defghiabc'.rindex, b'abc', 0, -1)
471 raises(ValueError, b'abcdefghi'.rindex, b'ghi', 0, 8)
472 raises(ValueError, b'abcdefghi'.rindex, b'ghi', 0, -1)
473 raises(TypeError, b'abcdefghijklmn'.rindex, b'abc', 0, 0.0)
474 raises(TypeError, b'abcdefghijklmn'.rindex, b'abc', -10.0, 30)
472475
473476
474477 def test_partition(self):
475478
476 assert ('this is the par', 'ti', 'tion method') == \
477 'this is the partition method'.partition('ti')
479 assert (b'this is the par', b'ti', b'tion method') == \
480 b'this is the partition method'.partition(b'ti')
478481
479482 # from raymond's original specification
480 S = 'http://www.python.org'
481 assert ('http', '://', 'www.python.org') == S.partition('://')
482 assert ('http://www.python.org', '', '') == S.partition('?')
483 assert ('', 'http://', 'www.python.org') == S.partition('http://')
484 assert ('http://www.python.', 'org', '') == S.partition('org')
485
486 raises(ValueError, S.partition, '')
483 S = b'http://www.python.org'
484 assert (b'http', b'://', b'www.python.org') == S.partition(b'://')
485 assert (b'http://www.python.org', b'', b'') == S.partition(b'?')
486 assert (b'', b'http://', b'www.python.org') == S.partition(b'http://')
487 assert (b'http://www.python.', b'org', b'') == S.partition(b'org')
488
489 raises(ValueError, S.partition, b'')
487490 raises(TypeError, S.partition, None)
488491
489492 def test_rpartition(self):
490493
491 assert ('this is the rparti', 'ti', 'on method') == \
492 'this is the rpartition method'.rpartition('ti')
494 assert (b'this is the rparti', b'ti', b'on method') == \
495 b'this is the rpartition method'.rpartition(b'ti')
493496
494497 # from raymond's original specification
495 S = 'http://www.python.org'
496 assert ('http', '://', 'www.python.org') == S.rpartition('://')
497 assert ('', '', 'http://www.python.org') == S.rpartition('?')
498 assert ('', 'http://', 'www.python.org') == S.rpartition('http://')
499 assert ('http://www.python.', 'org', '') == S.rpartition('org')
500
501 raises(ValueError, S.rpartition, '')
498 S = b'http://www.python.org'
499 assert (b'http', b'://', b'www.python.org') == S.rpartition(b'://')
500 assert (b'', b'', b'http://www.python.org') == S.rpartition(b'?')
501 assert (b'', b'http://', b'www.python.org') == S.rpartition(b'http://')
502 assert (b'http://www.python.', b'org', b'') == S.rpartition(b'org')
503
504 raises(ValueError, S.rpartition, b'')
502505 raises(TypeError, S.rpartition, None)
503506
504507 def test_split_maxsplit(self):
505 assert "/a/b/c".split('/', 2) == ['','a','b/c']
506 assert "a/b/c".split("/") == ['a', 'b', 'c']
507 assert " a ".split(None, 0) == ['a ']
508 assert " a ".split(None, 1) == ['a']
509 assert " a a ".split(" ", 0) == [' a a ']
510 assert " a a ".split(" ", 1) == ['', 'a a ']
508 assert b"/a/b/c".split(b'/', 2) == [b'',b'a',b'b/c']
509 assert b"a/b/c".split(b"/") == [b'a', b'b', b'c']
510 assert b" a ".split(None, 0) == [b'a ']
511 assert b" a ".split(None, 1) == [b'a']
512 assert b" a a ".split(b" ", 0) == [b' a a ']
513 assert b" a a ".split(b" ", 1) == [b'', b'a a ']
511514
512515 def test_join(self):
513 assert ", ".join(['a', 'b', 'c']) == "a, b, c"
514 assert "".join([]) == ""
515 assert "-".join(['a', 'b']) == 'a-b'
516 text = 'text'
517 assert "".join([text]) == text
518 assert " -- ".join([text]) is text
519 raises(TypeError, ''.join, 1)
520 raises(TypeError, ''.join, [1])
521 raises(TypeError, ''.join, [[1]])
516 assert b", ".join([b'a', b'b', b'c']) == b"a, b, c"
517 assert b"".join([]) == b""
518 assert b"-".join([b'a', b'b']) == b'a-b'
519 text = b'text'
520 assert b"".join([text]) is text
521 assert b" -- ".join([text]) is text
522 raises(TypeError, b''.join, 1)
523 raises(TypeError, b''.join, [1])
524 raises(TypeError, b''.join, [[1]])
522525
523526 def test_unicode_join_str_arg_ascii(self):
524527 raises(UnicodeDecodeError, u''.join, ['\xc3\xa1'])
575578 return unicode("fooled you!")
576579 return self.it.next()
577580
578 f = ('a\n', 'b\n', 'c\n')
581 f = (b'a\n', b'b\n', b'c\n')
579582 got = " - ".join(OhPhooey(f))
580583 assert got == unicode("a\n - b\n - fooled you! - c\n")
581584
582585 def test_lower(self):
583 assert "aaa AAA".lower() == "aaa aaa"
584 assert "".lower() == ""
586 assert b"aaa AAA".lower() == b"aaa aaa"
587 assert b"".lower() == b""
585588
586589 def test_upper(self):
587 assert "aaa AAA".upper() == "AAA AAA"
588 assert "".upper() == ""
590 assert b"aaa AAA".upper() == b"AAA AAA"
591 assert b"".upper() == b""
589592
590593 def test_isalnum(self):
591 assert "".isalnum() == False
592 assert "!Bro12345w&&&&n Fox".isalnum() == False
593 assert "125 Brown Foxes".isalnum() == False
594 assert "125BrownFoxes".isalnum() == True
594 assert b"".isalnum() == False
595 assert b"!Bro12345w&&&&n Fox".isalnum() == False
596 assert b"125 Brown Foxes".isalnum() == False
597 assert b"125BrownFoxes".isalnum() == True
595598
596599 def test_isalpha(self):
597 assert "".isalpha() == False
598 assert "!Bro12345w&&&&nFox".isalpha() == False
599 assert "Brown Foxes".isalpha() == False
600 assert "125".isalpha() == False
600 assert b"".isalpha() == False
601 assert b"!Bro12345w&&&&nFox".isalpha() == False
602 assert b"Brown Foxes".isalpha() == False
603 assert b"125".isalpha() == False
601604
602605 def test_isdigit(self):
603 assert "".isdigit() == False
604 assert "!Bro12345w&&&&nFox".isdigit() == False
605 assert "Brown Foxes".isdigit() == False
606 assert "125".isdigit() == True
606 assert b"".isdigit() == False
607 assert b"!Bro12345w&&&&nFox".isdigit() == False
608 assert b"Brown Foxes".isdigit() == False
609 assert b"125".isdigit() == True
607610
608611 def test_isspace(self):
609 assert "".isspace() == False
610 assert "!Bro12345w&&&&nFox".isspace() == False
611 assert " ".isspace() == True
612 assert "\t\t\b\b\n".isspace() == False
613 assert "\t\t".isspace() == True
614 assert "\t\t\r\r\n".isspace() == True
612 assert b"".isspace() == False
613 assert b"!Bro12345w&&&&nFox".isspace() == False
614 assert b" ".isspace() == True
615 assert b"\t\t\b\b\n".isspace() == False
616 assert b"\t\t".isspace() == True
617 assert b"\t\t\r\r\n".isspace() == True
615618
616619 def test_islower(self):
617 assert "".islower() == False
618 assert " ".islower() == False
619 assert "\t\t\b\b\n".islower() == False
620 assert "b".islower() == True
621 assert "bbb".islower() == True
622 assert "!bbb".islower() == True
623 assert "BBB".islower() == False
624 assert "bbbBBB".islower() == False
620 assert b"".islower() == False
621 assert b" ".islower() == False
622 assert b"\t\t\b\b\n".islower() == False
623 assert b"b".islower() == True
624 assert b"bbb".islower() == True
625 assert b"!bbb".islower() == True
626 assert b"BBB".islower() == False
627 assert b"bbbBBB".islower() == False
625628
626629 def test_isupper(self):
627 assert "".isupper() == False
628 assert " ".isupper() == False
629 assert "\t\t\b\b\n".isupper() == False
630 assert "B".isupper() == True
631 assert "BBB".isupper() == True
632 assert "!BBB".isupper() == True
633 assert "bbb".isupper() == False
634 assert "BBBbbb".isupper() == False
630 assert b"".isupper() == False
631 assert b" ".isupper() == False
632 assert b"\t\t\b\b\n".isupper() == False
633 assert b"B".isupper() == True
634 assert b"BBB".isupper() == True
635 assert b"!BBB".isupper() == True
636 assert b"bbb".isupper() == False
637 assert b"BBBbbb".isupper() == False
635638
636639
637640 def test_swapcase(self):
638 assert "aaa AAA 111".swapcase() == "AAA aaa 111"
639 assert "".swapcase() == ""
641 assert b"aaa AAA 111".swapcase() == b"AAA aaa 111"
642 assert b"".swapcase() == b""
640643
641644 def test_translate(self):
642645 def maketrans(origin, image):
649652 tbl = ''.join(L)
650653 return tbl
651654
652 table = maketrans('abc', 'xyz')
653 assert 'xyzxyz' == 'xyzabcdef'.translate(table, 'def')
655 table = maketrans(b'abc', b'xyz')
656 assert b'xyzxyz' == b'xyzabcdef'.translate(table, b'def')
654657 exc = raises(TypeError, "'xyzabcdef'.translate(memoryview(table), 'def')")
655658 assert str(exc.value) == 'expected a character buffer object'
656659
657 table = maketrans('a', 'A')
658 assert 'Abc' == 'abc'.translate(table)
659 assert 'xyz' == 'xyz'.translate(table)
660 assert 'yz' == 'xyz'.translate(table, 'x')
661
662 raises(ValueError, 'xyz'.translate, 'too short', 'strip')
663 raises(ValueError, 'xyz'.translate, 'too short')
664 raises(ValueError, 'xyz'.translate, 'too long'*33)
665
666 assert 'yz' == 'xyz'.translate(None, 'x') # 2.6
660 table = maketrans(b'a', b'A')
661 assert b'Abc' == b'abc'.translate(table)
662 assert b'xyz' == b'xyz'.translate(table)
663 assert b'yz' == b'xyz'.translate(table, b'x')
664
665 raises(ValueError, b'xyz'.translate, b'too short', b'strip')
666 raises(ValueError, b'xyz'.translate, b'too short')
667 raises(ValueError, b'xyz'.translate, b'too long'*33)
668
669 assert b'yz' == b'xyz'.translate(None, b'x') # 2.6
667670
668671 def test_iter(self):
669672 l=[]
670 for i in iter("42"):
673 for i in iter(b"42"):
671674 l.append(i)
672675 assert l == ['4','2']
673676
691694 assert repr(chr(2)) =="'\\x02'"
692695
693696 def test_contains(self):
694 assert '' in 'abc'
695 assert 'a' in 'abc'
696 assert 'ab' in 'abc'
697 assert not 'd' in 'abc'
697 assert b'' in b'abc'
698 assert b'a' in b'abc'
699 assert b'ab' in b'abc'
700 assert not b'd' in b'abc'
698701 raises(TypeError, 'a'.__contains__, 1)
699702
700703 def test_decode(self):
714717 assert hash('hello world!') & 0x7fffffff == 0x2f0bb411
715718
716719 def test_buffer(self):
717 x = "he"
718 x += "llo"
720 x = b"he"
721 x += b"llo"
719722 b = buffer(x)
720723 assert len(b) == 5
721724 assert b[-1] == "o"
722 assert b[:] == "hello"
723 assert b[1:0] == ""
725 assert b[:] == b"hello"
726 assert b[1:0] == b""
724727 raises(TypeError, "b[3] = 'x'")
725728
726729 def test_getnewargs(self):
727 assert "foo".__getnewargs__() == ("foo",)
730 assert b"foo".__getnewargs__() == (b"foo",)
728731
729732 def test_subclass(self):
730733 class S(str):
774777 import sys
775778 if sys.maxint > 2**31-1:
776779 skip("Wrong platform")
777 s = "a" * (2**16)
778 raises(OverflowError, s.replace, "", s)
780 s = b"a" * (2**16)
781 raises(OverflowError, s.replace, b"", s)
779782
780783 def test_getslice(self):
781784 assert "foobar".__getslice__(4, 4321) == "ar"
782 s = "abc"
783 assert s[:] == "abc"
784 assert s[1:] == "bc"
785 assert s[:2] == "ab"
786 assert s[1:2] == "b"
787 assert s[-2:] == "bc"
788 assert s[:-1] == "ab"
789 assert s[-2:2] == "b"
790 assert s[1:-1] == "b"
791 assert s[-2:-1] == "b"
785 s = b"abc"
786 assert s[:] == b"abc"
787 assert s[1:] == b"bc"
788 assert s[:2] == b"ab"
789 assert s[1:2] == b"b"
790 assert s[-2:] == b"bc"
791 assert s[:-1] == b"ab"
792 assert s[-2:2] == b"b"
793 assert s[1:-1] == b"b"
794 assert s[-2:-1] == b"b"
792795
793796 def test_no_len_on_str_iter(self):
794 iterable = "hello"
797 iterable = b"hello"
795798 raises(TypeError, len, iter(iterable))
796799
797800 def test___radd__(self):
126126 space = self.space
127127 w = space.wrap
128128
129 w_l = self.space.newlist([w("a"),w("b")])
129 w_l = space.newlist([w("a"),w("b")])
130130 w_l.getitems = None
131131 w_d = space.call_method(space.w_dict, "fromkeys", w_l)
132132
135135
136136 def test_listview_bytes_dict(self):
137137 w = self.space.wrap
138 wb = self.space.newbytes
138139 w_d = self.space.newdict()
139 w_d.initialize_content([(w("a"), w(1)), (w("b"), w(2))])
140 w_d.initialize_content([(wb("a"), w(1)), (wb("b"), w(2))])
140141 assert self.space.listview_bytes(w_d) == ["a", "b"]
141142
142143 def test_listview_unicode_dict(self):
153154
154155 def test_keys_on_string_unicode_int_dict(self, monkeypatch):
155156 w = self.space.wrap
156
157 wb = self.space.newbytes
158
157159 w_d = self.space.newdict()
158 w_d.initialize_content([(w(1), w("a")), (w(2), w("b"))])
160 w_d.initialize_content([(w(1), wb("a")), (w(2), wb("b"))])
159161 w_l = self.space.call_method(w_d, "keys")
160162 assert sorted(self.space.listview_int(w_l)) == [1,2]
161163
165167 monkeypatch.setattr(self.space, 'newlist', not_allowed)
166168 #
167169 w_d = self.space.newdict()
168 w_d.initialize_content([(w("a"), w(1)), (w("b"), w(6))])
170 w_d.initialize_content([(wb("a"), w(1)), (wb("b"), w(6))])
169171 w_l = self.space.call_method(w_d, "keys")
170172 assert sorted(self.space.listview_bytes(w_l)) == ["a", "b"]
171173
681683 s = "abc"
682684 setattr(a, s, 123)
683685 assert holder.seen is s
686
684687
685688 class AppTestDictViews:
686689 def test_dictview(self):
944947 helper(lambda x: x.viewkeys())
945948 helper(lambda x: x.viewitems())
946949
950 def test_contains(self):
951 logger = []
952
953 class Foo(object):
954
955 def __init__(self, value, name=None):
956 self.value = value
957 self.name = name or value
958
959 def __repr__(self):
960 return '<Foo %s>' % self.name
961
962 def __eq__(self, other):
963 logger.append((self, other))
964 return self.value == other.value
965
966 def __hash__(self):
967 return 42 # __eq__ will be used given all objects' hashes clash
968
969 foo1, foo2, foo3 = Foo(1), Foo(2), Foo(3)
970 foo42 = Foo(42)
971 foo_dict = {foo1: 1, foo2: 1, foo3: 1}
972 del logger[:]
973 foo42 in foo_dict
974 logger_copy = set(logger[:]) # prevent re-evaluation during pytest error print
975 assert logger_copy == {(foo3, foo42), (foo2, foo42), (foo1, foo42)}
976
977 del logger[:]
978 foo2_bis = Foo(2, '2 bis')
979 foo2_bis in foo_dict
980 logger_copy = set(logger[:]) # prevent re-evaluation during pytest error print
981 assert (foo2, foo2_bis) in logger_copy
982 assert logger_copy.issubset({(foo1, foo2_bis), (foo2, foo2_bis), (foo3, foo2_bis)})
983
984
947985 class AppTestStrategies(object):
948986 def setup_class(cls):
949987 if cls.runappdirect:
957995 def test_empty_to_string(self):
958996 d = {}
959997 assert "EmptyDictStrategy" in self.get_strategy(d)
960 d["a"] = 1
998 d[b"a"] = 1
961999 assert "BytesDictStrategy" in self.get_strategy(d)
9621000
9631001 class O(object):
88 assert 'a' in NotEmpty.__dict__
99 assert 'a' in NotEmpty.__dict__.keys()
1010 assert 'b' not in NotEmpty.__dict__
11 NotEmpty.__dict__['b'] = 4
12 assert NotEmpty.b == 4
13 del NotEmpty.__dict__['b']
1411 assert NotEmpty.__dict__.get("b") is None
12 raises(TypeError, "NotEmpty.__dict__['b'] = 4")
1513 raises(TypeError, 'NotEmpty.__dict__[15] = "y"')
16 raises(KeyError, 'del NotEmpty.__dict__[15]')
14 raises(TypeError, 'del NotEmpty.__dict__[15]')
1715
18 assert NotEmpty.__dict__.setdefault("string", 1) == 1
19 assert NotEmpty.__dict__.setdefault("string", 2) == 1
20 assert NotEmpty.string == 1
21 raises(TypeError, 'NotEmpty.__dict__.setdefault(15, 1)')
22
23 def test_dictproxy_popitem(self):
24 class A(object):
25 a = 42
26 seen = 0
27 try:
28 while True:
29 key, value = A.__dict__.popitem()
30 if key == 'a':
31 assert value == 42
32 seen += 1
33 except KeyError:
34 pass
35 assert seen == 1
16 raises(AttributeError, 'NotEmpty.__dict__.setdefault')
3617
3718 def test_dictproxy_getitem(self):
3819 class NotEmpty(object):
3920 a = 1
4021 assert 'a' in NotEmpty.__dict__
41 class substr(str): pass
22 class substr(str):
23 pass
4224 assert substr('a') in NotEmpty.__dict__
4325 assert u'a' in NotEmpty.__dict__
4426 assert NotEmpty.__dict__[u'a'] == 1
6143 class a(object):
6244 pass
6345 s1 = repr(a.__dict__)
46 assert s1.startswith('dict_proxy({') and s1.endswith('})')
6447 s2 = str(a.__dict__)
65 assert s1 == s2
66 assert s1.startswith('{') and s1.endswith('}')
48 assert s1 == 'dict_proxy(%s)' % s2
6749
6850 def test_immutable_dict_on_builtin_type(self):
6951 raises(TypeError, "int.__dict__['a'] = 1")
70 raises(TypeError, int.__dict__.popitem)
71 raises(TypeError, int.__dict__.clear)
52 raises((AttributeError, TypeError), "int.__dict__.popitem()")
53 raises((AttributeError, TypeError), "int.__dict__.clear()")
54
55 def test_dictproxy(self):
56 dictproxy = type(int.__dict__)
57 assert dictproxy is not dict
58 assert dictproxy.__name__ == 'dictproxy'
59 raises(TypeError, dictproxy)
60
61 mapping = {'a': 1}
62 raises(TypeError, dictproxy, mapping)
63
64 class A(object):
65 a = 1
66
67 proxy = A.__dict__
68 mapping = dict(proxy)
69 assert proxy['a'] == 1
70 assert 'a' in proxy
71 assert 'z' not in proxy
72 assert repr(proxy) == 'dict_proxy(%r)' % mapping
73 assert proxy.keys() == mapping.keys()
74 assert list(proxy.iterkeys()) == proxy.keys()
75 assert list(proxy.itervalues()) == proxy.values()
76 assert list(proxy.iteritems()) == proxy.items()
77 raises(TypeError, "proxy['a'] = 4")
78 raises(TypeError, "del proxy['a']")
79 raises(AttributeError, "proxy.clear()")
7280
7381 class AppTestUserObjectMethodCache(AppTestUserObject):
7482 spaceconfig = {"objspace.std.withmethodcachecounter": True}
75
294294 assert self.space.unwrap(result) == hex(x)
295295
296296
297 class AppTestInt:
297 class AppTestInt(object):
298 def test_hash(self):
299 assert hash(-1) == (-1).__hash__() == -2
300 assert hash(-2) == (-2).__hash__() == -2
301
298302 def test_conjugate(self):
299303 assert (1).conjugate() == 1
300304 assert (-1).conjugate() == -1
453457 return None
454458 inst = a()
455459 raises(TypeError, int, inst)
456 assert inst.ar == True
460 assert inst.ar == True
457461
458462 class b(object):
459 pass
460 raises((AttributeError,TypeError), int, b())
463 pass
464 raises((AttributeError,TypeError), int, b())
461465
462466 def test_special_long(self):
463467 class a(object):
9696 def test_no_len_on_xrange(self):
9797 iterable = xrange(10)
9898 raises(TypeError, len, iter(iterable))
99
100 def test_contains(self):
101 logger = []
102
103 class Foo(object):
104
105 def __init__(self, value, name=None):
106 self.value = value
107 self.name = name or value
108
109 def __repr__(self):
110 return '<Foo %s>' % self.name
111
112 def __eq__(self, other):
113 logger.append((self, other))
114 return self.value == other.value
115
116 foo1, foo2, foo3 = Foo(1), Foo(2), Foo(3)
117 foo42 = Foo(42)
118 foo_list = [foo1, foo2, foo3]
119 foo42 in (x for x in foo_list)
120 logger_copy = logger[:] # prevent re-evaluation during pytest error print
121 assert logger_copy == [(foo42, foo1), (foo42, foo2), (foo42, foo3)]
122
123 del logger[:]
124 foo2_bis = Foo(2, '2 bis')
125 foo2_bis in (x for x in foo_list)
126 logger_copy = logger[:] # prevent re-evaluation during pytest error print
127 assert logger_copy == [(foo2_bis, foo1), (foo2_bis, foo2)]
501501 assert not l.__contains__(-3)
502502 assert not l.__contains__(-20)
503503 assert not l.__contains__(-21)
504
505 logger = []
506
507 class Foo(object):
508
509 def __init__(self, value, name=None):
510 self.value = value
511 self.name = name or value
512
513 def __repr__(self):
514 return '<Foo %s>' % self.name
515
516 def __eq__(self, other):
517 logger.append((self, other))
518 return self.value == other.value
519
520 foo1, foo2, foo3 = Foo(1), Foo(2), Foo(3)
521 foo42 = Foo(42)
522 foo_list = [foo1, foo2, foo3]
523 foo42 in foo_list
524 logger_copy = logger[:] # prevent re-evaluation during pytest error print
525 assert logger_copy == [(foo42, foo1), (foo42, foo2), (foo42, foo3)]
526
527 del logger[:]
528 foo2_bis = Foo(2, '2 bis')
529 foo2_bis in foo_list
530 logger_copy = logger[:] # prevent re-evaluation during pytest error print
531 assert logger_copy == [(foo2_bis, foo1), (foo2_bis, foo2)]
504532
505533 def test_call_list(self):
506534 assert list('') == []
1212 def test_check_strategy(self):
1313 space = self.space
1414 w = space.wrap
15 wb = space.newbytes
1516 assert isinstance(W_ListObject(space, []).strategy, EmptyListStrategy)
16 assert isinstance(W_ListObject(space, [w(1),w('a')]).strategy, ObjectListStrategy)
17 assert isinstance(W_ListObject(space, [w(1),wb('a')]).strategy, ObjectListStrategy)
1718 assert isinstance(W_ListObject(space, [w(1),w(2),w(3)]).strategy,
1819 IntegerListStrategy)
19 assert isinstance(W_ListObject(space, [w('a'), w('b')]).strategy,
20 assert isinstance(W_ListObject(space, [wb('a'), wb('b')]).strategy,
2021 BytesListStrategy)
2122 assert isinstance(W_ListObject(space, [w(u'a'), w(u'b')]).strategy,
2223 UnicodeListStrategy)
23 assert isinstance(W_ListObject(space, [w(u'a'), w('b')]).strategy,
24 assert isinstance(W_ListObject(space, [w(u'a'), wb('b')]).strategy,
2425 ObjectListStrategy) # mixed unicode and bytes
2526
2627 def test_empty_to_any(self):
2728 space = self.space
2829 w = space.wrap
30 wb = space.newbytes
2931 l = W_ListObject(space, [])
3032 assert isinstance(l.strategy, EmptyListStrategy)
3133 l.append(w((1,3)))
3840
3941 l = W_ListObject(space, [])
4042 assert isinstance(l.strategy, EmptyListStrategy)
41 l.append(w('a'))
43 l.append(wb('a'))
4244 assert isinstance(l.strategy, BytesListStrategy)
4345
4446 l = W_ListObject(space, [])
6264
6365 def test_string_to_any(self):
6466 l = W_ListObject(self.space,
65 [self.space.wrap('a'),self.space.wrap('b'),self.space.wrap('c')])
67 [self.space.newbytes('a'), self.space.newbytes('b'),
68 self.space.newbytes('c')])
6669 assert isinstance(l.strategy, BytesListStrategy)
67 l.append(self.space.wrap('d'))
70 l.append(self.space.newbytes('d'))
6871 assert isinstance(l.strategy, BytesListStrategy)
6972 l.append(self.space.wrap(3))
7073 assert isinstance(l.strategy, ObjectListStrategy)
9093 def test_setitem(self):
9194 space = self.space
9295 w = space.wrap
96 wb = space.newbytes
9397 # This should work if test_listobject.py passes
9498 l = W_ListObject(space, [w('a'),w('b'),w('c')])
9599 assert space.eq_w(l.getitem(0), w('a'))
105109 assert isinstance(l.strategy, ObjectListStrategy)
106110
107111 # BytesStrategy to ObjectStrategy
108 l = W_ListObject(space, [w('a'),w('b'),w('c')])
112 l = W_ListObject(space, [wb('a'),wb('b'),wb('c')])
109113 assert isinstance(l.strategy, BytesListStrategy)
110114 l.setitem(0, w(2))
111115 assert isinstance(l.strategy, ObjectListStrategy)
125129 def test_insert(self):
126130 space = self.space
127131 w = space.wrap
132 wb = space.newbytes
128133 # no change
129134 l = W_ListObject(space, [w(1),w(2),w(3)])
130135 assert isinstance(l.strategy, IntegerListStrategy)
132137 assert isinstance(l.strategy, IntegerListStrategy)
133138
134139 # BytesStrategy
135 l = W_ListObject(space, [w('a'),w('b'),w('c')])
140 l = W_ListObject(space, [wb('a'),wb('b'),wb('c')])
136141 assert isinstance(l.strategy, BytesListStrategy)
137142 l.insert(3, w(2))
138143 assert isinstance(l.strategy, ObjectListStrategy)
158163 # EmptyStrategy
159164 l = W_ListObject(space, [])
160165 assert isinstance(l.strategy, EmptyListStrategy)
161 l.insert(0, w('a'))
166 l.insert(0, wb('a'))
162167 assert isinstance(l.strategy, BytesListStrategy)
163168
164169 l = W_ListObject(space, [])
186191 def test_setslice(self):
187192 space = self.space
188193 w = space.wrap
194 wb = space.newbytes
189195
190196 l = W_ListObject(space, [])
191197 assert isinstance(l.strategy, EmptyListStrategy)
211217 assert isinstance(l.strategy, ObjectListStrategy)
212218
213219 # BytesStrategy to ObjectStrategy
214 l = W_ListObject(space, [w('a'), w('b'), w('c')])
220 l = W_ListObject(space, [wb('a'), wb('b'), wb('c')])
215221 assert isinstance(l.strategy, BytesListStrategy)
216222 l.setslice(0, 1, 2, W_ListObject(space, [w(1), w(2), w(3)]))
217223 assert isinstance(l.strategy, ObjectListStrategy)
323329 def test_empty_extend_with_any(self):
324330 space = self.space
325331 w = space.wrap
332 wb = space.newbytes
326333
327334 empty = W_ListObject(space, [])
328335 assert isinstance(empty.strategy, EmptyListStrategy)
331338
332339 empty = W_ListObject(space, [])
333340 assert isinstance(empty.strategy, EmptyListStrategy)
334 empty.extend(W_ListObject(space, [w("a"), w("b"), w("c")]))
341 empty.extend(W_ListObject(space, [wb("a"), wb("b"), wb("c")]))
335342 assert isinstance(empty.strategy, BytesListStrategy)
336343
337344 empty = W_ListObject(space, [])
577584 assert not self.space.eq_w(l1, l2)
578585
579586 def test_weird_rangelist_bug(self):
580 l = make_range_list(self.space, 1, 1, 3)
587 space = self.space
588 l = make_range_list(space, 1, 1, 3)
581589 # should not raise
582 assert l.descr_getslice(self.space, self.space.wrap(15), self.space.wrap(2222)).strategy == self.space.fromcache(EmptyListStrategy)
590 w_slice = space.newslice(space.wrap(15), space.wrap(2222), space.wrap(1))
591 assert l.descr_getitem(space, w_slice).strategy == space.fromcache(EmptyListStrategy)
583592
584593 def test_add_to_rangelist(self):
585594 l1 = make_range_list(self.space, 1, 1, 3)
588597 assert self.space.eq_w(l3, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3), self.space.wrap(4), self.space.wrap(5)]))
589598
590599 def test_unicode(self):
591 l1 = W_ListObject(self.space, [self.space.wrap("eins"), self.space.wrap("zwei")])
600 l1 = W_ListObject(self.space, [self.space.newbytes("eins"), self.space.newbytes("zwei")])
592601 assert isinstance(l1.strategy, BytesListStrategy)
593 l2 = W_ListObject(self.space, [self.space.wrap(u"eins"), self.space.wrap(u"zwei")])
602 l2 = W_ListObject(self.space, [self.space.newunicode(u"eins"), self.space.newunicode(u"zwei")])
594603 assert isinstance(l2.strategy, UnicodeListStrategy)
595 l3 = W_ListObject(self.space, [self.space.wrap("eins"), self.space.wrap(u"zwei")])
604 l3 = W_ListObject(self.space, [self.space.newbytes("eins"), self.space.newunicode(u"zwei")])
596605 assert isinstance(l3.strategy, ObjectListStrategy)
597606
598607 def test_listview_bytes(self):
599608 space = self.space
600609 assert space.listview_bytes(space.wrap(1)) == None
601 w_l = self.space.newlist([self.space.wrap('a'), self.space.wrap('b')])
610 w_l = self.space.newlist([self.space.newbytes('a'), self.space.newbytes('b')])
602611 assert space.listview_bytes(w_l) == ["a", "b"]
603612
604613 def test_listview_unicode(self):
640649
641650 def test_string_uses_newlist_bytes(self):
642651 space = self.space
643 w_s = space.wrap("a b c")
652 w_s = space.newbytes("a b c")
644653 space.newlist = None
645654 try:
646655 w_l = space.call_method(w_s, "split")
647 w_l2 = space.call_method(w_s, "split", space.wrap(" "))
656 w_l2 = space.call_method(w_s, "split", space.newbytes(" "))
648657 w_l3 = space.call_method(w_s, "rsplit")
649 w_l4 = space.call_method(w_s, "rsplit", space.wrap(" "))
658 w_l4 = space.call_method(w_s, "rsplit", space.newbytes(" "))
650659 finally:
651660 del space.newlist
652661 assert space.listview_bytes(w_l) == ["a", "b", "c"]
706715
707716 def test_listview_bytes_list(self):
708717 space = self.space
709 w_l = W_ListObject(space, [space.wrap("a"), space.wrap("b")])
718 w_l = W_ListObject(space, [space.newbytes("a"), space.newbytes("b")])
710719 assert self.space.listview_bytes(w_l) == ["a", "b"]
711720
712721 def test_listview_unicode_list(self):
10331042 assert [(type(x), x) for x in space.unwrap(w_l)] == [
10341043 (int, 5), (float, 1.2), (int, 1), (float, 1.0)]
10351044
1045 def test_stringstrategy_wraps_bytes(self):
1046 space = self.space
1047 wb = space.newbytes
1048 l = W_ListObject(space, [wb('a'), wb('b')])
1049 w_item = l.getitem(0)
1050 assert isinstance(w_item, space.StringObjectCls)
1051
10361052
10371053 class TestW_ListStrategiesDisabled:
10381054 spaceconfig = {"objspace.std.withliststrategies": False}
227227 def test_hash(self):
228228 # ints have the same hash as equal longs
229229 for i in range(-4, 14):
230 assert hash(i) == hash(long(i))
230 assert hash(i) == hash(long(i)) == long(i).__hash__()
231231 # might check too much -- it's ok to change the hashing algorithm
232232 assert hash(123456789L) == 123456789
233233 assert hash(1234567890123456789L) in (
12161216 got = x.a
12171217 assert got == 'd'
12181218
1219 def test_bug_builtin_types_callmethod(self):
1220 import sys
1221 class D(type(sys)):
1222 def mymethod(self):
1223 return "mymethod"
1224
1225 def foobar():
1226 return "foobar"
1227
1228 d = D('d')
1229 res1 = d.mymethod()
1230 d.mymethod = foobar
1231 res2 = d.mymethod()
1232 assert res1 == "mymethod"
1233 assert res2 == "foobar"
1234
1235 def test_bug_builtin_types_load_attr(self):
1236 import sys
1237 class D(type(sys)):
1238 def mymethod(self):
1239 return "mymethod"
1240
1241 def foobar():
1242 return "foobar"
1243
1244 d = D('d')
1245 m = d.mymethod
1246 res1 = m()
1247 d.mymethod = foobar
1248 m = d.mymethod
1249 res2 = m()
1250 assert res1 == "mymethod"
1251 assert res2 == "foobar"
1252
1253
1254
12191255 class AppTestGlobalCaching(AppTestWithMapDict):
12201256 spaceconfig = {"objspace.std.withmethodcachecounter": True}
12211257
185185 def test_id_on_strs(self):
186186 if self.appdirect:
187187 skip("cannot run this test as apptest")
188 u = u"a"
189 assert id(self.unwrap_wrap_unicode(u)) == id(u)
190 s = "a"
191 assert id(self.unwrap_wrap_str(s)) == id(s)
188 for u in [u"", u"a", u"aa"]:
189 assert id(self.unwrap_wrap_unicode(u)) == id(u)
190 s = str(u)
191 assert id(self.unwrap_wrap_str(s)) == id(s)
192 #
193 assert id('') == (256 << 4) | 11 # always
194 assert id(u'') == (257 << 4) | 11
195 assert id('a') == (ord('a') << 4) | 11
196 assert id(u'\u1234') == ((~0x1234) << 4) | 11
197
198 def test_id_of_tuples(self):
199 l = []
200 x = (l,)
201 assert id(x) != id((l,)) # no caching at all
202 if self.appdirect:
203 skip("cannot run this test as apptest")
204 assert id(()) == (258 << 4) | 11 # always
205
206 def test_id_of_frozensets(self):
207 x = frozenset([4])
208 assert id(x) != id(frozenset([4])) # no caching at all
209 if self.appdirect:
210 skip("cannot run this test as apptest")
211 assert id(frozenset()) == (259 << 4) | 11 # always
212 assert id(frozenset([])) == (259 << 4) | 11 # always
192213
193214 def test_identity_vs_id_primitives(self):
194 if self.cpython_apptest:
195 skip("cpython behaves differently")
196 import sys
197 l = range(-10, 10)
198 for i in range(10):
215 import sys
216 l = range(-10, 10, 2)
217 for i in [0, 1, 3]:
199218 l.append(float(i))
200219 l.append(i + 0.1)
201220 l.append(long(i))
205224 l.append(i - 1j)
206225 l.append(1 + i * 1j)
207226 l.append(1 - i * 1j)
208 s = str(i)
209 l.append(s)
210 u = unicode(s)
211 l.append(u)
227 l.append((i,))
228 l.append(frozenset([i]))
212229 l.append(-0.0)
213230 l.append(None)
214231 l.append(True)
215232 l.append(False)
216 s = "s"
217 l.append(s)
218 s = u"s"
219 l.append(s)
233 l.append(())
234 l.append(tuple([]))
235 l.append(frozenset())
220236
221237 for i, a in enumerate(l):
222238 for b in l[i:]:
227243 def test_identity_vs_id_str(self):
228244 if self.appdirect:
229245 skip("cannot run this test as apptest")
230 import sys
231 l = range(-10, 10)
232 for i in range(10):
233 s = str(i)
246 l = []
247 def add(s, u):
234248 l.append(s)
235249 l.append(self.unwrap_wrap_str(s))
236 u = unicode(s)
250 l.append(s[:1] + s[1:])
237251 l.append(u)
238252 l.append(self.unwrap_wrap_unicode(u))
239 s = "s"
240 l.append(s)
241 l.append(self.unwrap_wrap_str(s))
242 s = u"s"
243 l.append(s)
244 l.append(self.unwrap_wrap_unicode(s))
253 l.append(u[:1] + u[1:])
254 for i in range(3, 18):
255 add(str(i), unicode(i))
256 add("s", u"s")
257 add("", u"")
245258
246259 for i, a in enumerate(l):
247260 for b in l[i:]:
0 import pytest
1 import sys
2 from pypy.tool.pytest.objspace import gettestobjspace
3 try:
4 from hypothesis import given, strategies, settings
5 except ImportError:
6 pytest.skip("requires hypothesis")
7
8 base_initargs = strategies.sampled_from([
9 ("object", (), False),
10 ("type(sys)", ("fake", ), True),
11 ("NewBase", (), True),
12 ("OldBase", (), False),
13 ("object, OldBase", (), False),
14 ("type(sys), OldBase", ("fake", ), True),
15 ])
16
17 attrnames = strategies.sampled_from(["a", "b", "c"])
18
19 @strategies.composite
20 def make_code(draw):
21 # now here we can do this kind of thing:
22 baseclass, initargs, hasdict = draw(base_initargs)
23 # and with arbitrary strategies
24
25 def class_attr():
26 what = draw(strategies.sampled_from(["value", "method", "property"]))
27 if what == "value":
28 val = draw(strategies.integers())
29 return val, str(val)
30 if what == "method":
31 val = draw(strategies.integers())
32 return (lambda self, val=val: val,
33 "lambda self: %d" % val)
34 if what == "property":
35 val = draw(strategies.integers())
36 return (property(lambda self, val=val: val,
37 lambda self, val: None,
38 lambda self: None),
39 "property(lambda self: %d, lambda self, val: None, lambda self: None)" % val)
40
41 code = ["import sys", "class OldBase:pass", "class NewBase(object):pass", "class A(%s):" % baseclass]
42 dct = {}
43 if draw(strategies.booleans()):
44 slots = draw(strategies.lists(attrnames))
45 if not hasdict and draw(strategies.booleans()):
46 slots.append("__dict__")
47 dct["__slots__"] = slots
48 code.append(" __slots__ = %s" % (slots, ))
49 for name in ["a", "b", "c"]:
50 if not draw(strategies.booleans()):
51 continue
52 dct[name], codeval = class_attr()
53 code.append(" %s = %s" % (name, codeval))
54 class OldBase: pass
55 class NewBase(object): pass
56 evaldct = {'OldBase': OldBase, 'NewBase': NewBase}
57 if baseclass == 'OldBase':
58 metaclass = type(OldBase)
59 else:
60 metaclass = type
61 cls = metaclass("A", eval(baseclass+',', globals(), evaldct), dct)
62 inst = cls(*initargs)
63 code.append(" pass")
64 code.append("a = A(*%s)" % (initargs, ))
65 for attr in draw(strategies.lists(attrnames, min_size=1)):
66 op = draw(strategies.sampled_from(["read", "read", "read",
67 "write", "writemeth", "writeclass", "writebase",
68 "del", "delclass"]))
69 if op == "read":
70 try:
71 res = getattr(inst, attr)
72 except AttributeError:
73 code.append("raises(AttributeError, 'a.%s')" % (attr, ))
74 else:
75 if callable(res):
76 code.append("assert a.%s() == %s" % (attr, res()))
77 else:
78 code.append("assert a.%s == %s" % (attr, res))
79 elif op == "write":
80 val = draw(strategies.integers())
81 try:
82 setattr(inst, attr, val)
83 except AttributeError:
84 code.append("raises(AttributeError, 'a.%s=%s')" % (attr, val))
85 else:
86 code.append("a.%s = %s" % (attr, val))
87 elif op == "writemeth":
88 val = draw(strategies.integers())
89 try:
90 setattr(inst, attr, lambda val=val: val)
91 except AttributeError:
92 code.append("raises(AttributeError, 'a.%s=0')" % (attr, ))
93 else:
94 code.append("a.%s = lambda : %s" % (attr, val))
95 elif op == "writeclass":
96 val, codeval = class_attr()
97 setattr(cls, attr, val)
98 code.append("A.%s = %s" % (attr, codeval))
99 elif op == "writebase":
100 val, codeval = class_attr()
101 setattr(OldBase, attr, val)
102 setattr(NewBase, attr, val)
103 code.append("OldBase.%s = NewBase.%s = %s" % (attr, attr , codeval))
104 elif op == "del":
105 try:
106 delattr(inst, attr)
107 except AttributeError:
108 code.append("raises(AttributeError, 'del a.%s')" % (attr, ))
109 else:
110 code.append("del a.%s" % (attr, ))
111 elif op == "delclass":
112 try:
113 delattr(cls, attr)
114 except AttributeError:
115 code.append("raises(AttributeError, 'del A.%s')" % (attr, ))
116 else:
117 code.append("del A.%s" % (attr, ))
118 return "\n ".join(code)
119
120
121 @given(make_code())
122 #@settings(max_examples=5000)
123 def test_random_attrs(code):
124 try:
125 import __pypy__
126 except ImportError:
127 pass
128 else:
129 pytest.skip("makes no sense under pypy!")
130 space = gettestobjspace()
131 print code
132 exec "if 1:\n " + code
133 space.appexec([], "():\n " + code)
8383 from pypy.objspace.std.floatobject import W_FloatObject
8484
8585 w = self.space.wrap
86 wb = self.space.newbytes
8687 intstr = self.space.fromcache(IntegerSetStrategy)
8788 tmp_func = intstr.get_storage_from_list
8889 # test if get_storage_from_list is no longer used
9495 assert w_set.strategy is intstr
9596 assert intstr.unerase(w_set.sstorage) == {1:None, 2:None, 3:None}
9697
97 w_list = W_ListObject(self.space, [w("1"), w("2"), w("3")])
98 w_list = W_ListObject(self.space, [wb("1"), wb("2"), wb("3")])
9899 w_set = W_SetObject(self.space)
99100 _initialize_set(self.space, w_set, w_list)
100101 assert w_set.strategy is self.space.fromcache(BytesSetStrategy)
125126
126127 def test_listview_bytes_int_on_set(self):
127128 w = self.space.wrap
129 wb = self.space.newbytes
128130
129131 w_a = W_SetObject(self.space)
130 _initialize_set(self.space, w_a, w("abcdefg"))
132 _initialize_set(self.space, w_a, wb("abcdefg"))
131133 assert sorted(self.space.listview_bytes(w_a)) == list("abcdefg")
132134 assert self.space.listview_int(w_a) is None
133135
438440 self.s = s
439441 def __repr__(self):
440442 return repr(self.s)
441
443
442444 s = set([1, 2, 3])
443445 s.add(A(s))
444446 therepr = repr(s)
459461 assert therepr.endswith("])")
460462 inner = set(therepr[11:-2].split(", "))
461463 assert inner == set(["1", "2", "3", "frozenset(...)"])
462
464
463465 def test_keyerror_has_key(self):
464466 s = set()
465467 try:
476478 return int(id(self) & 0x7fffffff)
477479 s = H()
478480 f = set([s])
479 print f
481 print(f)
480482 assert s in f
481483 f.remove(s)
482484 f.add(s)
528530 for c in letters:
529531 assert (c in s) == (c in word)
530532 raises(TypeError, s.__contains__, [])
533
534 logger = []
535
536 class Foo(object):
537
538 def __init__(self, value, name=None):
539 self.value = value
540 self.name = name or value
541
542 def __repr__(self):
543 return '<Foo %s>' % self.name
544
545 def __eq__(self, other):
546 logger.append((self, other))
547 return self.value == other.value
548
549 def __hash__(self):
550 return 42 # __eq__ will be used given all objects' hashes clash
551
552 foo1, foo2, foo3 = Foo(1), Foo(2), Foo(3)
553 foo42 = Foo(42)
554 foo_set = {foo1, foo2, foo3}
555 del logger[:]
556 foo42 in foo_set
557 logger_copy = set(logger[:]) # prevent re-evaluation during pytest error print
558 assert logger_copy == {(foo3, foo42), (foo2, foo42), (foo1, foo42)}
559
560 del logger[:]
561 foo2_bis = Foo(2, '2 bis')
562 foo2_bis in foo_set
563 logger_copy = set(logger[:]) # prevent re-evaluation during pytest error print
564 assert (foo2, foo2_bis) in logger_copy
565 assert logger_copy.issubset({(foo1, foo2_bis), (foo2, foo2_bis), (foo3, foo2_bis)})
531566
532567 def test_remove(self):
533568 s = set('abc')
552587 assert v1 == v2
553588 else:
554589 assert False, 'Expected KeyError'
555
590
556591 def test_singleton_empty_frozenset(self):
557592 class Frozenset(frozenset):
558593 pass
176176
177177 assert hash(a) == hash((1L, 2L)) == hash((1.0, 2.0)) == hash((1.0, 2L))
178178
179 x = (-1, -1)
180 y = tuple([-1, -1])
181 assert hash(x) == hash(y)
182
179183 def test_getitem(self):
180184 t = (5, 3)
181185 assert (t)[0] == 5
6565
6666 def test_wrap_various_unsigned_types(self):
6767 import sys
68 from rpython.rlib.rarithmetic import r_uint
6869 from rpython.rtyper.lltypesystem import lltype, rffi
6970 space = self.space
7071 value = sys.maxint * 2
71 x = rffi.cast(lltype.Unsigned, value)
72 x = r_uint(value)
7273 assert space.eq_w(space.wrap(value), space.wrap(x))
73 x = rffi.cast(rffi.UINTPTR_T, value)
74 x = rffi.cast(rffi.UINTPTR_T, r_uint(value))
7475 assert x > 0
7576 assert space.eq_w(space.wrap(value), space.wrap(x))
7677 value = 60000
77 x = rffi.cast(rffi.USHORT, value)
78 x = rffi.cast(rffi.USHORT, r_uint(value))
7879 assert space.eq_w(space.wrap(value), space.wrap(x))
7980 value = 200
80 x = rffi.cast(rffi.UCHAR, value)
81 x = rffi.cast(rffi.UCHAR, r_uint(value))
8182 assert space.eq_w(space.wrap(value), space.wrap(x))
267267 assert 99 in t
268268 assert not 11 in t
269269 assert not t in t
270
271 logger = []
272
273 class Foo(object):
274
275 def __init__(self, value, name=None):
276 self.value = value
277 self.name = name or value
278
279 def __repr__(self):
280 return '<Foo %s>' % self.name
281
282 def __eq__(self, other):
283 logger.append((self, other))
284 return self.value == other.value
285
286 foo1, foo2, foo3 = Foo(1), Foo(2), Foo(3)
287 foo42 = Foo(42)
288 foo_tuple = (foo1, foo2, foo3)
289 foo42 in foo_tuple
290 logger_copy = logger[:] # prevent re-evaluation during pytest error print
291 assert logger_copy == [(foo42, foo1), (foo42, foo2), (foo42, foo3)]
292
293 del logger[:]
294 foo2_bis = Foo(2, '2 bis')
295 foo2_bis in foo_tuple
296 logger_copy = logger[:] # prevent re-evaluation during pytest error print
297 assert logger_copy == [(foo2_bis, foo1), (foo2_bis, foo2)]
270298
271299 def test_add(self):
272300 t0 = ()
967967 raises(TypeError, setattr, list, 'foobar', 42)
968968 raises(TypeError, delattr, dict, 'keys')
969969 raises(TypeError, 'int.__dict__["a"] = 1')
970 raises(TypeError, 'int.__dict__.clear()')
971970
972971 def test_nontype_in_mro(self):
973972 class OldStyle:
10251024 pass
10261025
10271026 a = A()
1027 d = A.__dict__
10281028 A.x = 1
1029 assert A.__dict__["x"] == 1
1030 A.__dict__['x'] = 5
1031 assert A.x == 5
1029 assert d["x"] == 1
10321030
10331031 def test_we_already_got_one_1(self):
10341032 # Issue #2079: highly obscure: CPython complains if we say
10891087 __metaclass__ = X
10901088 C() # the lookup of '__new__' succeeds in 'int',
10911089 # but the lookup of '__init__' fails
1090
1091 def test_instancecheck(self):
1092 assert int.__instancecheck__(42) is True
1093 assert int.__instancecheck__(42.0) is False
1094 class Foo:
1095 __class__ = int
1096 assert int.__instancecheck__(Foo()) is False
1097 class Bar(object):
1098 __class__ = int
1099 assert int.__instancecheck__(Bar()) is True
1100
1101 def test_subclasscheck(self):
1102 assert int.__subclasscheck__(bool) is True
1103 assert int.__subclasscheck__(float) is False
1104 class Foo:
1105 __class__ = int
1106 assert int.__subclasscheck__(Foo) is False
1107 class Bar(object):
1108 __class__ = int
1109 assert int.__subclasscheck__(Bar) is False
1110 class AbstractClass(object):
1111 __bases__ = (int,)
1112 assert int.__subclasscheck__(AbstractClass()) is True
10921113
10931114
10941115 class AppTestWithMethodCacheCounter:
12891310 assert not self.compares_by_identity(X)
12901311 del X.__eq__
12911312 assert self.compares_by_identity(X)
1292
1293
88 from pypy.interpreter.typedef import TypeDef
99 from pypy.objspace.std.sliceobject import (W_SliceObject, unwrap_start_stop,
1010 normalize_simple_slice)
11 from pypy.objspace.std.util import negate
11 from pypy.objspace.std.util import negate, IDTAG_SPECIAL, IDTAG_SHIFT
1212 from rpython.rlib import jit
1313 from rpython.rlib.debug import make_sure_not_resized
1414 from rpython.rlib.rarithmetic import intmask
3636
3737 class W_AbstractTupleObject(W_Root):
3838 __slots__ = ()
39
40 def is_w(self, space, w_other):
41 if not isinstance(w_other, W_AbstractTupleObject):
42 return False
43 if self is w_other:
44 return True
45 if self.user_overridden_class or w_other.user_overridden_class:
46 return False
47 # empty tuples are unique-ified
48 return 0 == w_other.length() == self.length()
49
50 def immutable_unique_id(self, space):
51 if self.user_overridden_class or self.length() > 0:
52 return None
53 # empty tuple: base value 258
54 uid = (258 << IDTAG_SHIFT) | IDTAG_SPECIAL
55 return space.wrap(uid)
3956
4057 def __repr__(self):
4158 """representation for debugging purposes"""
135152 @jit.unroll_safe
136153 def _descr_contains_unroll_safe(self, space, w_obj):
137154 for w_item in self.tolist():
138 if space.eq_w(w_item, w_obj):
155 if space.eq_w(w_obj, w_item):
139156 return space.w_True
140157 return space.w_False
141158
143160 tp = space.type(w_obj)
144161 for w_item in self.tolist():
145162 contains_jmp.jit_merge_point(tp=tp)
146 if space.eq_w(w_item, w_obj):
163 if space.eq_w(w_obj, w_item):
147164 return space.w_True
148165 return space.w_False
149166
22 from pypy.interpreter.baseobjspace import W_Root, SpaceCache
33 from pypy.interpreter.error import OperationError, oefmt
44 from pypy.interpreter.function import Function, StaticMethod
5 from pypy.interpreter.typedef import weakref_descr, GetSetProperty,\
6 descr_get_dict, dict_descr, Member, TypeDef
5 from pypy.interpreter.typedef import (
6 weakref_descr, GetSetProperty, dict_descr, Member, TypeDef)
77 from pypy.interpreter.astcompiler.misc import mangle
8 from pypy.module.__builtin__ import abstractinst
89
910 from rpython.rlib.jit import (promote, elidable_promote, we_are_jitted,
1011 elidable, dont_look_inside, unroll_safe)
344345 def deldictvalue(self, space, key):
345346 if self.lazyloaders:
346347 self._cleanup_() # force un-lazification
347 if not self.is_heaptype():
348 if not (self.is_heaptype() or self.is_cpytype()):
348349 raise oefmt(space.w_TypeError,
349350 "can't delete attributes on type object '%N'", self)
350351 try:
483484 self.getdictvalue(self.space, attr)
484485 del self.lazyloaders
485486
486 def getdict(self, space): # returning a dict-proxy!
487 from pypy.objspace.std.dictproxyobject import DictProxyStrategy
487 def getdict(self, space):
488 from pypy.objspace.std.classdict import ClassDictStrategy
488489 from pypy.objspace.std.dictmultiobject import W_DictObject
489490 if self.lazyloaders:
490491 self._cleanup_() # force un-lazification
491 strategy = space.fromcache(DictProxyStrategy)
492 strategy = space.fromcache(ClassDictStrategy)
492493 storage = strategy.erase(self)
493494 return W_DictObject(space, strategy, storage)
494495
898899
899900 # ____________________________________________________________
900901
901 @gateway.unwrap_spec(w_obj=W_TypeObject, w_sub=W_TypeObject)
902 @gateway.unwrap_spec(w_obj=W_TypeObject)
902903 def type_issubtype(w_obj, space, w_sub):
903 return space.newbool(w_sub.issubtype(w_obj))
904 return space.newbool(
905 abstractinst.p_recursive_issubclass_w(space, w_sub, w_obj))
904906
905907 @gateway.unwrap_spec(w_obj=W_TypeObject)
906908 def type_isinstance(w_obj, space, w_inst):
907 return space.newbool(space.type(w_inst).issubtype(w_obj))
909 return space.newbool(
910 abstractinst.p_recursive_isinstance_type_w(space, w_inst, w_obj))
911
912 def type_get_dict(space, w_cls):
913 w_cls = _check(space, w_cls)
914 from pypy.objspace.std.dictproxyobject import W_DictProxyObject
915 w_dict = w_cls.getdict(space)
916 if w_dict is None:
917 return space.w_None
918 return W_DictProxyObject(w_dict)
908919
909920 W_TypeObject.typedef = TypeDef("type",
910921 __new__ = gateway.interp2app(descr__new__),
912923 __bases__ = GetSetProperty(descr_get__bases__, descr_set__bases__),
913924 __base__ = GetSetProperty(descr__base),
914925 __mro__ = GetSetProperty(descr_get__mro__),
915 __dict__ = GetSetProperty(descr_get_dict),
926 __dict__=GetSetProperty(type_get_dict),
916927 __doc__ = GetSetProperty(descr__doc),
917928 mro = gateway.interp2app(descr_mro),
918929 __flags__ = GetSetProperty(descr__flags),
1717 from pypy.objspace.std.basestringtype import basestring_typedef
1818 from pypy.objspace.std.formatting import mod_format
1919 from pypy.objspace.std.stringmethods import StringMethods
20 from pypy.objspace.std.util import IDTAG_SPECIAL, IDTAG_SHIFT
2021
2122 __all__ = ['W_UnicodeObject', 'wrapunicode', 'plain_str2unicode',
2223 'encode_object', 'decode_object', 'unicode_from_object',
5152 return True
5253 if self.user_overridden_class or w_other.user_overridden_class:
5354 return False
54 return space.unicode_w(self) is space.unicode_w(w_other)
55 s1 = space.unicode_w(self)
56 s2 = space.unicode_w(w_other)
57 if len(s2) > 1:
58 return s1 is s2
59 else: # strings of len <= 1 are unique-ified
60 return s1 == s2
5561
5662 def immutable_unique_id(self, space):
5763 if self.user_overridden_class:
5864 return None
59 return space.wrap(compute_unique_id(space.unicode_w(self)))
65 s = space.unicode_w(self)
66 if len(s) > 1:
67 uid = compute_unique_id(s)
68 else: # strings of len <= 1 are unique-ified
69 if len(s) == 1:
70 base = ~ord(s[0]) # negative base values
71 else:
72 base = 257 # empty unicode string: base value 257
73 uid = (base << IDTAG_SHIFT) | IDTAG_SPECIAL
74 return space.wrap(uid)
6075
6176 def str_w(self, space):
6277 return space.str_w(space.str(self))
88 IDTAG_FLOAT = 5
99 IDTAG_COMPLEX = 7
1010 IDTAG_METHOD = 9
11 IDTAG_SPECIAL = 11 # -1 - (-maxunicode-1): unichar
12 # 0 - 255: char
13 # 256: empty string
14 # 257: empty unicode
15 # 258: empty tuple
16 # 259: empty frozenset
1117
1218 CMP_OPS = dict(lt='<', le='<=', eq='==', ne='!=', gt='>', ge='>=')
1319 BINARY_BITWISE_OPS = {'and': '&', 'lshift': '<<', 'or': '|', 'rshift': '>>',
140140 return myint(15)
141141 assert hash(I()) == 15
142142 assert type(hash(I())) is int
143
144 # check hashing of -1 to -2
145 class myint(int):
146 pass
147 class mylong(long):
148 pass
149 class myfloat(float):
150 pass
151 class myHashClass(object):
152 def __hash__(self):
153 return -1
154 class myHashClass2(object):
155 def __hash__(self):
156 return -1L
157 class myHashClass3(object):
158 def __hash__(self):
159 return -10**100
160
161 assert hash(-1) == -2
162 assert hash(-1L) == -2
163 assert hash(-1.0) == -2
164 assert hash(-1 + 0j) == -2
165 assert hash(myint(-1)) == -2
166 assert hash(mylong(-1)) == -2
167 assert hash(myfloat(-1.0)) == -2
168 assert hash(myHashClass()) == -2
169 assert hash(myHashClass2()) == -2
170 assert hash(myHashClass3()) == hash(-10**100)
1212 from pypy.interpreter.function import Method
1313 from pypy.tool.pytest import appsupport
1414 from pypy.tool.pytest.objspace import gettestobjspace
15 from pypy.conftest import PyPyClassCollector
1615 from inspect import getmro
1716
1817
2019 def __init__(self, excinfo):
2120 self.excinfo = excinfo
2221
23 marker = py.test.mark.applevel
2422
2523 class AppTestFunction(py.test.collect.Function):
26 def __init__(self, *args, **kwargs):
27 super(AppTestFunction, self).__init__(*args, **kwargs)
28 self._request.applymarker(marker)
29
3024 def _prunetraceback(self, traceback):
3125 return traceback
3226
121115 self.w_instance = space.call_function(w_class)
122116
123117
124 class AppClassCollector(PyPyClassCollector):
118 class AppClassCollector(py.test.Class):
125119 Instance = AppClassInstance
126120
127121 def setup(self):
1616 resultwc = py.path.svnwc(testresultdir)
1717 print "updating", resultwc
1818 resultwc.update()
19 except KeyboardInterrupt as RuntimeError:
19 except (KeyboardInterrupt, RuntimeError):
2020 raise
2121 except Exception as e: #py.process.ExecutionFailed,e:
2222 print >> sys.stderr, "Warning: ",e #Subversion update failed"
+0
-52
pypy/tool/pytest/inttest.py less more
0 # Collects and executes interpreter-level tests.
1 #
2 # Most pypy tests are of this kind.
3
4 import py
5 import sys
6 from pypy.interpreter.error import OperationError
7 from pypy.conftest import PyPyClassCollector
8
9
10 def check_keyboard_interrupt(e):
11 # we cannot easily convert w_KeyboardInterrupt to KeyboardInterrupt
12 # in general without a space -- here is an approximation
13 try:
14 if e.w_type.name == 'KeyboardInterrupt':
15 tb = sys.exc_info()[2]
16 raise KeyboardInterrupt, KeyboardInterrupt(), tb
17 except AttributeError:
18 pass
19
20
21 marker = py.test.mark.interplevel
22
23
24 class IntTestFunction(py.test.collect.Function):
25 def __init__(self, *args, **kwargs):
26 super(IntTestFunction, self).__init__(*args, **kwargs)
27 self._request.applymarker(marker)
28
29 def runtest(self):
30 try:
31 super(IntTestFunction, self).runtest()
32 except OperationError as e:
33 check_keyboard_interrupt(e)
34 raise
35 except Exception as e:
36 cls = e.__class__
37 while cls is not Exception:
38 if cls.__name__ == 'DistutilsPlatformError':
39 from distutils.errors import DistutilsPlatformError
40 if isinstance(e, DistutilsPlatformError):
41 py.test.skip('%s: %s' % (e.__class__.__name__, e))
42 cls = cls.__bases__[0]
43 raise
44
45
46 class IntInstanceCollector(py.test.collect.Instance):
47 Function = IntTestFunction
48
49
50 class IntClassCollector(PyPyClassCollector):
51 Instance = IntInstanceCollector
106106 def newlist(self, iterable):
107107 return list(iterable)
108108
109 def newbytes(self, obj):
110 return bytes(obj)
111
109112 def call_function(self, func, *args, **kwds):
110113 return func(*args, **kwds)
111114
127130 def is_w(self, obj1, obj2):
128131 return obj1 is obj2
129132
133 def setitem(self, obj, key, value):
134 obj[key] = value
2626 result = testdir.runpytest("--collectonly")
2727 assert result.ret == 0
2828 result.stdout.fnmatch_lines([
29 "*IntTestFunction*test_func*",
30 "*IntClassCollector*TestClassInt*",
31 "*IntTestFunction*test_method*",
29 "*Function*test_func*",
30 "*Class*TestClassInt*",
31 "*Function*test_method*",
3232 "*AppClassCollector*AppTestClass*",
33 "*AppTestMethod*",
33 "*AppTestMethod*",
3434 ])
3535
3636 class TestSpaceConfig:
132132
133133 x = 43
134134 info = raises(ZeroDivisionError, "x/0")
135 assert info.type is ZeroDivisionError
136 assert isinstance(info.value, ZeroDivisionError)
135 assert info.type is ZeroDivisionError
136 assert isinstance(info.value, ZeroDivisionError)
1919 assert not skipped and not failed
2020 assert "app_test_something" in passed[0].nodeid
2121 assert "test_method_app" in passed[1].nodeid
22
23 def test_appdirect(self, testdir):
24 sorter = testdir.inline_run(innertest, '-m', 'applevel', '--runappdirect')
25 passed, skipped, failed = sorter.listoutcomes()
26 assert len(passed) == 2
27 print passed
28 assert "app_test_something" in passed[0].nodeid
29 assert "test_method_app" in passed[1].nodeid
22 It uses 'pypy/goal/pypy-c' and parts of the rest of the working
33 copy. Usage:
44
5 package.py [--options] pypy-VER-PLATFORM
5 package.py [--options] --archive-name=pypy-VER-PLATFORM
66
77 The output is found in the directory from --builddir,
88 by default /tmp/usession-YOURNAME/build/.
9
10 For a list of all options, see 'package.py --help'.
911 """
1012
1113 import shutil
6062 name = options.name
6163 if not name:
6264 name = 'pypy-nightly'
65 assert '/' not in name
6366 rename_pypy_c = options.pypy_c
6467 override_pypy_c = options.override_pypy_c
6568
287290 help='destination dir for archive')
288291 parser.add_argument('--override_pypy_c', type=str, default='',
289292 help='use as pypy exe instead of pypy/goal/pypy-c')
290 # Positional arguments, for backward compatability with buldbots
291 parser.add_argument('extra_args', help='optional interface to positional arguments', nargs=argparse.REMAINDER,
292 metavar='[archive-name] [rename_pypy_c] [targetdir] [override_pypy_c]',
293 )
294293 options = parser.parse_args(args)
295294
296 # Handle positional arguments, choke if both methods are used
297 for i,target, default in ([1, 'name', ''], [2, 'pypy_c', pypy_exe],
298 [3, 'targetdir', ''], [4,'override_pypy_c', '']):
299 if len(options.extra_args)>i:
300 if getattr(options, target) != default:
301 print 'positional argument',i,target,'already has value',getattr(options, target)
302 parser.print_help()
303 return
304 setattr(options, target, options.extra_args[i])
305295 if os.environ.has_key("PYPY_PACKAGE_NOSTRIP"):
306296 options.nostrip = True
307
308297 if os.environ.has_key("PYPY_PACKAGE_WITHOUTTK"):
309 options.tk = True
298 options.no_tk = True
310299 if not options.builddir:
311300 # The import actually creates the udir directory
312301 from rpython.tool.udir import udir
00 # Edit these appropriately before running this script
11 maj=5
2 min=3
2 min=4
33 rev=0
44 branchname=release-$maj.x # ==OR== release-$maj.$min.x
5 tagname=release-$maj.$min.$rev # ==OR== release-$maj.$min
5 tagname=release-pypy2.7-v$maj.$min.$rev # ==OR== release-$maj.$min
66
77 echo checking hg log -r $branchname
88 hg log -r $branchname || exit 1
3333 plat=win32
3434 wget http://buildbot.pypy.org/nightly/$branchname/pypy-c-jit-latest-$plat.zip
3535 unzip pypy-c-jit-latest-$plat.zip
36 rm pypy-c-jit-latest-$plat.zip
3637 mv pypy-c-jit-*-$plat $rel-$plat
37 zip -r $rel-$plat.zip $rel-$plat
38 zip -rq $rel-$plat.zip $rel-$plat
3839 rm -rf $rel-$plat
3940
4041 # Do this after creating a tag, note the untarred directory is pypy-pypy-<hash>
4142 # so make sure there is not another one
4243 wget https://bitbucket.org/pypy/pypy/get/$tagname.tar.bz2
4344 tar -xf $tagname.tar.bz2
45 rm $tagname.tar.bz2
4446 mv pypy-pypy-* $rel-src
4547 tar --owner=root --group=root --numeric-owner -cjf $rel-src.tar.bz2 $rel-src
46 zip -r $rel-src.zip $rel-src
48 zip -rq $rel-src.zip $rel-src
4749 rm -rf $rel-src
4850
4951 # Print out the md5, sha1, sha256
2020
2121 def test_dir_structure(self, test='test'):
2222 retval, builddir = package.package(
23 '--without-cffi', str(py.path.local(pypydir).dirpath()),
24 test, self.rename_pypy_c, _fake=True)
23 '--without-cffi',
24 '--archive-name', test,
25 '--rename_pypy_c', self.rename_pypy_c,
26 _fake=True)
2527 assert retval == 0
2628 prefix = builddir.join(test)
2729 cpyver = '%d.%d' % CPYTHON_VERSION[:2]
7072 builddir = udir.ensure("build", dir=True)
7173 retval, builddir = package.package(
7274 '--without-cffi', '--builddir', str(builddir),
73 str(py.path.local(pypydir).dirpath()),
74 test, self.rename_pypy_c, _fake=True)
75 '--archive-name', test,
76 '--rename_pypy_c', self.rename_pypy_c,
77 _fake=True)
7578
7679 def test_with_zipfile_module(self):
7780 prev = package.USE_ZIPFILE_MODULE
0 # hypothesis is used for test generation on untranslated jit tests
0 cffi>=1.4.0
1
2 # hypothesis is used for test generation on untranslated tests
13 hypothesis
24 enum34>=1.1.2
400400 class __extend__(pairtype(SomeString, SomeTuple),
401401 pairtype(SomeUnicodeString, SomeTuple)):
402402 def mod((s_string, s_tuple)):
403 if not s_string.is_constant():
404 raise AnnotatorError("string formatting requires a constant "
405 "string/unicode on the left of '%'")
403406 is_string = isinstance(s_string, SomeString)
404407 is_unicode = isinstance(s_string, SomeUnicodeString)
405408 assert is_string or is_unicode
46094609 a.build_types(fd, [])
46104610 py.test.raises(AnnotatorError, a.build_types, fb, [])
46114611
4612 def test_annotate_generator_with_unreachable_yields(self):
4613 def f(n):
4614 if n < 0:
4615 yield 42
4616 yield n
4617 yield n
4618 def main(n):
4619 for x in f(abs(n)):
4620 pass
4621 #
4622 a = self.RPythonAnnotator()
4623 a.build_types(main, [int])
4624
4625 def test_string_mod_nonconstant(self):
4626 def f(x):
4627 return x % 5
4628 a = self.RPythonAnnotator()
4629 e = py.test.raises(AnnotatorError, a.build_types, f, [str])
4630 assert ('string formatting requires a constant string/unicode'
4631 in str(e.value))
4632
46124633
46134634 def g(n):
46144635 return [0, 1, 2, n]
260260 "stack based virtual machines (only for backends that support it)",
261261 default=True),
262262 BoolOption("storesink", "Perform store sinking", default=True),
263 BoolOption("replace_we_are_jitted",
264 "Replace we_are_jitted() calls by False",
265 default=False, cmdline=None),
263266 BoolOption("none",
264267 "Do not run any backend optimizations",
265268 requires=[('translation.backendopt.inline', False),
0 .. _arch_index:
1
2 Architecture specific notes
3 ===========================
4
5 Here you can find some architecture specific notes.
6
7 .. toctree::
8 :maxdepth: 1
9
10 s390x
0 .. _s390x:
1
2 IBM Mainframe S390X
3 ===================
4
5 Our JIT implements the 64 bit version of the IBM Mainframe called s390x.
6 Note that this architecture is big endian.
7
8 Currently supported ISAs:
9
10 * z13 (released January 2015)
11 * zEC12 (released September 2012)
12 * z196 (released August 2010)
13 * z10 (released February 2008)
14
15 To check if all the necessary CPU facilities are installed
16 on the subject machine, please run the test using a copy of the pypy
17 source code::
18
19 $ ./pytest.py rpython/jit/backend/zarch/test/test_assembler -v -k 'test_facility'
20
21 In addition you can run the auto encoding test to check if your Linux GCC tool chain
22 is able to compile all instructions used in the JIT backend::
23
24 $ ./pytest.py rpython/jit/backend/zarch/test/test_auto_encoding.py -v
25
26 Translating
27 -----------
28
29 Specifically check for these two dependencies. On old versions of some
30 Linux distributions ship older versions.
31
32 * libffi (version should do > 3.0.+).
33 * CPython 2.7.+.
147147
148148 ::
149149
150 pypy ~/path_to_pypy_checkout/rpython/bin/rpython -O1 --platform=arm target.py
150 pypy ~/path_to_pypy_checkout/rpython/bin/rpython -O2 --platform=arm target.py
151151
152152 If everything worked correctly this should yield an ARM binary. Running this binary in the ARM chroot or on an ARM device should produce the output ``"Hello World"``.
153153
141141 Translating Full Programs
142142 ~~~~~~~~~~~~~~~~~~~~~~~~~
143143
144 To translate full RPython programs, there is the script ``translate.py`` in
145 :source:`rpython/translator/goal`. Examples for this are a slightly changed version of
144 To translate full RPython programs, there is the script ``bin/rpython`` in
145 :source:`rpython/bin/`. Examples for this are a slightly changed version of
146146 Pystone::
147147
148148 python bin/rpython translator/goal/targetrpystonedalone
3636
3737 arm
3838 logging
39 s390x
4039
4140
4241 Writing your own interpreter in RPython
6059 getting-started
6160 dir-reference
6261 jit/index
62 arch/index
6363 translation
6464 rtyper
6565 garbage_collection
133133 dicts with a unique key type only, provided it is hashable. Custom
134134 hash functions and custom equality will not be honored.
135135 Use ``rpython.rlib.objectmodel.r_dict`` for custom hash functions.
136
137 **sets**
138
139 sets are not directly supported in RPython. Instead you should use a
140 plain dict and fill the values with None. Values in that dict
141 will not consume space.
136142
137143 **list comprehensions**
138144
+0
-20
rpython/doc/s390x.rst less more
0 .. _s390x:
1
2 S390X JIT Backend
3 =================
4
5 Our JIT implements the 64 bit version of the IBM Mainframe called s390x.
6 Note that this architecture is big endian.
7
8 The following facilities need to be installed to operate
9 correctly (all of the machines used for development these where installed):
10
11 * General-Instructions-Extension
12 * Long-Displacement
13 * Binary Floating Point (IEEE)
14
15 Translating
16 -----------
17
18 Ensure that libffi is installed (version should do > 3.0.+).
19 CPython should be version 2.7.+.
131131 del block.operations[index]
132132 newlink = split_block(block, index)
133133 newblock = newlink.target
134 varnames = get_variable_names(newlink.args)
134135 #
135136 class Resume(AbstractPosition):
136137 _immutable_ = True
138 _attrs_ = varnames
137139 block = newblock
138140 Resume.__name__ = 'Resume%d' % len(mappings)
139141 mappings.append(Resume)
140 varnames = get_variable_names(newlink.args)
141142 #
142143 _insert_reads(newblock, varnames)
143144 #
1313 CoreRegisterManager, check_imm_arg, VFPRegisterManager,
1414 operations as regalloc_operations)
1515 from rpython.jit.backend.llsupport import jitframe, rewrite
16 from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, BaseAssembler
16 from rpython.jit.backend.llsupport.assembler import BaseAssembler
1717 from rpython.jit.backend.llsupport.regalloc import get_scale, valid_addressing_size
1818 from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
1919 from rpython.jit.backend.model import CompiledLoopToken
2828 from rpython.rtyper.lltypesystem import lltype, rffi
2929 from rpython.jit.backend.arm import callbuilder
3030 from rpython.rtyper.lltypesystem.lloperation import llop
31 from rpython.rlib.rjitlog import rjitlog as jl
3132
3233 class AssemblerARM(ResOpAssembler):
3334
8182 self.failure_recovery_code = [0, 0, 0, 0]
8283
8384 def _build_propagate_exception_path(self):
84 if not self.cpu.propagate_exception_descr:
85 return # not supported (for tests, or non-translated)
86 #
8785 mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
8886 self._store_and_reset_exception(mc, r.r0)
8987 ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
371369 self._write_barrier_fastpath(mc, wbdescr, [r.fp], array=False,
372370 is_frame=True)
373371
374 def propagate_memoryerror_if_r0_is_null(self):
375 # see ../x86/assembler.py:propagate_memoryerror_if_eax_is_null
376 self.mc.CMP_ri(r.r0.value, 0)
372 def propagate_memoryerror_if_reg_is_null(self, reg_loc):
373 # see ../x86/assembler.py:genop_discard_check_memory_error()
374 self.mc.CMP_ri(reg_loc.value, 0)
377375 self.mc.B(self.propagate_exception_path, c=c.EQ)
378376
379377 def _push_all_regs_to_jitframe(self, mc, ignored_regs, withfloats,
635633 'loop.asm')
636634
637635 ops_offset = self.mc.ops_offset
638 if logger is not None:
639 logger.log_loop(inputargs, operations, 0, "rewritten",
640 name=loopname, ops_offset=ops_offset)
636
637 if logger:
638 log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc)
639 log.write(inputargs, operations, ops_offset=ops_offset)
640
641 # legacy
642 if logger.logger_ops:
643 logger.logger_ops.log_loop(inputargs, operations, 0,
644 "rewritten", name=loopname,
645 ops_offset=ops_offset)
646
641647 self.teardown()
642648
643649 debug_start("jit-backend-addr")
737743 frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE)
738744 self.fixup_target_tokens(rawstart)
739745 self.update_frame_depth(frame_depth)
746
740747 if logger:
741 logger.log_bridge(inputargs, operations, "rewritten", faildescr,
742 ops_offset=ops_offset)
748 log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc)
749 log.write(inputargs, operations, ops_offset)
750 # log that the already written bridge is stitched to a descr!
751 logger.log_patch_guard(descr_number, rawstart)
752
753 # legacy
754 if logger.logger_ops:
755 logger.logger_ops.log_bridge(inputargs, operations, "rewritten",
756 faildescr, ops_offset=ops_offset)
757
743758 self.teardown()
744759
745760 return AsmInfo(ops_offset, startpos + rawstart, codeendpos - startpos)
882882 ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR,
883883 self.cpu.translate_support_code)
884884 assert itemsize == 1
885 ofs_items -= 1 # for the extra null character
885886 scale = 0
886887 self._gen_address(resloc, baseloc, ofsloc, scale, ofs_items)
887888
10491050 regalloc = self._regalloc
10501051 return regalloc.operations[regalloc.rm.position + delta]
10511052
1052 def emit_op_call_malloc_gc(self, op, arglocs, regalloc, fcond):
1053 self._emit_call(op, arglocs, fcond=fcond)
1054 self.propagate_memoryerror_if_r0_is_null()
1053 def emit_op_check_memory_error(self, op, arglocs, regalloc, fcond):
1054 self.propagate_memoryerror_if_reg_is_null(arglocs[0])
10551055 self._alignment_check()
10561056 return fcond
10571057
593593 resloc = self.after_call(op)
594594 return resloc
595595
596 def prepare_op_call_malloc_gc(self, op, fcond):
597 return self._prepare_call(op)
596 def prepare_op_check_memory_error(self, op, fcond):
597 argloc = self.make_sure_var_in_reg(op.getarg(0))
598 return [argloc]
598599
599600 def _prepare_llong_binop_xx(self, op, fcond):
600601 # arg 0 is the address of the function
900901 size_box = op.getarg(0)
901902 assert isinstance(size_box, ConstInt)
902903 size = size_box.getint()
904 # hint: try to move unrelated registers away from r0 and r1 now
905 self.rm.spill_or_move_registers_before_call([r.r0, r.r1])
903906
904907 self.rm.force_allocate_reg(op, selected_reg=r.r0)
905908 t = TempInt()
923926 # sizeloc must be in a register, but we can free it now
924927 # (we take care explicitly of conflicts with r0 or r1)
925928 sizeloc = self.rm.make_sure_var_in_reg(size_box)
929 self.rm.spill_or_move_registers_before_call([r.r0, r.r1]) # sizeloc safe
926930 self.rm.possibly_free_var(size_box)
927931 #
928932 self.rm.force_allocate_reg(op, selected_reg=r.r0)
950954 arraydescr = op.getdescr()
951955 length_box = op.getarg(2)
952956 assert not isinstance(length_box, Const) # we cannot have a const here!
957 # can only use spill_or_move_registers_before_call() as a hint if
958 # we are sure that length_box stays alive and won't be freed now
959 # (it should always be the case, see below, but better safe than sorry)
960 if self.rm.stays_alive(length_box):
961 self.rm.spill_or_move_registers_before_call([r.r0, r.r1])
953962 # the result will be in r0
954963 self.rm.force_allocate_reg(op, selected_reg=r.r0)
955964 # we need r1 as a temporary
00 from rpython.jit.backend.arm import conditions as c
11 from rpython.jit.backend.arm import registers as r
2 from rpython.jit.backend.arm.support import arm_int_div
32 from rpython.jit.backend.arm.assembler import AssemblerARM
43 from rpython.jit.backend.arm.locations import imm
54 from rpython.jit.backend.arm.test.support import run_asm
179178 self.a.gen_func_epilog()
180179 assert run_asm(self.a) == 133
181180
182 def test_division(self):
183 self.a.gen_func_prolog()
184 self.a.mc.MOV_ri(r.r0.value, 123)
185 self.a.mc.MOV_ri(r.r1.value, 2)
186
187 # call to div
188 self.a.mc.PUSH(range(2, 12))
189 div_addr = rffi.cast(lltype.Signed, arm_int_div)
190 self.a.mc.BL(div_addr)
191 self.a.mc.POP(range(2, 12))
192 self.a.gen_func_epilog()
193 assert run_asm(self.a) == 61
194
195181 def test_bl_with_conditional_exec(self):
196182 functype = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
197183 call_addr = rffi.cast(lltype.Signed, llhelper(functype, callme))
543543 s = lltype.malloc(self.I, 3)
544544 self.interpret(ops, [s, 1234567890])
545545 assert s[1] == 1234567890
546
547 def test_division_optimized(self):
548 ops = '''
549 [i7, i6]
550 label(i7, i6, descr=targettoken)
551 i18 = int_floordiv(i7, i6)
552 i19 = int_xor(i7, i6)
553 i21 = int_lt(i19, 0)
554 i22 = int_mod(i7, i6)
555 i23 = int_is_true(i22)
556 i24 = int_eq(i6, 4)
557 guard_false(i24) [i18]
558 jump(i18, i6, descr=targettoken)
559 '''
560 self.interpret(ops, [10, 4])
561 assert self.getint(0) == 2
562 # FIXME: Verify that i19 - i23 are removed
563546
564547
565548 class TestRegallocFloats(CustomBaseTestRegalloc):
831831 struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct)
832832 result_adr = llmemory.cast_ptr_to_adr(struct.typeptr)
833833 return heaptracker.adr2int(result_adr)
834
835 def bh_new_raw_buffer(self, size):
836 return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
837834
838835 # vector operations
839836 vector_arith_code = """
15201517 lle = None
15211518 self.last_exception = lle
15221519
1520 def execute_check_memory_error(self, descr, value):
1521 if not value:
1522 from rpython.jit.backend.llsupport import llmodel
1523 raise llmodel.MissingLatestDescrError
1524
15231525
15241526 def _getdescr(op):
15251527 d = op.getdescr()
222222 self.init_block_builder()
223223 else:
224224 self._become_a_plain_block_builder()
225 self.rawstart = 0
225226
226227 def init_block_builder(self):
227228 self._cursubblock = lltype.nullptr(self.SUBBLOCK)
243244 index = 0
244245 self._cursubblock.data[index] = char
245246 self._cursubindex = index + 1
247
248 def absolute_addr(self):
249 return self.rawstart
246250
247251 def overwrite(self, index, char):
248252 assert 0 <= index < self.get_relative_pos()
278282 blocksize = self.SUBBLOCK_SIZE
279283 targetindex -= self.SUBBLOCK_SIZE
280284 assert not block
285
286 def copy_core_dump(self, addr, offset=0, count=-1):
287 HEX = '0123456789ABCDEF'
288 dump = []
289 src = rffi.cast(rffi.CCHARP, addr)
290 end = self.get_relative_pos()
291 if count != -1:
292 end = offset + count
293 for p in range(offset, end):
294 o = ord(src[p])
295 dump.append(HEX[o >> 4])
296 dump.append(HEX[o & 15])
297 return ''.join(dump)
281298
282299 def _dump(self, addr, logname, backend=None):
283300 debug_start(logname)
292309 else:
293310 debug_print('SYS_EXECUTABLE', '??')
294311 #
295 HEX = '0123456789ABCDEF'
296 dump = []
297 src = rffi.cast(rffi.CCHARP, addr)
298 for p in range(self.get_relative_pos()):
299 o = ord(src[p])
300 dump.append(HEX[o >> 4])
301 dump.append(HEX[o & 15])
312 dump = self.copy_core_dump(addr)
302313 debug_print('CODE_DUMP',
303314 '@%x' % addr,
304315 '+0 ', # backwards compatibility
305 ''.join(dump))
316 dump)
306317 #
307318 debug_stop(logname)
308319
314325 allblocks.append(malloced)
315326 rawstart = malloced[0]
316327 rawstart = (rawstart + align - 1) & (-align)
328 self.rawstart = rawstart
317329 self.copy_to_raw_memory(rawstart)
318330 if self.gcroot_markers is not None:
319331 assert gcrootmap is not None
1111 from rpython.rlib.objectmodel import specialize, compute_unique_id
1212 from rpython.rtyper.annlowlevel import cast_instance_to_gcref, llhelper
1313 from rpython.rtyper.lltypesystem import rffi, lltype
14
14 from rpython.rlib.rjitlog import rjitlog as jl
1515
1616 DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER',
1717 # 'b'ridge, 'l'abel or # 'e'ntry point
7272 self.memcpy_addr = 0
7373 self.memset_addr = 0
7474 self.rtyper = cpu.rtyper
75 # do not rely on this attribute if you test for jitlog
7576 self._debug = False
77 self.loop_run_counters = []
7678
7779 def stitch_bridge(self, faildescr, target):
7880 raise NotImplementedError
128130
129131 self._build_stack_check_slowpath()
130132 self._build_release_gil(gc_ll_descr.gcrootmap)
133 # do not rely on the attribute _debug for jitlog
131134 if not self._debug:
132135 # if self._debug is already set it means that someone called
133136 # set_debug by hand before initializing the assembler. Leave it
134137 # as it is
135 self.set_debug(have_debug_prints_for('jit-backend-counts'))
138 should_debug = have_debug_prints_for('jit-backend-counts')
139 self.set_debug(should_debug)
136140 # when finishing, we only have one value at [0], the rest dies
137141 self.gcmap_for_finish = lltype.malloc(jitframe.GCMAP, 1,
138142 flavor='raw',
336340 # Here we join Path A and Path B again
337341 self._call_assembler_patch_jmp(jmp_location)
338342
343 def get_loop_run_counters(self, index):
344 return self.loop_run_counters[index]
345
339346 @specialize.argtype(1)
340347 def _inject_debugging_code(self, looptoken, operations, tp, number):
341 if self._debug:
342 s = 0
343 for op in operations:
344 s += op.getopnum()
345
348 if self._debug or jl.jitlog_enabled():
346349 newoperations = []
347 self._append_debugging_code(newoperations, tp, number,
348 None)
350 self._append_debugging_code(newoperations, tp, number, None)
349351 for op in operations:
350352 newoperations.append(op)
351353 if op.getopnum() == rop.LABEL:
361363 ResOperation(rop.INCREMENT_DEBUG_COUNTER, [c_adr]))
362364
363365 def _register_counter(self, tp, number, token):
364 # YYY very minor leak -- we need the counters to stay alive
365 # forever, just because we want to report them at the end
366 # of the process
367
368366 # XXX the numbers here are ALMOST unique, but not quite, use a counter
369367 # or something
370368 struct = lltype.malloc(DEBUG_COUNTER, flavor='raw',
376374 else:
377375 assert token
378376 struct.number = compute_unique_id(token)
377 # YYY very minor leak -- we need the counters to stay alive
378 # forever, just because we want to report them at the end
379 # of the process
379380 self.loop_run_counters.append(struct)
380381 return struct
381382
382383 def finish_once(self):
383384 if self._debug:
385 # TODO remove the old logging system when jitlog is complete
384386 debug_start('jit-backend-counts')
385 for i in range(len(self.loop_run_counters)):
387 length = len(self.loop_run_counters)
388 for i in range(length):
386389 struct = self.loop_run_counters[i]
387390 if struct.type == 'l':
388391 prefix = 'TargetToken(%d)' % struct.number
399402 debug_print(prefix + ':' + str(struct.i))
400403 debug_stop('jit-backend-counts')
401404
405 self.flush_trace_counters()
406
407 def flush_trace_counters(self):
408 # this is always called, the jitlog knows if it is enabled
409 length = len(self.loop_run_counters)
410 for i in range(length):
411 struct = self.loop_run_counters[i]
412 # only log if it has been executed
413 if struct.i > 0:
414 jl._log_jit_counter(struct)
415 # reset the counter, flush in a later point in time will
416 # add up the counters!
417 struct.i = 0
418 # here would be the point to free some counters
419 # see YYY comment above! but first we should run this every once in a while
420 # not just when jitlog_disable is called
421
402422 @staticmethod
403423 @rgc.no_collect
404424 def _reacquire_gil_asmgcc(css, old_rpy_fastgil):
279279 concrete_type = '\x00'
280280
281281 def __init__(self, basesize, itemsize, lendescr, flag, is_pure=False, concrete_type='\x00'):
282 self.basesize = basesize
282 self.basesize = basesize # this includes +1 for STR
283283 self.itemsize = itemsize
284284 self.lendescr = lendescr # or None, if no length
285285 self.flag = flag
675675
676676 def unpack_arraydescr(arraydescr):
677677 assert isinstance(arraydescr, ArrayDescr)
678 ofs = arraydescr.basesize
678 ofs = arraydescr.basesize # this includes +1 for STR
679679 size = arraydescr.itemsize
680680 sign = arraydescr.is_item_signed()
681681 return size, ofs, sign
4747 anything, it must be an optional MemoryError.
4848 """
4949 FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, RESULT))
50 descr = get_call_descr(self, ARGS, RESULT)
50 # Note: the call may invoke the GC, which may run finalizers.
51 # Finalizers are constrained in what they can do, but we can't
52 # really express that in a useful way here.
53 descr = get_call_descr(self, ARGS, RESULT, EffectInfo.MOST_GENERAL)
5154 setattr(self, funcname, func)
5255 setattr(self, funcname + '_FUNCPTR', FUNCPTR)
5356 setattr(self, funcname + '_descr', descr)
112112 unique_id=0, log=True, name='', logger=None):
113113 return self.assembler.assemble_loop(jd_id, unique_id, logger, name,
114114 inputargs, operations,
115 looptoken, log=log)
115 looptoken, log)
116116
117117 def stitch_bridge(self, faildescr, target):
118118 self.assembler.stitch_bridge(faildescr, target)
407407 deadframe = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, deadframe)
408408 descr = deadframe.jf_descr
409409 res = history.AbstractDescr.show(self, descr)
410 if not we_are_translated(): # tests only: for missing
411 if res is None: # propagate_exception_descr
412 raise MissingLatestDescrError
410413 assert isinstance(res, history.AbstractFailDescr)
411414 return res
412415
753756 self.write_int_at_mem(res, self.vtable_offset, WORD, sizedescr.get_vtable())
754757 return res
755758
756 def bh_new_raw_buffer(self, size):
757 return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
758
759759 def bh_classof(self, struct):
760760 struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct)
761761 result_adr = llmemory.cast_ptr_to_adr(struct.typeptr)
815815 calldescr.call_stub_i(func, args_i, args_r, args_f)
816816
817817
818 class MissingLatestDescrError(Exception):
819 """For propagate_exception_descr in untranslated tests."""
820
818821 final_descr_rd_locs = [rffi.cast(rffi.USHORT, 0)]
819822 history.BasicFinalDescr.rd_locs = final_descr_rd_locs
820823 compile._DoneWithThisFrameDescr.rd_locs = final_descr_rd_locs
578578 new_free_regs.append(self.reg_bindings.pop(v))
579579
580580 def before_call(self, force_store=[], save_all_regs=0):
581 """Spill or move some registers before a call. By default,
582 this means: for every register in 'self.save_around_call_regs',
581 self.spill_or_move_registers_before_call(self.save_around_call_regs,
582 force_store, save_all_regs)
583
584 def spill_or_move_registers_before_call(self, save_sublist,
585 force_store=[], save_all_regs=0):
586 """Spill or move some registers before a call.
587
588 By default, this means: for every register in 'save_sublist',
583589 if there is a variable there and it survives longer than
584590 the current operation, then it is spilled/moved somewhere else.
591
592 WARNING: this might do the equivalent of possibly_free_vars()
593 on variables dying in the current operation. It won't
594 immediately overwrite registers that used to be occupied by
595 these variables, though. Use this function *after* you finished
596 calling self.loc() or self.make_sure_var_in_reg(), i.e. when you
597 know the location of all input arguments. These locations stay
598 valid, but only *if they are in self.save_around_call_regs,*
599 not if they are callee-saved registers!
585600
586601 'save_all_regs' can be 0 (default set of registers), 1 (do that
587602 for all registers), or 2 (default + gc ptrs).
611626 anyway, as a local hack in this function, because on x86 CPUs
612627 such register-register moves are almost free.
613628 """
629 if not we_are_translated():
630 # 'save_sublist' is either the whole
631 # 'self.save_around_call_regs', or a sublist thereof, and
632 # then only those registers are spilled/moved. But when
633 # we move them, we never move them to other registers in
634 # 'self.save_around_call_regs', to avoid ping-pong effects
635 # where the same value is constantly moved around.
636 for reg in save_sublist:
637 assert reg in self.save_around_call_regs
638
614639 new_free_regs = []
615640 move_or_spill = []
616641
630655 # we need to spill all GC ptrs in this mode
631656 self._bc_spill(v, new_free_regs)
632657 #
633 elif reg not in self.save_around_call_regs:
658 elif reg not in save_sublist:
634659 continue # in a register like ebx/rbx: it is fine where it is
635660 #
636661 else:
662687 if not we_are_translated():
663688 if move_or_spill:
664689 assert max_age <= min([_a for _, _a in move_or_spill])
690 assert reg in save_sublist
665691 assert reg in self.save_around_call_regs
666692 assert new_reg not in self.save_around_call_regs
667693 self.assembler.regalloc_mov(reg, new_reg)
2525 class GcRewriterAssembler(object):
2626 """ This class performs the following rewrites on the list of operations:
2727
28 - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY
28 - Turn all NEW_xxx to either a CALL_R/CHECK_MEMORY_ERROR,
29 or a CALL_MALLOC_NURSERY,
2930 followed by SETFIELDs in order to initialize their GC fields. The
3031 two advantages of CALL_MALLOC_NURSERY is that it inlines the common
3132 path, and we need only one such operation to allocate several blocks
291292 basesize, itemsize, ofs_length = get_array_token(rstr.STR,
292293 self.cpu.translate_support_code)
293294 assert itemsize == 1
295 basesize -= 1 # for the extra null character
294296 self.emit_gc_load_or_indexed(op, op.getarg(0), op.getarg(1),
295297 itemsize, itemsize, basesize, NOT_SIGNED)
296298 elif opnum == rop.UNICODEGETITEM:
302304 basesize, itemsize, ofs_length = get_array_token(rstr.STR,
303305 self.cpu.translate_support_code)
304306 assert itemsize == 1
307 basesize -= 1 # for the extra null character
305308 self.emit_gc_store_or_indexed(op, op.getarg(0), op.getarg(1), op.getarg(2),
306309 itemsize, itemsize, basesize)
307310 elif opnum == rop.UNICODESETITEM:
714717 self._delayed_zero_setfields.clear()
715718
716719 def _gen_call_malloc_gc(self, args, v_result, descr):
717 """Generate a CALL_MALLOC_GC with the given args."""
720 """Generate a CALL_R/CHECK_MEMORY_ERROR with the given args."""
718721 self.emitting_an_operation_that_can_collect()
719 op = ResOperation(rop.CALL_MALLOC_GC, args, descr=descr)
722 op = ResOperation(rop.CALL_R, args, descr=descr)
720723 self.replace_op_with(v_result, op)
721724 self.emit_op(op)
725 self.emit_op(ResOperation(rop.CHECK_MEMORY_ERROR, [op]))
722726 # In general, don't add v_result to write_barrier_applied:
723727 # v_result might be a large young array.
724728
725729 def gen_malloc_fixedsize(self, size, typeid, v_result):
726 """Generate a CALL_MALLOC_GC(malloc_fixedsize_fn, ...).
730 """Generate a CALL_R(malloc_fixedsize_fn, ...).
727731 Used on Boehm, and on the framework GC for large fixed-size
728732 mallocs. (For all I know this latter case never occurs in
729733 practice, but better safe than sorry.)
743747 self.remember_write_barrier(v_result)
744748
745749 def gen_boehm_malloc_array(self, arraydescr, v_num_elem, v_result):
746 """Generate a CALL_MALLOC_GC(malloc_array_fn, ...) for Boehm."""
750 """Generate a CALL_R(malloc_array_fn, ...) for Boehm."""
747751 addr = self.gc_ll_descr.get_malloc_fn_addr('malloc_array')
748752 self._gen_call_malloc_gc([ConstInt(addr),
749753 ConstInt(arraydescr.basesize),
754758 self.gc_ll_descr.malloc_array_descr)
755759
756760 def gen_malloc_array(self, arraydescr, v_num_elem, v_result):
757 """Generate a CALL_MALLOC_GC(malloc_array_fn, ...) going either
761 """Generate a CALL_R(malloc_array_fn, ...) going either
758762 to the standard or the nonstandard version of the function."""
759763 #
760764 if (arraydescr.basesize == self.gc_ll_descr.standard_array_basesize
781785 self._gen_call_malloc_gc(args, v_result, calldescr)
782786
783787 def gen_malloc_str(self, v_num_elem, v_result):
784 """Generate a CALL_MALLOC_GC(malloc_str_fn, ...)."""
788 """Generate a CALL_R(malloc_str_fn, ...)."""
785789 addr = self.gc_ll_descr.get_malloc_fn_addr('malloc_str')
786790 self._gen_call_malloc_gc([ConstInt(addr), v_num_elem], v_result,
787791 self.gc_ll_descr.malloc_str_descr)
788792
789793 def gen_malloc_unicode(self, v_num_elem, v_result):
790 """Generate a CALL_MALLOC_GC(malloc_unicode_fn, ...)."""
794 """Generate a CALL_R(malloc_unicode_fn, ...)."""
791795 addr = self.gc_ll_descr.get_malloc_fn_addr('malloc_unicode')
792796 self._gen_call_malloc_gc([ConstInt(addr), v_num_elem], v_result,
793797 self.gc_ll_descr.malloc_unicode_descr)
2828 def get_array_token(T, translate_support_code):
2929 # T can be an array or a var-sized structure
3030 if translate_support_code:
31 basesize = llmemory.sizeof(T, 0)
31 basesize = llmemory.sizeof(T, 0) # this includes +1 for STR
3232 if isinstance(T, lltype.Struct):
3333 SUBARRAY = getattr(T, T._arrayfld)
3434 itemsize = llmemory.sizeof(SUBARRAY.OF)
5656 assert carray.length.size == WORD
5757 ofs_length = before_array_part + carray.length.offset
5858 basesize = before_array_part + carray.items.offset
59 basesize += T._hints.get('extra_item_after_alloc', 0) # +1 for STR
5960 carrayitem = ll2ctypes.get_ctypes_type(T.OF)
6061 itemsize = ctypes.sizeof(carrayitem)
6162 return basesize, itemsize, ofs_length
434434 def test_bytearray_descr():
435435 c0 = GcCache(False)
436436 descr = get_array_descr(c0, rstr.STR) # for bytearray
437 # note that we get a basesize that has 1 extra byte for the final null char
438 # (only for STR)
437439 assert descr.flag == FLAG_UNSIGNED
438 assert descr.basesize == struct.calcsize("PP") # hash, length
440 assert descr.basesize == struct.calcsize("PP") + 1 # hash, length, extra
439441 assert descr.lendescr.offset == struct.calcsize("P") # hash
440442 assert not descr.is_array_of_pointers()
441443
323323 def check(frame):
324324 expected_size = 1
325325 idx = 0
326 fixed_size = self.cpu.JITFRAME_FIXED_SIZE
326327 if self.cpu.backend_name.startswith('arm'):
327328 # jitframe fixed part is larger here
328329 expected_size = 2
329330 idx = 1
331 fixed_size -= 32
332 if self.cpu.backend_name.startswith('zarch') or \
333 self.cpu.backend_name.startswith('ppc'):
334 # the allocation always allocates the register
335 # into the return register. (e.g. r3 on ppc)
336 # the next malloc_nursery will move r3 to the
337 # frame manager, thus the two bits will be on the frame
338 fixed_size += 4
330339 assert len(frame.jf_gcmap) == expected_size
331 if self.cpu.IS_64_BIT:
332 exp_idx = self.cpu.JITFRAME_FIXED_SIZE + 1 # +1 from i0
333 else:
334 assert frame.jf_gcmap[idx]
335 exp_idx = self.cpu.JITFRAME_FIXED_SIZE - 32 * idx + 1 # +1 from i0
336 assert frame.jf_gcmap[idx] == (1 << (exp_idx + 1)) | (1 << exp_idx)
340 # check that we have two bits set, and that they are in two
341 # registers (p0 and p1 are moved away when doing p2, but not
342 # spilled, just moved to different registers)
343 bits = [n for n in range(fixed_size)
344 if frame.jf_gcmap[idx] & (1<<n)]
345 assert len(bits) == 2
337346
338347 self.cpu = self.getcpu(check)
339348 ops = '''
253253 jump()
254254 """, """
255255 [p1]
256 p0 = call_malloc_gc(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
257 descr=malloc_fixedsize_descr)
256 p0 = call_r(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
257 descr=malloc_fixedsize_descr)
258 check_memory_error(p0)
258259 jump()
259260 """)
260261
266267 jump()
267268 """, """
268269 []
269 p0 = call_malloc_gc(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
270 descr=malloc_fixedsize_descr)
271 p1 = call_malloc_gc(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
272 descr=malloc_fixedsize_descr)
270 p0 = call_r(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
271 descr=malloc_fixedsize_descr)
272 check_memory_error(p0)
273 p1 = call_r(ConstClass(malloc_fixedsize), %(sdescr.size)d,\
274 descr=malloc_fixedsize_descr)
275 check_memory_error(p1)
273276 jump()
274277 """)
275278
280283 jump()
281284 """, """
282285 []
283 p0 = call_malloc_gc(ConstClass(malloc_array), \
286 p0 = call_r(ConstClass(malloc_array), \
284287 %(adescr.basesize)d, \
285288 10, \
286289 %(adescr.itemsize)d, \
287290 %(adescr.lendescr.offset)d, \
288291 descr=malloc_array_descr)
292 check_memory_error(p0)
289293 jump()
290294 """)
291295 ## should ideally be:
292 ## p0 = call_malloc_gc(ConstClass(malloc_fixedsize), \
296 ## p0 = call_r(ConstClass(malloc_fixedsize), \
293297 ## %(adescr.basesize + 10 * adescr.itemsize)d, \
294298 ## descr=malloc_fixedsize_descr)
295299 ## setfield_gc(p0, 10, descr=alendescr)
301305 jump()
302306 """, """
303307 [i1]
304 p0 = call_malloc_gc(ConstClass(malloc_array), \
308 p0 = call_r(ConstClass(malloc_array), \
305309 %(adescr.basesize)d, \
306310 i1, \
307311 %(adescr.itemsize)d, \
308312 %(adescr.lendescr.offset)d, \
309313 descr=malloc_array_descr)
314 check_memory_error(p0)
310315 jump()
311316 """)
312317
317322 jump()
318323 """, """
319324 [p1]
320 p0 = call_malloc_gc(ConstClass(malloc_fixedsize), 102, \
325 p0 = call_r(ConstClass(malloc_fixedsize), 102, \
321326 descr=malloc_fixedsize_descr)
327 check_memory_error(p0)
322328 gc_store(p0, 0, ConstClass(o_vtable), %(vtable_descr.field_size)s)
323329 jump()
324330 """)
330336 jump()
331337 """, """
332338 [i1]
333 p0 = call_malloc_gc(ConstClass(malloc_array), \
339 p0 = call_r(ConstClass(malloc_array), \
334340 %(strdescr.basesize)d, \
335341 i1, \
336342 %(strdescr.itemsize)d, \
337343 %(strlendescr.offset)d, \
338344 descr=malloc_array_descr)
345 check_memory_error(p0)
339346 jump()
340347 """)
341348
346353 jump()
347354 """, """
348355 [i1]
349 p0 = call_malloc_gc(ConstClass(malloc_array), \
356 p0 = call_r(ConstClass(malloc_array), \
350357 %(unicodedescr.basesize)d, \
351358 10, \
352359 %(unicodedescr.itemsize)d, \
353360 %(unicodelendescr.offset)d, \
354361 descr=malloc_array_descr)
362 check_memory_error(p0)
355363 jump()
356364 """)
357365 ## should ideally be:
358 ## p0 = call_malloc_gc(ConstClass(malloc_fixedsize), \
366 ## p0 = call_r(ConstClass(malloc_fixedsize), \
359367 ## %(unicodedescr.basesize + \
360368 ## 10 * unicodedescr.itemsize)d, \
361369 ## descr=malloc_fixedsize_descr)
544552 jump(i0)
545553 """, """
546554 [i0, p1]
547 p0 = call_malloc_gc(ConstClass(malloc_array_nonstandard), \
555 p0 = call_r(ConstClass(malloc_array_nonstandard), \
548556 64, 8, \
549557 %(nonstd_descr.lendescr.offset)d, \
550558 6464, i0, \
551559 descr=malloc_array_nonstandard_descr)
560 check_memory_error(p0)
552561 cond_call_gc_wb_array(p0, i0, descr=wbdescr)
553562 gc_store_indexed(p0, i0, p1, 8, 64, 8)
554563 jump(i0)
562571 jump()
563572 """, """
564573 []
565 p0 = call_malloc_gc(ConstClass(malloc_array), 1, \
574 p0 = call_r(ConstClass(malloc_array), 1, \
566575 %(bdescr.tid)d, 103, \
567576 descr=malloc_array_descr)
577 check_memory_error(p0)
568578 jump()
569579 """)
570580
600610 jump()
601611 """, """
602612 []
603 p0 = call_malloc_gc(ConstClass(malloc_array), 1, \
613 p0 = call_r(ConstClass(malloc_array), 1, \
604614 %(bdescr.tid)d, 20000000, \
605615 descr=malloc_array_descr)
616 check_memory_error(p0)
606617 jump()
607618 """)
608619
627638 jump()
628639 """, """
629640 [p1]
630 p0 = call_malloc_gc(ConstClass(malloc_big_fixedsize), 104, 9315, \
641 p0 = call_r(ConstClass(malloc_big_fixedsize), 104, 9315, \
631642 descr=malloc_big_fixedsize_descr)
643 check_memory_error(p0)
632644 gc_store(p0, 0, 0, %(vtable_descr.field_size)s)
633645 jump()
634646 """)
635647
636648 def test_rewrite_assembler_newstr_newunicode(self):
649 # note: strdescr.basesize already contains the extra final character,
650 # so that's why newstr(14) is rounded up to 'basesize+15' and not
651 # 'basesize+16'.
637652 self.check_rewrite("""
638653 [i2]
639654 p0 = newstr(14)
644659 """, """
645660 [i2]
646661 p0 = call_malloc_nursery( \
647 %(strdescr.basesize + 16 * strdescr.itemsize + \
662 %(strdescr.basesize + 15 * strdescr.itemsize + \
648663 unicodedescr.basesize + 10 * unicodedescr.itemsize)d)
649664 gc_store(p0, 0, %(strdescr.tid)d, %(tiddescr.field_size)s)
650665 gc_store(p0, %(strlendescr.offset)s, 14, %(strlendescr.field_size)s)
651666 gc_store(p0, 0, 0, %(strhashdescr.field_size)s)
652 p1 = nursery_ptr_increment(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d)
667 p1 = nursery_ptr_increment(p0, %(strdescr.basesize + 15 * strdescr.itemsize)d)
653668 gc_store(p1, 0, %(unicodedescr.tid)d, %(tiddescr.field_size)s)
654669 gc_store(p1, %(unicodelendescr.offset)s, 10, %(unicodelendescr.field_size)s)
655670 gc_store(p1, 0, 0, %(unicodehashdescr.field_size)s)
12271242 # 'i3 = gc_load_i(p0,i5,%(unicodedescr.itemsize)d)'],
12281243 [True, (4,), 'i3 = strgetitem(p0,i1)' '->'
12291244 'i3 = gc_load_indexed_i(p0,i1,1,'
1230 '%(strdescr.basesize)d,1)'],
1245 '%(strdescr.basesize-1)d,1)'],
12311246 #[False, (4,), 'i3 = strgetitem(p0,i1)' '->'
1232 # 'i5 = int_add(i1, %(strdescr.basesize)d);'
1247 # 'i5 = int_add(i1, %(strdescr.basesize-1)d);'
12331248 # 'i3 = gc_load_i(p0,i5,1)'],
12341249 ## setitem str/unicode
12351250 [True, (4,), 'i3 = strsetitem(p0,i1,0)' '->'
12361251 'i3 = gc_store_indexed(p0,i1,0,1,'
1237 '%(strdescr.basesize)d,1)'],
1252 '%(strdescr.basesize-1)d,1)'],
12381253 [True, (2,4), 'i3 = unicodesetitem(p0,i1,0)' '->'
12391254 'i3 = gc_store_indexed(p0,i1,0,'
12401255 '%(unicodedescr.itemsize)d,'
22 from rpython.rlib.jit import JitDriver, unroll_parameters, set_param
33 from rpython.rlib.jit import PARAMETERS, dont_look_inside
44 from rpython.rlib.jit import promote, _get_virtualizable_token
5 from rpython.rlib import jit_hooks, rposix
5 from rpython.rlib import jit_hooks, rposix, rgc
66 from rpython.rlib.objectmodel import keepalive_until_here
77 from rpython.rlib.rthread import ThreadLocalReference, ThreadLocalField
88 from rpython.jit.backend.detect_cpu import getcpuclass
1010 from rpython.jit.codewriter.policy import StopAtXPolicy
1111 from rpython.config.config import ConfigError
1212 from rpython.translator.tool.cbuild import ExternalCompilationInfo
13 from rpython.rtyper.lltypesystem import lltype, rffi
13 from rpython.rtyper.lltypesystem import lltype, rffi, rstr
14 from rpython.rlib.rjitlog import rjitlog as jl
1415
1516
1617 class TranslationTest(CCompiledMixin):
2728 # - floats neg and abs
2829 # - cast_int_to_float
2930 # - llexternal with macro=True
31 # - extra place for the zero after STR instances
3032
3133 class BasicFrame(object):
3234 _virtualizable_ = ['i']
3941
4042 eci = ExternalCompilationInfo(post_include_bits=['''
4143 #define pypy_my_fabs(x) fabs(x)
42 '''])
44 '''], includes=['math.h'])
4345 myabs1 = rffi.llexternal('pypy_my_fabs', [lltype.Float],
4446 lltype.Float, macro=True, releasegil=False,
4547 compilation_info=eci)
4749 lltype.Float, macro=True, releasegil=True,
4850 compilation_info=eci)
4951
52 @jl.returns(jl.MP_FILENAME,
53 jl.MP_LINENO,
54 jl.MP_INDEX)
55 def get_location():
56 return ("/home.py",0,0)
57
5058 jitdriver = JitDriver(greens = [],
51 reds = ['total', 'frame', 'j'],
52 virtualizables = ['frame'])
59 reds = ['total', 'frame', 'prev_s', 'j'],
60 virtualizables = ['frame'],
61 get_location = get_location)
5362 def f(i, j):
5463 for param, _ in unroll_parameters:
5564 defl = PARAMETERS[param]
5968 total = 0
6069 frame = Frame(i)
6170 j = float(j)
71 prev_s = rstr.mallocstr(16)
6272 while frame.i > 3:
63 jitdriver.can_enter_jit(frame=frame, total=total, j=j)
64 jitdriver.jit_merge_point(frame=frame, total=total, j=j)
73 jitdriver.can_enter_jit(frame=frame, total=total, j=j,
74 prev_s=prev_s)
75 jitdriver.jit_merge_point(frame=frame, total=total, j=j,
76 prev_s=prev_s)
6577 _get_virtualizable_token(frame)
6678 total += frame.i
6779 if frame.i >= 20:
7385 k = myabs1(myabs2(j))
7486 if k - abs(j): raise ValueError
7587 if k - abs(-j): raise ValueError
88 s = rstr.mallocstr(16)
89 rgc.ll_write_final_null_char(s)
90 rgc.ll_write_final_null_char(prev_s)
91 if (frame.i & 3) == 0:
92 prev_s = s
7693 return chr(total % 253)
7794 #
7895 class Virt2(object):
232249 assert res == 2
233250 # one for loop and one for the prologue, no unrolling
234251
252 def test_flush_trace_counts(self):
253 driver = JitDriver(greens = [], reds = ['i'])
254
255 def f():
256 i = 0
257 while i < 100000:
258 driver.jit_merge_point(i=i)
259 i += 1
260
261 def main():
262 jit_hooks.stats_set_debug(None, True)
263 f()
264 jl.stats_flush_trace_counts(None)
265 return 0
266
267 res = self.meta_interp(main, [])
268 assert res == 0
235269
236270 class TranslationRemoveTypePtrTest(CCompiledMixin):
237271 CPUClass = getcpuclass()
227227 def bh_newstr(self, length):
228228 raise NotImplementedError
229229 def bh_newunicode(self, length):
230 raise NotImplementedError
231 def bh_new_raw_buffer(self, size):
232230 raise NotImplementedError
233231
234232 def bh_arraylen_gc(self, array, arraydescr):
993993 basesize, itemsize, _ = symbolic.get_array_token(rstr.STR,
994994 self.cpu.translate_support_code)
995995 assert itemsize == 1
996 basesize -= 1 # for the extra null character
996997 scale = 0
997998
998999 self._emit_load_for_copycontent(r.r0, src_ptr_loc, src_ofs_loc, scale)
10241025
10251026 _mixin_ = True
10261027
1027 def emit_call_malloc_gc(self, op, arglocs, regalloc):
1028 self._emit_call(op, arglocs)
1029 self.propagate_memoryerror_if_r3_is_null()
1028 def emit_check_memory_error(self, op, arglocs, regalloc):
1029 self.propagate_memoryerror_if_reg_is_null(arglocs[0])
10301030
10311031 def emit_call_malloc_nursery(self, op, arglocs, regalloc):
10321032 # registers r.RES and r.RSZ are allocated for this call
3535 from rpython.rlib.jit import AsmInfo
3636 from rpython.rlib.objectmodel import compute_unique_id
3737 from rpython.rlib.rarithmetic import r_uint
38 from rpython.rlib.rjitlog import rjitlog as jl
3839
3940 memcpy_fn = rffi.llexternal('memcpy', [llmemory.Address, llmemory.Address,
4041 rffi.SIZE_T], lltype.Void,
411412 # Check that we don't get NULL; if we do, we always interrupt the
412413 # current loop, as a "good enough" approximation (same as
413414 # emit_call_malloc_gc()).
414 self.propagate_memoryerror_if_r3_is_null()
415 self.propagate_memoryerror_if_reg_is_null(r.r3)
415416
416417 mc.mtlr(r.RCS1.value) # restore LR
417418 self._pop_core_regs_from_jitframe(mc, saved_regs)
593594 self.wb_slowpath[withcards + 2 * withfloats] = rawstart
594595
595596 def _build_propagate_exception_path(self):
596 if not self.cpu.propagate_exception_descr:
597 return
598
599597 self.mc = PPCBuilder()
600598 #
601599 # read and reset the current exception
796794 looptoken._ppc_fullsize = full_size
797795 looptoken._ppc_ops_offset = ops_offset
798796 looptoken._ll_function_addr = rawstart
797
799798 if logger:
800 logger.log_loop(inputargs, operations, 0, "rewritten",
801 name=loopname, ops_offset=ops_offset)
799 log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc)
800 log.write(inputargs, operations, ops_offset=ops_offset)
801
802 # legacy
803 if logger.logger_ops:
804 logger.logger_ops.log_loop(inputargs, operations, 0,
805 "rewritten", name=loopname,
806 ops_offset=ops_offset)
802807
803808 self.fixup_target_tokens(rawstart)
804809 self.teardown()
865870 ops_offset = self.mc.ops_offset
866871 frame_depth = max(self.current_clt.frame_info.jfi_frame_depth,
867872 frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE)
873
868874 if logger:
869 logger.log_bridge(inputargs, operations, "rewritten",
870 ops_offset=ops_offset)
875 log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc)
876 log.write(inputargs, operations, ops_offset)
877 # log that the already written bridge is stitched to a descr!
878 logger.log_patch_guard(descr_number, rawstart)
879
880 # legacy
881 if logger.logger_ops:
882 logger.logger_ops.log_bridge(inputargs, operations, "rewritten",
883 faildescr, ops_offset=ops_offset)
884
871885 self.fixup_target_tokens(rawstart)
872886 self.update_frame_depth(frame_depth)
873887 self.teardown()
13251339 pmc.b(offset) # jump always
13261340 pmc.overwrite()
13271341
1328 def propagate_memoryerror_if_r3_is_null(self):
1329 # if self.propagate_exception_path == 0 (tests), this may jump to 0
1330 # and segfaults. too bad. the alternative is to continue anyway
1331 # with r3==0, but that will segfault too.
1332 self.mc.cmp_op(0, r.r3.value, 0, imm=True)
1342 def propagate_memoryerror_if_reg_is_null(self, reg_loc):
1343 self.mc.cmp_op(0, reg_loc.value, 0, imm=True)
13331344 self.mc.b_cond_abs(self.propagate_exception_path, c.EQ)
13341345
13351346 def write_new_force_index(self):
532532 res = self.rm.force_allocate_reg(op)
533533 return [res]
534534
535 def prepare_call_malloc_gc(self, op):
536 return self._prepare_call(op)
535 def prepare_check_memory_error(self, op):
536 loc = self.ensure_reg(op.getarg(0))
537 return [loc]
537538
538539 def _prepare_guard(self, op, args=None):
539540 if args is None:
0 import re
1 import os
2 from rpython.rlib import debug
3 from rpython.jit.tool.oparser import pure_parse
4 from rpython.jit.metainterp import logger
5 from rpython.jit.metainterp.typesystem import llhelper
6 from rpython.rlib.rjitlog import rjitlog as jl
7 from StringIO import StringIO
8 from rpython.jit.metainterp.optimizeopt.util import equaloplists
9 from rpython.jit.metainterp.history import AbstractDescr, JitCellToken, BasicFailDescr, BasicFinalDescr
10 from rpython.jit.backend.model import AbstractCPU
11 from rpython.rlib.jit import JitDriver
12 from rpython.rlib.objectmodel import always_inline
13 from rpython.jit.metainterp.test.support import LLJitMixin
14 from rpython.rlib.rjitlog import rjitlog
15 import tempfile
16
17 class LoggerTest(LLJitMixin):
18
19 def test_explicit_enable(self, tmpdir):
20 file = tmpdir.join('jitlog')
21 fileno = os.open(file.strpath, os.O_WRONLY | os.O_CREAT)
22 enable_jitlog = lambda: rjitlog.enable_jitlog(fileno)
23 f = self.run_sample_loop(enable_jitlog)
24 self.meta_interp(f, [10, 0])
25
26 assert os.path.exists(file.strpath)
27 with file.open('rb') as f:
28 # check the file header
29 assert f.read(3) == jl.MARK_JITLOG_HEADER + jl.JITLOG_VERSION_16BIT_LE
30 assert len(f.read()) > 0
31
32 def test_env(self, monkeypatch, tmpdir):
33 file = tmpdir.join('jitlog')
34 monkeypatch.setenv("JITLOG", file.strpath)
35 f = self.run_sample_loop(None)
36 self.meta_interp(f, [10,0])
37 assert os.path.exists(file.strpath)
38 with file.open('rb') as fd:
39 # check the file header
40 assert fd.read(3) == jl.MARK_JITLOG_HEADER + jl.JITLOG_VERSION_16BIT_LE
41 assert len(fd.read()) > 0
42
43 def test_version(self, monkeypatch, tmpdir):
44 file = tmpdir.join('jitlog')
45 monkeypatch.setattr(jl, 'JITLOG_VERSION_16BIT_LE', '\xff\xfe')
46 monkeypatch.setenv("JITLOG", file.strpath)
47 f = self.run_sample_loop(None)
48 self.meta_interp(f, [10,0])
49 assert os.path.exists(file.strpath)
50 with file.open('rb') as fd:
51 # check the file header
52 assert fd.read(3) == jl.MARK_JITLOG_HEADER + '\xff\xfe'
53 assert len(fd.read()) > 0
54
55 def test_version(self, monkeypatch, tmpdir):
56 file = tmpdir.join('jitlog')
57 monkeypatch.setattr(jl, 'JITLOG_VERSION_16BIT_LE', '\xff\xfe')
58 monkeypatch.setenv("JITLOG", file.strpath)
59 f = self.run_sample_loop(None)
60 self.meta_interp(f, [10,0])
61 assert os.path.exists(file.strpath)
62 with file.open('rb') as fd:
63 # check the file header
64 assert fd.read(3) == jl.MARK_JITLOG_HEADER + '\xff\xfe'
65 assert len(fd.read()) > 0
66
67 def run_sample_loop(self, func, myjitdriver = None):
68 if not myjitdriver:
69 myjitdriver = JitDriver(greens = [], reds = 'auto')
70 def f(y, x):
71 res = 0
72 if func:
73 func()
74 while y > 0:
75 myjitdriver.jit_merge_point()
76 res += x
77 y -= 1
78 return res
79 return f
2121 from rpython.jit.backend.detect_cpu import autodetect
2222 from rpython.jit.backend.llsupport import jitframe
2323 from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU
24 from rpython.jit.backend.llsupport.llmodel import MissingLatestDescrError
2425 from rpython.jit.backend.llsupport.rewrite import GcRewriterAssembler
2526
2627
28242825 from rpython.rlib.rarithmetic import r_singlefloat
28252826 from rpython.translator.c import primitive
28262827
2828
28272829 def same_as_for_box(b):
28282830 if b.type == 'i':
28292831 return rop.SAME_AS_I
28342836
28352837 cpu = self.cpu
28362838 rnd = random.Random(525)
2839 seed = py.test.config.option.randomseed
2840 print("random seed %d" % seed)
28372841
28382842 ALL_TYPES = [
28392843 (types.ulong, lltype.Unsigned),
43874391 'float', descr=calldescr)
43884392 assert longlong.getrealfloat(res) == expected
43894393
4394 def test_check_memory_error(self):
4395 self.execute_operation(
4396 rop.CHECK_MEMORY_ERROR, [InputArgInt(12345)], 'void')
4397 py.test.raises(MissingLatestDescrError, self.execute_operation,
4398 rop.CHECK_MEMORY_ERROR, [InputArgInt(0)], 'void')
4399
43904400 def test_compile_loop_with_target(self):
43914401 looptoken = JitCellToken()
43924402 targettoken1 = TargetToken()
11 from rpython.rlib import jit
22 from rpython.rtyper.annlowlevel import llhelper
33 from rpython.rtyper.lltypesystem import lltype, rffi
4 from rpython.rlib.rvmprof import cintf
4 from rpython.rlib.rvmprof import cintf, vmprof_execute_code, register_code,\
5 register_code_object_class, _get_vmprof
56 from rpython.jit.backend.x86.arch import WORD
67 from rpython.jit.codewriter.policy import JitPolicy
78
9
810 class BaseRVMProfTest(object):
9 def test_one(self):
10 py.test.skip("needs thread-locals in the JIT, which is only available "
11 "after translation")
11
12 def setup_method(self, meth):
1213 visited = []
1314
1415 def helper():
16 trace = []
1517 stack = cintf.vmprof_tl_stack.getraw()
16 if stack:
17 # not during tracing
18 visited.append(stack.c_value)
19 else:
20 visited.append(0)
18 while stack:
19 trace.append((stack.c_kind, stack.c_value))
20 stack = stack.c_next
21 visited.append(trace)
2122
2223 llfn = llhelper(lltype.Ptr(lltype.FuncType([], lltype.Void)), helper)
2324
24 driver = jit.JitDriver(greens=[], reds='auto')
25 class CodeObj(object):
26 def __init__(self, name):
27 self.name = name
2528
26 def f(n):
29 def get_code_fn(codes, code, arg, c):
30 return code
31
32 def get_name(code):
33 return "foo"
34
35 _get_vmprof().use_weaklist = False
36 register_code_object_class(CodeObj, get_name)
37
38 self.misc = visited, llfn, CodeObj, get_code_fn, get_name
39
40
41 def teardown_method(self, meth):
42 del _get_vmprof().use_weaklist
43
44
45 def test_simple(self):
46 visited, llfn, CodeObj, get_code_fn, get_name = self.misc
47 driver = jit.JitDriver(greens=['code'], reds=['c', 'i', 'n', 'codes'])
48
49 @vmprof_execute_code("main", get_code_fn,
50 _hack_update_stack_untranslated=True)
51 def f(codes, code, n, c):
2752 i = 0
2853 while i < n:
29 driver.jit_merge_point()
54 driver.jit_merge_point(code=code, c=c, i=i, codes=codes, n=n)
55 if code.name == "main":
56 c = f(codes, codes[1], 1, c)
57 else:
58 llfn()
59 c -= 1
3060 i += 1
31 llfn()
61 return c
3262
33 class Hooks(jit.JitHookInterface):
34 def after_compile(self, debug_info):
35 self.raw_start = debug_info.asminfo.rawstart
36
37 hooks = Hooks()
63 def main(n):
64 codes = [CodeObj("main"), CodeObj("not main")]
65 for code in codes:
66 register_code(code, get_name)
67 return f(codes, codes[0], n, 8)
3868
3969 null = lltype.nullptr(cintf.VMPROFSTACK)
40 cintf.vmprof_tl_stack.setraw(null) # make it empty
41 self.meta_interp(f, [10], policy=JitPolicy(hooks))
42 v = set(visited)
43 assert 0 in v
44 v.remove(0)
45 assert len(v) == 1
46 assert 0 <= list(v)[0] - hooks.raw_start <= 10*1024
47 assert cintf.vmprof_tl_stack.getraw() == null
48 # ^^^ make sure we didn't leave anything dangling
70 cintf.vmprof_tl_stack.setraw(null)
71 self.meta_interp(main, [30], inline=True)
72 assert visited[:3] == [[(1, 12), (1, 8)], [(1, 12), (1, 8)], [(1, 12), (1, 8)]]
73
74
75 def test_leaving_with_exception(self):
76 visited, llfn, CodeObj, get_code_fn, get_name = self.misc
77 driver = jit.JitDriver(greens=['code'], reds=['c', 'i', 'n', 'codes'])
78
79 class MyExc(Exception):
80 def __init__(self, c):
81 self.c = c
82
83 @vmprof_execute_code("main", get_code_fn,
84 _hack_update_stack_untranslated=True)
85 def f(codes, code, n, c):
86 i = 0
87 while i < n:
88 driver.jit_merge_point(code=code, c=c, i=i, codes=codes, n=n)
89 if code.name == "main":
90 try:
91 f(codes, codes[1], 1, c)
92 except MyExc as e:
93 c = e.c
94 else:
95 llfn()
96 c -= 1
97 i += 1
98 raise MyExc(c)
99
100 def main(n):
101 codes = [CodeObj("main"), CodeObj("not main")]
102 for code in codes:
103 register_code(code, get_name)
104 try:
105 f(codes, codes[0], n, 8)
106 except MyExc as e:
107 return e.c
108
109 null = lltype.nullptr(cintf.VMPROFSTACK)
110 cintf.vmprof_tl_stack.setraw(null)
111 self.meta_interp(main, [30], inline=True)
112 assert visited[:3] == [[(1, 12), (1, 8)], [(1, 12), (1, 8)], [(1, 12), (1, 8)]]
113
114
115 def test_leaving_with_exception_in_blackhole(self):
116 visited, llfn, CodeObj, get_code_fn, get_name = self.misc
117 driver = jit.JitDriver(greens=['code'], reds=['c', 'i', 'n', 'codes'])
118
119 class MyExc(Exception):
120 def __init__(self, c):
121 self.c = c
122
123 @vmprof_execute_code("main", get_code_fn,
124 _hack_update_stack_untranslated=True)
125 def f(codes, code, n, c):
126 i = 0
127 while True:
128 driver.jit_merge_point(code=code, c=c, i=i, codes=codes, n=n)
129 if i >= n:
130 break
131 i += 1
132 if code.name == "main":
133 try:
134 f(codes, codes[1], 1, c)
135 except MyExc as e:
136 c = e.c
137 driver.can_enter_jit(code=code, c=c, i=i, codes=codes, n=n)
138 else:
139 llfn()
140 c -= 1
141 if c & 1: # a failing guard
142 pass
143 raise MyExc(c)
144
145 def main(n):
146 codes = [CodeObj("main"), CodeObj("not main")]
147 for code in codes:
148 register_code(code, get_name)
149 try:
150 f(codes, codes[0], n, 8)
151 except MyExc as e:
152 return e.c
153
154 null = lltype.nullptr(cintf.VMPROFSTACK)
155 cintf.vmprof_tl_stack.setraw(null)
156 self.meta_interp(main, [30], inline=True)
157 assert visited[:3] == [[(1, 12), (1, 8)], [(1, 12), (1, 8)], [(1, 12), (1, 8)]]
22 import py
33
44 from rpython.jit.backend.llsupport import symbolic, jitframe, rewrite
5 from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler,
6 DEBUG_COUNTER)
5 from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler, debug_bridge)
76 from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
87 from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
98 from rpython.jit.metainterp.history import (Const, VOID, ConstInt)
109 from rpython.jit.metainterp.history import AbstractFailDescr, INT, REF, FLOAT
1110 from rpython.jit.metainterp.compile import ResumeGuardDescr
11 from rpython.rlib.rjitlog import rjitlog as jl
1212 from rpython.rtyper.lltypesystem import lltype, rffi, rstr, llmemory
1313 from rpython.rtyper.lltypesystem.lloperation import llop
1414 from rpython.rtyper.annlowlevel import cast_instance_to_gcref
203203
204204 def _build_malloc_slowpath(self, kind):
205205 """ While arriving on slowpath, we have a gcpattern on stack 0.
206 The arguments are passed in eax and edi, as follows:
207
208 kind == 'fixed': nursery_head in eax and the size in edi - eax.
209
210 kind == 'str/unicode': length of the string to allocate in edi.
211
212 kind == 'var': length to allocate in edi, tid in eax,
206 The arguments are passed in ecx and edx, as follows:
207
208 kind == 'fixed': nursery_head in ecx and the size in (edx - ecx).
209
210 kind == 'str/unicode': length of the string to allocate in edx.
211
212 kind == 'var': length to allocate in edx, tid in ecx,
213213 and itemsize in the stack 1 (position esp+WORD).
214214
215 This function must preserve all registers apart from eax and edi.
215 This function must preserve all registers apart from ecx and edx.
216216 """
217217 assert kind in ['fixed', 'str', 'unicode', 'var']
218218 mc = codebuf.MachineCodeBlockWrapper()
219 self._push_all_regs_to_frame(mc, [eax, edi], self.cpu.supports_floats)
219 self._push_all_regs_to_frame(mc, [ecx, edx], self.cpu.supports_floats)
220220 # the caller already did push_gcmap(store=True)
221221 #
222222 if kind == 'fixed':
230230 mc.SUB_ri(esp.value, 16 - WORD) # restore 16-byte alignment
231231 # magically, the above is enough on X86_32 to reserve 3 stack places
232232 if kind == 'fixed':
233 mc.SUB_rr(edi.value, eax.value) # compute the size we want
234 # the arg is already in edi
233 mc.SUB_rr(edx.value, ecx.value) # compute the size we want
235234 if IS_X86_32:
236 mc.MOV_sr(0, edi.value)
235 mc.MOV_sr(0, edx.value) # store the length
237236 if hasattr(self.cpu.gc_ll_descr, 'passes_frame'):
238 mc.MOV_sr(WORD, ebp.value)
239 elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'):
240 # for tests only
241 mc.MOV_rr(esi.value, ebp.value)
237 mc.MOV_sr(WORD, ebp.value) # for tests only
238 else:
239 mc.MOV_rr(edi.value, edx.value) # length argument
240 if hasattr(self.cpu.gc_ll_descr, 'passes_frame'):
241 mc.MOV_rr(esi.value, ebp.value) # for tests only
242242 elif kind == 'str' or kind == 'unicode':
243243 if IS_X86_32:
244244 # stack layout: [---][---][---][ret].. with 3 free stack places
245 mc.MOV_sr(0, edi.value) # store the length
246 else:
247 pass # length already in edi
245 mc.MOV_sr(0, edx.value) # store the length
246 elif IS_X86_64:
247 mc.MOV_rr(edi.value, edx.value) # length argument
248248 else:
249249 if IS_X86_32:
250250 # stack layout: [---][---][---][ret][gcmap][itemsize]...
251 mc.MOV_sr(WORD * 2, edi.value) # store the length
252 mc.MOV_sr(WORD * 1, eax.value) # store the tid
253 mc.MOV_rs(edi.value, WORD * 5) # load the itemsize
254 mc.MOV_sr(WORD * 0, edi.value) # store the itemsize
251 mc.MOV_sr(WORD * 2, edx.value) # store the length
252 mc.MOV_sr(WORD * 1, ecx.value) # store the tid
253 mc.MOV_rs(edx.value, WORD * 5) # load the itemsize
254 mc.MOV_sr(WORD * 0, edx.value) # store the itemsize
255255 else:
256256 # stack layout: [---][ret][gcmap][itemsize]...
257 mc.MOV_rr(edx.value, edi.value) # length
258 mc.MOV_rr(esi.value, eax.value) # tid
257 # (already in edx) # length
258 mc.MOV_rr(esi.value, ecx.value) # tid
259259 mc.MOV_rs(edi.value, WORD * 3) # load the itemsize
260260 self.set_extra_stack_depth(mc, 16)
261261 mc.CALL(imm(follow_jump(addr)))
266266 mc.TEST_rr(eax.value, eax.value)
267267 mc.J_il(rx86.Conditions['Z'], 0xfffff) # patched later
268268 jz_location = mc.get_relative_pos()
269 mc.MOV_rr(ecx.value, eax.value)
269270 #
270271 nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr()
271 self._pop_all_regs_from_frame(mc, [eax, edi], self.cpu.supports_floats)
272 mc.MOV(edi, heap(nursery_free_adr)) # load this in EDI
272 self._pop_all_regs_from_frame(mc, [ecx, edx], self.cpu.supports_floats)
273 mc.MOV(edx, heap(nursery_free_adr)) # load this in EDX
273274 self.pop_gcmap(mc) # push_gcmap(store=True) done by the caller
274275 mc.RET()
275276 #
290291 return rawstart
291292
292293 def _build_propagate_exception_path(self):
293 if not self.cpu.propagate_exception_descr:
294 return # not supported (for tests, or non-translated)
295 #
296294 self.mc = codebuf.MachineCodeBlockWrapper()
297295 self.mc.force_frame_size(DEFAULT_FRAME_BYTES)
298296 #
491489 clt.frame_info.clear() # for now
492490
493491 if log:
492 number = looptoken.number
494493 operations = self._inject_debugging_code(looptoken, operations,
495 'e', looptoken.number)
494 'e', number)
496495
497496 regalloc = RegAlloc(self, self.cpu.translate_support_code)
498497 #
539538 looptoken._x86_fullsize = full_size
540539 looptoken._x86_ops_offset = ops_offset
541540 looptoken._ll_function_addr = rawstart + functionpos
541
542542 if logger:
543 logger.log_loop(inputargs, operations, 0, "rewritten",
544 name=loopname, ops_offset=ops_offset)
543 log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc)
544 log.write(inputargs, operations, ops_offset=ops_offset)
545
546 # legacy
547 if logger.logger_ops:
548 logger.logger_ops.log_loop(inputargs, operations, 0,
549 "rewritten", name=loopname,
550 ops_offset=ops_offset)
545551
546552 self.fixup_target_tokens(rawstart)
547553 self.teardown()
606612 ops_offset = self.mc.ops_offset
607613 frame_depth = max(self.current_clt.frame_info.jfi_frame_depth,
608614 frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE)
615
609616 if logger:
610 logger.log_bridge(inputargs, operations, "rewritten", faildescr,
611 ops_offset=ops_offset)
617 log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc)
618 log.write(inputargs, operations, ops_offset)
619 # log that the already written bridge is stitched to a descr!
620 logger.log_patch_guard(descr_number, rawstart)
621
622 # legacy
623 if logger.logger_ops:
624 logger.logger_ops.log_bridge(inputargs, operations, "rewritten",
625 faildescr, ops_offset=ops_offset)
626
612627 self.fixup_target_tokens(rawstart)
613628 self.update_frame_depth(frame_depth)
614629 self.teardown()
10481063 else:
10491064 assert mc.get_relative_pos() <= 13
10501065 mc.copy_to_raw_memory(oldadr)
1066 # log the redirection of the call_assembler_* operation
1067 jl.redirect_assembler(oldlooptoken, newlooptoken, target)
10511068
10521069 def dump(self, text):
10531070 if not self.verbose:
15171534
15181535 # ----------
15191536
1520 def genop_call_malloc_gc(self, op, arglocs, result_loc):
1521 self._genop_call(op, arglocs, result_loc)
1522 self.propagate_memoryerror_if_eax_is_null()
1523
1524 def propagate_memoryerror_if_eax_is_null(self):
1525 # if self.propagate_exception_path == 0 (tests), this may jump to 0
1526 # and segfaults. too bad. the alternative is to continue anyway
1527 # with eax==0, but that will segfault too.
1528 self.mc.TEST_rr(eax.value, eax.value)
1537 def genop_discard_check_memory_error(self, op, arglocs):
1538 reg = arglocs[0]
1539 self.mc.TEST(reg, reg)
15291540 if WORD == 4:
15301541 self.mc.J_il(rx86.Conditions['Z'], self.propagate_exception_path)
15311542 self.mc.add_pending_relocation()
16621673 scale = get_scale(factor_loc.value)
16631674 dest_addr = AddressLoc(base_loc, ofs_loc, scale, offset_loc.value)
16641675 self.save_into_mem(dest_addr, value_loc, size_loc)
1665
1666 def genop_discard_strsetitem(self, op, arglocs):
1667 base_loc, ofs_loc, val_loc = arglocs
1668 basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,
1669 self.cpu.translate_support_code)
1670 assert itemsize == 1
1671 dest_addr = AddressLoc(base_loc, ofs_loc, 0, basesize)
1672 self.mc.MOV8(dest_addr, val_loc.lowest8bits())
1673
1674 def genop_discard_unicodesetitem(self, op, arglocs):
1675 base_loc, ofs_loc, val_loc = arglocs
1676 basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE,
1677 self.cpu.translate_support_code)
1678 if itemsize == 4:
1679 self.mc.MOV32(AddressLoc(base_loc, ofs_loc, 2, basesize), val_loc)
1680 elif itemsize == 2:
1681 self.mc.MOV16(AddressLoc(base_loc, ofs_loc, 1, basesize), val_loc)
1682 else:
1683 assert 0, itemsize
16841676
16851677 # genop_discard_setfield_raw = genop_discard_setfield_gc
16861678
24402432
24412433 def malloc_cond(self, nursery_free_adr, nursery_top_adr, size, gcmap):
24422434 assert size & (WORD-1) == 0 # must be correctly aligned
2443 self.mc.MOV(eax, heap(nursery_free_adr))
2444 self.mc.LEA_rm(edi.value, (eax.value, size))
2445 self.mc.CMP(edi, heap(nursery_top_adr))
2435 self.mc.MOV(ecx, heap(nursery_free_adr))
2436 self.mc.LEA_rm(edx.value, (ecx.value, size))
2437 self.mc.CMP(edx, heap(nursery_top_adr))
24462438 self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later
24472439 jmp_adr = self.mc.get_relative_pos()
24482440 # save the gcmap
24512443 offset = self.mc.get_relative_pos() - jmp_adr
24522444 assert 0 < offset <= 127
24532445 self.mc.overwrite(jmp_adr-1, chr(offset))
2454 self.mc.MOV(heap(nursery_free_adr), edi)
2446 self.mc.MOV(heap(nursery_free_adr), edx)
24552447
24562448 def malloc_cond_varsize_frame(self, nursery_free_adr, nursery_top_adr,
24572449 sizeloc, gcmap):
2458 if sizeloc is eax:
2459 self.mc.MOV(edi, sizeloc)
2460 sizeloc = edi
2461 self.mc.MOV(eax, heap(nursery_free_adr))
2462 if sizeloc is edi:
2463 self.mc.ADD_rr(edi.value, eax.value)
2464 else:
2465 self.mc.LEA_ra(edi.value, (eax.value, sizeloc.value, 0, 0))
2466 self.mc.CMP(edi, heap(nursery_top_adr))
2450 if sizeloc is ecx:
2451 self.mc.MOV(edx, sizeloc)
2452 sizeloc = edx
2453 self.mc.MOV(ecx, heap(nursery_free_adr))
2454 if sizeloc is edx:
2455 self.mc.ADD_rr(edx.value, ecx.value)
2456 else:
2457 self.mc.LEA_ra(edx.value, (ecx.value, sizeloc.value, 0, 0))
2458 self.mc.CMP(edx, heap(nursery_top_adr))
24672459 self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later
24682460 jmp_adr = self.mc.get_relative_pos()
24692461 # save the gcmap
24722464 offset = self.mc.get_relative_pos() - jmp_adr
24732465 assert 0 < offset <= 127
24742466 self.mc.overwrite(jmp_adr-1, chr(offset))
2475 self.mc.MOV(heap(nursery_free_adr), edi)
2467 self.mc.MOV(heap(nursery_free_adr), edx)
24762468
24772469 def malloc_cond_varsize(self, kind, nursery_free_adr, nursery_top_adr,
24782470 lengthloc, itemsize, maxlength, gcmap,
24812473 assert isinstance(arraydescr, ArrayDescr)
24822474
24832475 # lengthloc is the length of the array, which we must not modify!
2484 assert lengthloc is not eax and lengthloc is not edi
2476 assert lengthloc is not ecx and lengthloc is not edx
24852477 if isinstance(lengthloc, RegLoc):
24862478 varsizeloc = lengthloc
24872479 else:
2488 self.mc.MOV(edi, lengthloc)
2489 varsizeloc = edi
2480 self.mc.MOV(edx, lengthloc)
2481 varsizeloc = edx
24902482
24912483 self.mc.CMP(varsizeloc, imm(maxlength))
24922484 self.mc.J_il8(rx86.Conditions['A'], 0) # patched later
24932485 jmp_adr0 = self.mc.get_relative_pos()
24942486
2495 self.mc.MOV(eax, heap(nursery_free_adr))
2487 self.mc.MOV(ecx, heap(nursery_free_adr))
24962488 if valid_addressing_size(itemsize):
24972489 shift = get_scale(itemsize)
24982490 else:
2499 shift = self._imul_const_scaled(self.mc, edi.value,
2491 shift = self._imul_const_scaled(self.mc, edx.value,
25002492 varsizeloc.value, itemsize)
2501 varsizeloc = edi
2502
2503 # now varsizeloc is a register != eax. The size of
2493 varsizeloc = edx
2494
2495 # now varsizeloc is a register != ecx. The size of
25042496 # the variable part of the array is (varsizeloc << shift)
25052497 assert arraydescr.basesize >= self.gc_minimal_size_in_nursery
25062498 constsize = arraydescr.basesize + self.gc_size_of_header
25072499 force_realignment = (itemsize % WORD) != 0
25082500 if force_realignment:
25092501 constsize += WORD - 1
2510 self.mc.LEA_ra(edi.value, (eax.value, varsizeloc.value, shift,
2502 self.mc.LEA_ra(edx.value, (ecx.value, varsizeloc.value, shift,
25112503 constsize))
25122504 if force_realignment:
2513 self.mc.AND_ri(edi.value, ~(WORD - 1))
2514 # now edi contains the total size in bytes, rounded up to a multiple
2505 self.mc.AND_ri(edx.value, ~(WORD - 1))
2506 # now edx contains the total size in bytes, rounded up to a multiple
25152507 # of WORD, plus nursery_free_adr
2516 self.mc.CMP(edi, heap(nursery_top_adr))
2508 self.mc.CMP(edx, heap(nursery_top_adr))
25172509 self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later
25182510 jmp_adr1 = self.mc.get_relative_pos()
25192511 #
25242516 self.push_gcmap(self.mc, gcmap, store=True)
25252517 if kind == rewrite.FLAG_ARRAY:
25262518 self.mc.MOV_si(WORD, itemsize)
2527 self.mc.MOV(edi, lengthloc)
2528 self.mc.MOV_ri(eax.value, arraydescr.tid)
2519 self.mc.MOV(edx, lengthloc)
2520 self.mc.MOV_ri(ecx.value, arraydescr.tid)
25292521 addr = self.malloc_slowpath_varsize
25302522 else:
25312523 if kind == rewrite.FLAG_STR:
25332525 else:
25342526 assert kind == rewrite.FLAG_UNICODE
25352527 addr = self.malloc_slowpath_unicode
2536 self.mc.MOV(edi, lengthloc)
2528 self.mc.MOV(edx, lengthloc)
25372529 self.mc.CALL(imm(follow_jump(addr)))
25382530 self.mc.JMP_l8(0) # jump to done, patched later
25392531 jmp_location = self.mc.get_relative_pos()
25432535 self.mc.overwrite(jmp_adr1-1, chr(offset))
25442536 self.mc.force_frame_size(DEFAULT_FRAME_BYTES)
25452537 # write down the tid, but not if it's the result of the CALL
2546 self.mc.MOV(mem(eax, 0), imm(arraydescr.tid))
2538 self.mc.MOV(mem(ecx, 0), imm(arraydescr.tid))
25472539 # while we're at it, this line is not needed if we've done the CALL
2548 self.mc.MOV(heap(nursery_free_adr), edi)
2540 self.mc.MOV(heap(nursery_free_adr), edx)
25492541 #
25502542 offset = self.mc.get_relative_pos() - jmp_location
25512543 assert 0 < offset <= 127
901901 consider_call_release_gil_i = _consider_call_release_gil
902902 consider_call_release_gil_f = _consider_call_release_gil
903903 consider_call_release_gil_n = _consider_call_release_gil
904
905 def consider_call_malloc_gc(self, op):
906 self._consider_call(op)
904
905 def consider_check_memory_error(self, op):
906 x = self.rm.make_sure_var_in_reg(op.getarg(0))
907 self.perform_discard(op, [x])
907908
908909 def _consider_call_assembler(self, op):
909910 locs = self.locs_for_call_assembler(op)
951952 size_box = op.getarg(0)
952953 assert isinstance(size_box, ConstInt)
953954 size = size_box.getint()
954 # looking at the result
955 self.rm.force_allocate_reg(op, selected_reg=eax)
956 #
957 # We need edi as a temporary, but otherwise don't save any more
955 # hint: try to move unrelated registers away from eax and edx now
956 self.rm.spill_or_move_registers_before_call([ecx, edx])
957 # the result will be in ecx
958 self.rm.force_allocate_reg(op, selected_reg=ecx)
959 #
960 # We need edx as a temporary, but otherwise don't save any more
958961 # register. See comments in _build_malloc_slowpath().
959962 tmp_box = TempVar()
960 self.rm.force_allocate_reg(tmp_box, selected_reg=edi)
961 gcmap = self.get_gcmap([eax, edi]) # allocate the gcmap *before*
963 self.rm.force_allocate_reg(tmp_box, selected_reg=edx)
964 gcmap = self.get_gcmap([ecx, edx]) # allocate the gcmap *before*
962965 self.rm.possibly_free_var(tmp_box)
963966 #
964967 gc_ll_descr = self.assembler.cpu.gc_ll_descr
971974 size_box = op.getarg(0)
972975 assert not isinstance(size_box, Const) # we cannot have a const here!
973976 # sizeloc must be in a register, but we can free it now
974 # (we take care explicitly of conflicts with eax or edi)
977 # (we take care explicitly of conflicts with ecx or edx)
975978 sizeloc = self.rm.make_sure_var_in_reg(size_box)
979 self.rm.spill_or_move_registers_before_call([ecx, edx]) # sizeloc safe
976980 self.rm.possibly_free_var(size_box)
977 # the result will be in eax
978 self.rm.force_allocate_reg(op, selected_reg=eax)
979 # we need edi as a temporary
981 # the result will be in ecx
982 self.rm.force_allocate_reg(op, selected_reg=ecx)
983 # we need edx as a temporary
980984 tmp_box = TempVar()
981 self.rm.force_allocate_reg(tmp_box, selected_reg=edi)
982 gcmap = self.get_gcmap([eax, edi]) # allocate the gcmap *before*
985 self.rm.force_allocate_reg(tmp_box, selected_reg=edx)
986 gcmap = self.get_gcmap([ecx, edx]) # allocate the gcmap *before*
983987 self.rm.possibly_free_var(tmp_box)
984988 #
985989 gc_ll_descr = self.assembler.cpu.gc_ll_descr
9961000 arraydescr = op.getdescr()
9971001 length_box = op.getarg(2)
9981002 assert not isinstance(length_box, Const) # we cannot have a const here!
999 # the result will be in eax
1000 self.rm.force_allocate_reg(op, selected_reg=eax)
1001 # we need edi as a temporary
1003 # can only use spill_or_move_registers_before_call() as a hint if
1004 # we are sure that length_box stays alive and won't be freed now
1005 # (it should always be the case, see below, but better safe than sorry)
1006 if self.rm.stays_alive(length_box):
1007 self.rm.spill_or_move_registers_before_call([ecx, edx])
1008 # the result will be in ecx
1009 self.rm.force_allocate_reg(op, selected_reg=ecx)
1010 # we need edx as a temporary
10021011 tmp_box = TempVar()
1003 self.rm.force_allocate_reg(tmp_box, selected_reg=edi)
1004 gcmap = self.get_gcmap([eax, edi]) # allocate the gcmap *before*
1012 self.rm.force_allocate_reg(tmp_box, selected_reg=edx)
1013 gcmap = self.get_gcmap([ecx, edx]) # allocate the gcmap *before*
10051014 self.rm.possibly_free_var(tmp_box)
10061015 # length_box always survives: it's typically also present in the
10071016 # next operation that will copy it inside the new array. It's
1008 # fine to load it from the stack too, as long as it's != eax, edi.
1017 # fine to load it from the stack too, as long as it is != ecx, edx.
10091018 lengthloc = self.rm.loc(length_box)
10101019 self.rm.possibly_free_var(length_box)
10111020 #
12091218 ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR,
12101219 self.translate_support_code)
12111220 assert itemsize == 1
1221 ofs_items -= 1 # for the extra null character
12121222 scale = 0
12131223 self.assembler.load_effective_addr(ofsloc, ofs_items, scale,
12141224 resloc, baseloc)
12241234 raise AssertionError("bad unicode item size")
12251235
12261236 def _consider_math_read_timestamp(self, op):
1237 # hint: try to move unrelated registers away from eax and edx now
1238 self.rm.spill_or_move_registers_before_call([eax, edx])
12271239 tmpbox_high = TempVar()
12281240 self.rm.force_allocate_reg(tmpbox_high, selected_reg=eax)
12291241 if longlong.is_64_bit:
113113 looptoken.compiled_loop_token.invalidate_positions = []
114114
115115 def get_all_loop_runs(self):
116 asm = self.assembler
116117 l = lltype.malloc(LOOP_RUN_CONTAINER,
117 len(self.assembler.loop_run_counters))
118 for i, ll_s in enumerate(self.assembler.loop_run_counters):
118 len(asm.loop_run_counters))
119 for i, ll_s in enumerate(asm.loop_run_counters):
119120 l[i].type = ll_s.type
120121 l[i].number = ll_s.number
121122 l[i].counter = ll_s.i
0
1 from rpython.jit.backend.x86.test.test_basic import Jit386Mixin
2 from rpython.jit.backend.test.jitlog_test import LoggerTest
3
4 class TestJitlog(Jit386Mixin, LoggerTest):
5 # for the individual tests see
6 # ====> ../../../test/jitlog_test.py
7 pass
146146 py.test.skip()
147147
148148 def test_reuse_scratch_register(self):
149 base_addr = 0xFEDCBA9876543210
149 base_addr = intmask(0xFEDCBA9876543210)
150150 cb = LocationCodeBuilder64()
151151 cb.begin_reuse_scratch_register()
152152 cb.MOV(ecx, heap(base_addr))
166166 # ------------------------------------------------------------
167167
168168 def test_64bit_address_1(self):
169 base_addr = 0xFEDCBA9876543210
169 base_addr = intmask(0xFEDCBA9876543210)
170170 cb = LocationCodeBuilder64()
171171 cb.CMP(ecx, AddressLoc(ImmedLoc(0), ImmedLoc(0), 0, base_addr))
172172 # this case is a CMP_rj
180180 assert cb.getvalue() == expected_instructions
181181
182182 def test_64bit_address_2(self):
183 base_addr = 0xFEDCBA9876543210
183 base_addr = intmask(0xFEDCBA9876543210)
184184 cb = LocationCodeBuilder64()
185185 cb.MOV(ecx, AddressLoc(ImmedLoc(0), edx, 3, base_addr))
186186 # this case is a CMP_ra
194194 assert cb.getvalue() == expected_instructions
195195
196196 def test_64bit_address_3(self):
197 base_addr = 0xFEDCBA9876543210
197 base_addr = intmask(0xFEDCBA9876543210)
198198 cb = LocationCodeBuilder64()
199199 cb.MOV(ecx, AddressLoc(edx, ImmedLoc(0), 0, base_addr))
200200 # this case is a CMP_rm
210210 assert cb.getvalue() == expected_instructions
211211
212212 def test_64bit_address_4(self):
213 base_addr = 0xFEDCBA9876543210
213 base_addr = intmask(0xFEDCBA9876543210)
214214 cb = LocationCodeBuilder64()
215215 cb.begin_reuse_scratch_register()
216216 assert cb._reuse_scratch_register is True
233233 # ------------------------------------------------------------
234234
235235 def test_MOV_64bit_constant_into_r11(self):
236 base_constant = 0xFEDCBA9876543210
236 base_constant = intmask(0xFEDCBA9876543210)
237237 cb = LocationCodeBuilder64()
238238 cb.MOV(r11, imm(base_constant))
239239
244244 assert cb.getvalue() == expected_instructions
245245
246246 def test_MOV_64bit_constant_into_rax(self):
247 base_constant = 0xFEDCBA9876543210
247 base_constant = intmask(0xFEDCBA9876543210)
248248 cb = LocationCodeBuilder64()
249249 cb.MOV(eax, imm(base_constant))
250250
255255 assert cb.getvalue() == expected_instructions
256256
257257 def test_MOV_64bit_address_into_r11(self):
258 base_addr = 0xFEDCBA9876543210
258 base_addr = intmask(0xFEDCBA9876543210)
259259 cb = LocationCodeBuilder64()
260260 cb.MOV(r11, heap(base_addr))
261261
269269
270270 def test_MOV_immed32_into_64bit_address_1(self):
271271 immed = -0x01234567
272 base_addr = 0xFEDCBA9876543210
272 base_addr = intmask(0xFEDCBA9876543210)
273273 cb = LocationCodeBuilder64()
274274 cb.MOV(AddressLoc(ImmedLoc(0), ImmedLoc(0), 0, base_addr),
275275 ImmedLoc(immed))
285285
286286 def test_MOV_immed32_into_64bit_address_2(self):
287287 immed = -0x01234567
288 base_addr = 0xFEDCBA9876543210
288 base_addr = intmask(0xFEDCBA9876543210)
289289 cb = LocationCodeBuilder64()
290290 cb.MOV(AddressLoc(ImmedLoc(0), edx, 3, base_addr),
291291 ImmedLoc(immed))
301301
302302 def test_MOV_immed32_into_64bit_address_3(self):
303303 immed = -0x01234567
304 base_addr = 0xFEDCBA9876543210
304 base_addr = intmask(0xFEDCBA9876543210)
305305 cb = LocationCodeBuilder64()
306306 cb.MOV(AddressLoc(edx, ImmedLoc(0), 0, base_addr),
307307 ImmedLoc(immed))
319319
320320 def test_MOV_immed32_into_64bit_address_4(self):
321321 immed = -0x01234567
322 base_addr = 0xFEDCBA9876543210
322 base_addr = intmask(0xFEDCBA9876543210)
323323 cb = LocationCodeBuilder64()
324324 cb.MOV(AddressLoc(edx, esi, 2, base_addr), ImmedLoc(immed))
325325 # this case is a MOV_ai
338338
339339 def test_MOV_immed64_into_64bit_address_1(self):
340340 immed = 0x0123456789ABCDEF
341 base_addr = 0xFEDCBA9876543210
341 base_addr = intmask(0xFEDCBA9876543210)
342342 cb = LocationCodeBuilder64()
343343 cb.MOV(AddressLoc(ImmedLoc(0), ImmedLoc(0), 0, base_addr),
344344 ImmedLoc(immed))
360360
361361 def test_MOV_immed64_into_64bit_address_2(self):
362362 immed = 0x0123456789ABCDEF
363 base_addr = 0xFEDCBA9876543210
363 base_addr = intmask(0xFEDCBA9876543210)
364364 cb = LocationCodeBuilder64()
365365 cb.MOV(AddressLoc(ImmedLoc(0), edx, 3, base_addr),
366366 ImmedLoc(immed))
382382
383383 def test_MOV_immed64_into_64bit_address_3(self):
384384 immed = 0x0123456789ABCDEF
385 base_addr = 0xFEDCBA9876543210
385 base_addr = intmask(0xFEDCBA9876543210)
386386 cb = LocationCodeBuilder64()
387387 cb.MOV(AddressLoc(eax, ImmedLoc(0), 0, base_addr),
388388 ImmedLoc(immed))
406406
407407 def test_MOV_immed64_into_64bit_address_4(self):
408408 immed = 0x0123456789ABCDEF
409 base_addr = 0xFEDCBA9876543210
409 base_addr = intmask(0xFEDCBA9876543210)
410410 cb = LocationCodeBuilder64()
411411 cb.MOV(AddressLoc(edx, eax, 2, base_addr), ImmedLoc(immed))
412412 # this case is a MOV_ai
589589 self.cpu.compile_loop(ops.inputargs, ops.operations, looptoken)
590590 self.cpu.execute_token(looptoken, 0)
591591 # check debugging info
592 struct = self.cpu.assembler.loop_run_counters[0]
592 struct = self.cpu.assembler.get_loop_run_counters(0)
593593 assert struct.i == 1
594 struct = self.cpu.assembler.loop_run_counters[1]
594 struct = self.cpu.assembler.get_loop_run_counters(1)
595595 assert struct.i == 1
596 struct = self.cpu.assembler.loop_run_counters[2]
596 struct = self.cpu.assembler.get_loop_run_counters(2)
597597 assert struct.i == 9
598598 self.cpu.finish_once()
599599 finally:
22 from rpython.jit.backend.test.test_rvmprof import BaseRVMProfTest
33 from rpython.jit.backend.x86.test.test_basic import Jit386Mixin
44
5 class TestFfiCall(Jit386Mixin, BaseRVMProfTest):
6 pass
5 class TestRVMProfCall(Jit386Mixin, BaseRVMProfTest):
6 pass
22 from rpython.config.translationoption import DEFL_GC
33 from rpython.jit.backend.x86.arch import WORD
44 import sys
5
6
7 # On Windows, this test crashes obscurely, but only if compiled with
8 # Boehm, not if run with no GC at all. So for now we'll assume it is
9 # really a Boehm bug, or maybe a Boehm-on-Windows-specific issue, and
10 # skip.
11 if sys.platform == 'win32':
12 import py
13 py.test.skip("crashes on Windows (Boehm issue?)")
14
515
616 class TestTranslationCallAssemblerX86(TranslationTestCallAssembler):
717 def _check_cbuilder(self, cbuilder):
+0
-7
rpython/jit/backend/x86/test/test_zvmprof.py less more
0
1 from rpython.jit.backend.llsupport.test.zrpy_vmprof_test import CompiledVmprofTest
2
3 class TestZVMprof(CompiledVmprofTest):
4
5 gcrootfinder = "shadowstack"
6 gc = "incminimark"
4444 # +------------------------------+ <- assembler begin
4545 # | SAVE CONTEXT |
4646 # +------------------------------+
47 # +--+| BRANCH (saves addr of pool |
48 # | | in r13) |
49 # | +------------------------------+
50 # | | ... |
47 #start| ... |
5148 # | | LITERAL POOL | <---+
5249 # | | ... | <-+ |
5350 # +-->+------------------------------+ | |
3131 from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
3232 from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref
3333 from rpython.rlib.jit import AsmInfo
34 from rpython.rlib.rjitlog import rjitlog as jl
3435
3536 class JitFrameTooDeep(Exception):
3637 pass
308309
309310 # signature of this _frame_realloc_slowpath function:
310311 # * on entry, r0 is the new size
311 # * on entry, r1 is the gcmap
312312 # * no managed register must be modified
313313
314 ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
315 mc.STG(r.SCRATCH, l.addr(ofs2, r.SPP))
314 # caller already did push_gcmap(store=True)
316315
317316 self._push_core_regs_to_jitframe(mc, r.MANAGED_REGS)
318317 self._push_fp_regs_to_jitframe(mc)
319318
320319
321 # First argument is SPP (= r31), which is the jitframe
320 # First argument is SPP, which is the jitframe
322321 mc.LGR(r.r2, r.SPP)
323322
324323 # no need to move second argument (frame_depth),
346345 mc.load(r.r5, r.r5, 0)
347346 mc.store(r.r2, r.r5, -WORD)
348347
348 self.pop_gcmap(mc) # cancel the push_gcmap(store=True) in the caller
349349 self._pop_core_regs_from_jitframe(mc, r.MANAGED_REGS)
350350 self._pop_fp_regs_from_jitframe(mc)
351351
356356 self.mc = None
357357
358358 def _build_propagate_exception_path(self):
359 if not self.cpu.propagate_exception_descr:
360 return
361
362359 self.mc = InstrBuilder()
363360 #
364361 # read and reset the current exception
385382 # signature of these cond_call_slowpath functions:
386383 # * on entry, r11 contains the function to call
387384 # * r2, r3, r4, r5 contain arguments for the call
388 # * r0 is the gcmap
385 # * gcmap is pushed
389386 # * the old value of these regs must already be stored in the jitframe
390387 # * on exit, all registers are restored from the jitframe
391388
392389 mc = InstrBuilder()
393390 self.mc = mc
394 ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
395 mc.STG(r.SCRATCH2, l.addr(ofs2,r.SPP))
396391 mc.store_link()
397392 mc.push_std_frame()
398393
410405 reg is not r.r4 and
411406 reg is not r.r5 and
412407 reg is not r.r11]
408 # the caller already did push_gcmap(store=True)
413409 self._push_core_regs_to_jitframe(mc, regs)
414410 if supports_floats:
415411 self._push_fp_regs_to_jitframe(mc)
419415 # Finish
420416 self._reload_frame_if_necessary(mc)
421417
418 self.pop_gcmap(mc) # cancel the push_gcmap(store=True) in the caller
422419 self._pop_core_regs_from_jitframe(mc, saved_regs)
423420 if supports_floats:
424421 self._pop_fp_regs_from_jitframe(mc)
448445 mc.store_link()
449446 mc.push_std_frame()
450447 #
451 ofs2 = self.cpu.get_ofs_of_frame_field('jf_gcmap')
452 mc.STG(r.r1, l.addr(ofs2, r.SPP))
453448 saved_regs = [reg for reg in r.MANAGED_REGS
454449 if reg is not r.RES and reg is not r.RSZ]
455450 self._push_core_regs_to_jitframe(mc, saved_regs)
456451 self._push_fp_regs_to_jitframe(mc)
452 # the caller already did push_gcmap(store=True)
457453 #
458454 if kind == 'fixed':
459455 addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr()
488484 # Check that we don't get NULL; if we do, we always interrupt the
489485 # current loop, as a "good enough" approximation (same as
490486 # emit_call_malloc_gc()).
491 self.propagate_memoryerror_if_r2_is_null(True)
487 self.propagate_memoryerror_if_reg_is_null(r.r2, True)
492488
493489 self._pop_core_regs_from_jitframe(mc, saved_regs)
494490 self._pop_fp_regs_from_jitframe(mc)
587583 # sum -> (14 bytes)
588584 mc.write('\x00'*14)
589585 mc.load_imm(r.RETURN, self._frame_realloc_slowpath)
590 self.load_gcmap(mc, r.r1, gcmap)
586 self.push_gcmap(mc, gcmap, store=True)
591587 mc.raw_call()
592588
593589 self.frame_depth_to_patch.append((patch_pos, mc.currpos()))
673669 looptoken._zarch_rawstart = rawstart
674670 looptoken._zarch_fullsize = full_size
675671 looptoken._zarch_ops_offset = ops_offset
672
676673 if logger:
677 logger.log_loop(inputargs, operations, 0, "rewritten",
678 name=loopname, ops_offset=ops_offset)
674 log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc)
675 log.write(inputargs, operations, ops_offset=ops_offset)
676
677 # legacy
678 if logger.logger_ops:
679 logger.logger_ops.log_loop(inputargs, operations, 0,
680 "rewritten", name=loopname,
681 ops_offset=ops_offset)
679682
680683 self.fixup_target_tokens(rawstart)
681684 self.teardown()
684687 # name = "Loop # %s: %s" % (looptoken.number, loopname)
685688 # self.cpu.profile_agent.native_code_written(name,
686689 # rawstart, full_size)
690 #print(hex(rawstart+looppos))
691 #import pdb; pdb.set_trace()
687692 return AsmInfo(ops_offset, rawstart + looppos,
688693 size_excluding_failure_stuff - looppos, rawstart)
689694
738743 ops_offset = self.mc.ops_offset
739744 frame_depth = max(self.current_clt.frame_info.jfi_frame_depth,
740745 frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE)
746
741747 if logger:
742 logger.log_bridge(inputargs, operations, "rewritten",
743 ops_offset=ops_offset)
748 log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc)
749 log.write(inputargs, operations, ops_offset)
750 # log that the already written bridge is stitched to a descr!
751 logger.log_patch_guard(descr_number, rawstart)
752
753 # legacy
754 if logger.logger_ops:
755 logger.logger_ops.log_bridge(inputargs, operations, "rewritten",
756 faildescr, ops_offset=ops_offset)
757
744758 self.fixup_target_tokens(rawstart)
745759 self.update_frame_depth(frame_depth)
746760 self.teardown()
796810 self.mc.BRC(condition, l.imm(off)) # branch over XGR
797811 self.mc.XGR(result_loc, result_loc)
798812
799 def propagate_memoryerror_if_r2_is_null(self, pop_one_stackframe=False):
813 def propagate_memoryerror_if_reg_is_null(self, reg, pop_one_stackframe=False):
800814 # if self.propagate_exception_path == 0 (tests), this may jump to 0
801815 # and segfaults. too bad. the alternative is to continue anyway
802 # with r2==0, but that will segfault too.
816 # with reg==0, but that will segfault too.
803817 jmp_pos = self.mc.get_relative_pos()
804 # bails to propagate exception path if r2 != 0
818 # bails to propagate exception path if reg != 0
805819 self.mc.reserve_cond_jump()
806820
807821 self.mc.load_imm(r.RETURN, self.propagate_exception_path)
811825
812826 curpos = self.mc.currpos()
813827 pmc = OverwritingBuilder(self.mc, jmp_pos, 1)
814 pmc.CGIJ(r.r2, l.imm(0), c.NE, l.imm(curpos - jmp_pos))
828 pmc.CGIJ(reg, l.imm(0), c.NE, l.imm(curpos - jmp_pos))
815829 pmc.overwrite()
816830
817831 def regalloc_push(self, loc, already_pushed):
865879 self.load_gcmap(mc, r.SCRATCH, gcmap)
866880 ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
867881 mc.STG(r.SCRATCH, l.addr(ofs, r.SPP))
882
883 def pop_gcmap(self, mc):
884 ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
885 mc.LG(r.SCRATCH, l.addr(ofs, r.SPP))
868886
869887 def break_long_loop(self):
870888 # If the loop is too long, the guards in it will jump forward
13381356
13391357 # new value of nursery_free_adr in RSZ and the adr of the new object
13401358 # in RES.
1341 self.load_gcmap(mc, r.r1, gcmap)
1359 self.push_gcmap(mc, gcmap, store=True)
13421360 mc.branch_absolute(self.malloc_slowpath)
13431361
13441362 # here r1 holds nursery_free_addr
13741392
13751393 # new value of nursery_free_adr in RSZ and the adr of the new object
13761394 # in RES.
1377 self.load_gcmap(mc, r.r1, gcmap)
1395 self.push_gcmap(mc, gcmap, store=True)
13781396 mc.branch_absolute(self.malloc_slowpath)
13791397
13801398 offset = mc.currpos() - fast_jmp_pos
14671485 pmc.overwrite()
14681486 #
14691487 # save the gcmap
1470 self.load_gcmap(mc, r.r1, gcmap)
1488 self.push_gcmap(mc, gcmap, store=True)
14711489 #
14721490 # load the function into r14 and jump
14731491 if kind == rewrite.FLAG_ARRAY:
1111 from rpython.rtyper.lltypesystem import rffi
1212 from rpython.jit.backend.llsupport.descr import CallDescr
1313
14 CALL_RELEASE_GIL_STACK_OFF = 6*WORD
15
1416 class CallBuilder(AbstractCallBuilder):
1517 GPR_ARGS = [r.r2, r.r3, r.r4, r.r5, r.r6]
1618 FPR_ARGS = [r.f0, r.f2, r.f4, r.f6]
8486 self.subtracted_to_sp += len(stack_params) * WORD
8587 base = len(stack_params) * WORD
8688 if self.is_call_release_gil:
87 self.subtracted_to_sp += 8*WORD
88 base += 8*WORD
89 self.subtracted_to_sp += CALL_RELEASE_GIL_STACK_OFF
90 base += CALL_RELEASE_GIL_STACK_OFF
8991 for idx,i in enumerate(stack_params):
9092 loc = arglocs[i]
9193 offset = STD_FRAME_SIZE_IN_BYTES - base + 8 * idx
186188 RSHADOWPTR = self.RSHADOWPTR
187189 RFASTGILPTR = self.RFASTGILPTR
188190 #
189 pos = STD_FRAME_SIZE_IN_BYTES - 7*WORD
191 pos = STD_FRAME_SIZE_IN_BYTES - CALL_RELEASE_GIL_STACK_OFF
190192 self.mc.STMG(r.r8, r.r13, l.addr(pos, r.SP))
191193 #
192194 # Save this thread's shadowstack pointer into r8, for later comparison
285287 if gcrootmap:
286288 if gcrootmap.is_shadow_stack and self.is_call_release_gil:
287289 self.mc.LGR(r.SCRATCH, RSHADOWOLD)
288 pos = STD_FRAME_SIZE_IN_BYTES - 7*WORD
290 pos = STD_FRAME_SIZE_IN_BYTES - CALL_RELEASE_GIL_STACK_OFF
289291 self.mc.LMG(r.r8, r.r13, l.addr(pos, r.SP))
290292
291293 def write_real_errno(self, save_err):
4444
4545 # rotating
4646 'RISBG': ('rie_f', ['\xEC','\x55']),
47 'RISBGN': ('rie_f', ['\xEC','\x59']),
4847
4948 # invert & negative & absolute
5049 'LPGR': ('rre', ['\xB9','\x00']),
386386 if reg in self._COND_CALL_SAVE_REGS]
387387 self._push_core_regs_to_jitframe(self.mc, should_be_saved)
388388
389 # load gc map into unusual location: r0
390 self.load_gcmap(self.mc, r.SCRATCH2, regalloc.get_gcmap())
389 self.push_gcmap(self.mc, regalloc.get_gcmap())
391390 #
392391 # load the 0-to-4 arguments into these registers, with the address of
393392 # the function to call into r11
421420 class AllocOpAssembler(object):
422421 _mixin_ = True
423422
424 def emit_call_malloc_gc(self, op, arglocs, regalloc):
425 self._emit_call(op, arglocs)
426 self.propagate_memoryerror_if_r2_is_null()
423 def emit_check_memory_error(self, op, arglocs, regalloc):
424 self.propagate_memoryerror_if_reg_is_null(arglocs[0])
427425
428426 def emit_call_malloc_nursery(self, op, arglocs, regalloc):
429427 # registers r.RES and r.RSZ are allocated for this call
992990 basesize, itemsize, _ = symbolic.get_array_token(rstr.STR,
993991 self.cpu.translate_support_code)
994992 assert itemsize == 1
993 basesize -= 1 # for the extra null character
995994 scale = 0
996995
997996 # src and src_len are tmp registers
827827 prepare_call_f = _prepare_call
828828 prepare_call_n = _prepare_call
829829
830 def prepare_call_malloc_gc(self, op):
831 return self._prepare_call_default(op)
830 def prepare_check_memory_error(self, op):
831 loc = self.ensure_reg(op.getarg(0))
832 return [loc]
832833
833834 def prepare_call_malloc_nursery(self, op):
834835 self.rm.force_allocate_reg(op, selected_reg=r.RES)
2020 from rpython.rlib.debug import ll_assert
2121 from rpython.rlib.longlong2float import (float2longlong,
2222 DOUBLE_ARRAY_PTR, singlefloat2uint_emulator)
23 from rpython.rlib.rarithmetic import r_uint, intmask
2324 import ctypes
2425
2526 CPU = getcpuclass()
154155 s64 = bin(fac_data[1])[2:]
155156 print(f64)
156157 print(s64)
158 for i,c in enumerate(f64):
159 print('index: %d is set? %s' % (i,c))
160
161 assert f64[1] == '1' # The z/Architecture architectural mode is installed.
162 assert f64[2] == '1' # The z/Architecture architectural mode is active.
157163 assert f64[18] == '1' # long displacement facility
164 assert f64[21] == '1' # extended immediate facility
165 assert f64[34] == '1' # general instruction facility
166 assert f64[41] == '1' # floating-point-support-enhancement
158167
159168 def test_load_byte_zero_extend(self):
160169 adr = self.a.datablockwrapper.malloc_aligned(16, 16)
161170 data = rffi.cast(rffi.CArrayPtr(rffi.ULONG), adr)
162 data[0] = rffi.cast(rffi.ULONG,0xffffFFFFffffFF02)
171 data[0] = rffi.cast(rffi.ULONG, intmask(0xffffFFFFffffFF02))
163172 self.a.mc.load_imm(r.r3, adr+7)
164173 self.a.mc.LLGC(r.r2, loc.addr(0,r.r3))
165174 self.a.mc.BCR(con.ANY, r.r14)
168177 def test_load_byte_and_imm(self):
169178 adr = self.a.datablockwrapper.malloc_aligned(16, 16)
170179 data = rffi.cast(rffi.CArrayPtr(rffi.ULONG), adr)
171 data[0] = rffi.cast(rffi.ULONG,0xffffFFFFffff0001)
180 data[0] = rffi.cast(rffi.ULONG, intmask(0xffffFFFFffff0001))
172181 self.a.mc.load_imm(r.r3, adr)
173182 self.a.mc.LG(r.r2, loc.addr(0,r.r3))
174183 self.a.mc.LLGC(r.r2, loc.addr(7,r.r3))
188197 @py.test.mark.parametrize('p', [2**32,2**32+1,2**63-1,2**63-2,0,1,2,3,4,5,6,7,8,10001])
189198 def test_align_withroll(self, p):
190199 self.a.mc.load_imm(r.r2, p & 0xffffFFFFffffFFFF)
191 self.a.mc.RISBGN(r.r2, r.r2, loc.imm(0), loc.imm(0x80 | 60), loc.imm(0))
200 self.a.mc.RISBG(r.r2, r.r2, loc.imm(0), loc.imm(0x80 | 60), loc.imm(0))
192201 self.a.mc.BCR(con.ANY, r.r14)
193202 assert run_asm(self.a) == rffi.cast(rffi.ULONG,p) & ~(7)
194203
213222 n = 13
214223 l = loc
215224 self.a.mc.load_imm(r.r2, 7<<n)
216 self.a.mc.RISBGN(r.r2, r.r2, l.imm(61), l.imm(0x80 | 63), l.imm(64-n))
225 self.a.mc.RISBG(r.r2, r.r2, l.imm(61), l.imm(0x80 | 63), l.imm(64-n))
217226 self.a.mc.BCR(con.ANY, r.r14)
218227 assert run_asm(self.a) == 7
219228
221230 n = 16
222231 l = loc
223232 self.a.mc.load_imm(r.r2, 0xffFFffFF)
224 self.a.mc.RISBGN(r.r2, r.r2, l.imm(60), l.imm(0x80 | 63), l.imm(64-n))
233 self.a.mc.RISBG(r.r2, r.r2, l.imm(60), l.imm(0x80 | 63), l.imm(64-n))
225234 self.a.mc.BCR(con.ANY, r.r14)
226235 assert run_asm(self.a) == 15
227236
203203 g.write('%s\n' % op)
204204 oplist.append(op)
205205 g.write('\t.string "%s"\n' % END_TAG)
206 proc = subprocess.Popen(['as', '-m64', '-mzarch', '-march=zEC12',
206 proc = subprocess.Popen(['as', '-m64', '-mzarch', '-march=z196',
207207 inputname, '-o', filename],
208208 stdout=subprocess.PIPE,
209209 stderr=subprocess.PIPE)
0
1 from rpython.jit.backend.zarch.test.support import JitZARCHMixin
2 from rpython.jit.backend.test.jitlog_test import LoggerTest
3
4 class TestJitlog(JitZARCHMixin, LoggerTest):
5 # for the individual tests see
6 # ====> ../../../test/jitlog_test.py
7 pass
3939
4040 def test_constant_in_call_malloc(self):
4141 c = ConstPtr(rffi.cast(llmemory.GCREF, 0xdeadbeef1234))
42 self.ensure_can_hold(rop.CALL_MALLOC_GC, [c], descr=self.calldescr)
42 self.ensure_can_hold(rop.COND_CALL, [c], descr=self.calldescr)
4343 assert self.const_in_pool(c)
4444 assert self.const_in_pool(ConstPtr(rffi.cast(llmemory.GCREF, 0xdeadbeef1234)))
4545
2525
2626 add_loop_instructions = "lg; lgr; larl; agr; cgfi; jge; j;$"
2727 bridge_loop_instructions = "lg; cgfi; jnl; lghi; " \
28 "(lgfi|iilf);( iihf;)? (lgfi|iilf);( iihf;)? basr; larl; (lgfi|iilf);( iihf;)? br;$"
28 "(lgfi|iilf);( iihf;)? (lgfi|iilf);( iihf;)? stg; basr; larl; (lgfi|iilf);( iihf;)? br;$"
451451 prepare = self._handle_math_sqrt_call
452452 elif oopspec_name.startswith('rgc.'):
453453 prepare = self._handle_rgc_call
454 elif oopspec_name.startswith('rvmprof.'):
455 prepare = self._handle_rvmprof_call
454456 elif oopspec_name.endswith('dict.lookup'):
455457 # also ordereddict.lookup
456458 prepare = self._handle_dict_lookup_call
520522 # XXX some of the following functions should not become residual calls
521523 # but be really compiled
522524 rewrite_op_int_abs = _do_builtin_call
525 rewrite_op_int_floordiv = _do_builtin_call
526 rewrite_op_int_mod = _do_builtin_call
523527 rewrite_op_llong_abs = _do_builtin_call
524528 rewrite_op_llong_floordiv = _do_builtin_call
525529 rewrite_op_llong_mod = _do_builtin_call
529533 rewrite_op_gc_id = _do_builtin_call
530534 rewrite_op_gc_pin = _do_builtin_call
531535 rewrite_op_gc_unpin = _do_builtin_call
532 rewrite_op_uint_mod = _do_builtin_call
533536 rewrite_op_cast_float_to_uint = _do_builtin_call
534537 rewrite_op_cast_uint_to_float = _do_builtin_call
535538 rewrite_op_weakref_create = _do_builtin_call
20772080 else:
20782081 raise NotImplementedError(oopspec_name)
20792082
2083 def _handle_rvmprof_call(self, op, oopspec_name, args):
2084 if oopspec_name != 'rvmprof.jitted':
2085 raise NotImplementedError(oopspec_name)
2086 c_entering = Constant(0, lltype.Signed)
2087 c_leaving = Constant(1, lltype.Signed)
2088 v_uniqueid = args[0]
2089 op1 = SpaceOperation('rvmprof_code', [c_entering, v_uniqueid], None)
2090 op2 = SpaceOperation('rvmprof_code', [c_leaving, v_uniqueid], None)
2091 #
2092 # fish fish inside the oopspec's graph for the ll_func pointer
2093 block = op.args[0].value._obj.graph.startblock
2094 while True:
2095 assert len(block.exits) == 1
2096 nextblock = block.exits[0].target
2097 if nextblock.operations == ():
2098 break
2099 block = nextblock
2100 last_op = block.operations[-1]
2101 assert last_op.opname == 'direct_call'
2102 c_ll_func = last_op.args[0]
2103 #
2104 args = [c_ll_func] + op.args[2:]
2105 ops = self.rewrite_op_direct_call(SpaceOperation('direct_call',
2106 args, op.result))
2107 return [op1] + ops + [op2]
2108
20802109 def rewrite_op_ll_read_timestamp(self, op):
20812110 op1 = self.prepare_builtin_call(op, "ll_read_timestamp", [])
20822111 return self.handle_residual_call(op1,
247247 mask = x >> (LONG_BIT - 1)
248248 return (x ^ mask) - mask
249249
250
251 def _ll_2_int_floordiv(x, y):
252 # this is used only if the RPython program uses llop.int_floordiv()
253 # explicitly. For 'a // b', see _handle_int_special() in jtransform.py.
254 # This is the reverse of rpython.rtyper.rint.ll_int_py_div(), i.e.
255 # the same logic as rpython.rtyper.lltypesystem.opimpl.op_int_floordiv
256 # but written in a no-branch style.
257 r = x // y
258 p = r * y
259 # the JIT knows that if x and y are both positive, this is just 'r'
260 return r + (((x ^ y) >> (LONG_BIT - 1)) & (p != x))
261
262 def _ll_2_int_mod(x, y):
263 # same comments as _ll_2_int_floordiv()
264 r = x % y
265 # the JIT knows that if x and y are both positive, this doesn't change 'r'
266 r -= y & (((x ^ y) & (r | -r)) >> (LONG_BIT - 1))
267 return r
268
269
250270 def _ll_1_cast_uint_to_float(x):
251271 # XXX on 32-bit platforms, this should be done using cast_longlong_to_float
252272 # (which is a residual call right now in the x86 backend)
416436 # in the following calls to builtins, the JIT is allowed to look inside:
417437 inline_calls_to = [
418438 ('int_abs', [lltype.Signed], lltype.Signed),
439 ('int_floordiv', [lltype.Signed, lltype.Signed], lltype.Signed),
440 ('int_mod', [lltype.Signed, lltype.Signed], lltype.Signed),
419441 ('ll_math.ll_math_sqrt', [lltype.Float], lltype.Float),
420442 ]
421443
559581 return lltype.malloc(ARRAY, n, flavor='raw', zero=zero,
560582 add_memory_pressure=add_memory_pressure,
561583 track_allocation=track_allocation)
584 name = '_ll_1_raw_malloc_varsize'
585 if zero:
586 name += '_zero'
587 if add_memory_pressure:
588 name += '_mpressure'
589 if not track_allocation:
590 name += '_notrack'
591 _ll_1_raw_malloc_varsize.func_name = name
562592 return _ll_1_raw_malloc_varsize
563593 return build_ll_1_raw_malloc_varsize
564594
587617 return lltype.malloc(STRUCT, flavor='raw', zero=zero,
588618 add_memory_pressure=add_memory_pressure,
589619 track_allocation=track_allocation)
620 name = '_ll_0_raw_malloc_fixedsize'
621 if zero:
622 name += '_zero'
623 if add_memory_pressure:
624 name += '_mpressure'
625 if not track_allocation:
626 name += '_notrack'
627 _ll_0_raw_malloc_fixedsize.func_name = name
590628 return _ll_0_raw_malloc_fixedsize
591629 return build_ll_0_raw_malloc_fixedsize
592630
1313 from rpython.rlib.rarithmetic import ovfcheck, r_uint, r_longlong, r_ulonglong
1414 from rpython.rlib.jit import dont_look_inside, _we_are_jitted, JitDriver
1515 from rpython.rlib.objectmodel import keepalive_until_here
16 from rpython.rlib import jit
16 from rpython.rlib import jit, debug
1717
1818
1919 class FakeRegAlloc:
139139
140140 def encoding_test(self, func, args, expected,
141141 transform=False, liveness=False, cc=None, jd=None):
142
143142 graphs = self.make_graphs(func, args)
144143 #graphs[0].show()
145144 if transform:
477476 except ZeroDivisionError:
478477 return -42
479478 self.encoding_test(f, [7, 2], """
480 residual_call_ir_i $<* fn ll_int_floordiv_ovf_zer__Signed_Signed>, I[%i0, %i1], R[], <Descr> -> %i2
479 residual_call_ir_i $<* fn ll_int_py_div_ovf_zer__Signed_Signed>, I[%i0, %i1], R[], <Descr> -> %i2
481480 -live-
482481 catch_exception L1
483482 int_return %i2
504503 return 42
505504 # XXX so far, this really produces a int_mod_ovf_zer...
506505 self.encoding_test(f, [7, 2], """
507 residual_call_ir_i $<* fn ll_int_mod_ovf_zer__Signed_Signed>, I[%i0, %i1], R[], <Descr> -> %i2
506 residual_call_ir_i $<* fn ll_int_py_mod_ovf_zer__Signed_Signed>, I[%i0, %i1], R[], <Descr> -> %i2
508507 -live-
509508 catch_exception L1
510509 int_return %i2
11111110 assert str(e.value).startswith("A virtualizable array is passed aroun")
11121111 assert "<Descr>" in str(e.value)
11131112
1113 def test_rvmprof_code(self):
1114 from rpython.rlib.rvmprof import cintf
1115 class MyFakeCallControl(FakeCallControl):
1116 def guess_call_kind(self, op):
1117 if 'jitted' in repr(op):
1118 return 'builtin'
1119 return 'residual'
1120 class X:
1121 pass
1122 def g(x, y):
1123 debug.debug_print("foo")
1124 return X()
1125 @jit.oopspec("rvmprof.jitted(unique_id)")
1126 def decorated_jitted_function(unique_id, *args):
1127 return g(*args)
1128 def f(id, x, y):
1129 return decorated_jitted_function(id, x, y)
1130 self.encoding_test(f, [42, 56, 74], """
1131 rvmprof_code $0, %i0
1132 residual_call_ir_r $<* fn g>, I[%i1, %i2], R[], <Descr> -> %r0
1133 -live-
1134 rvmprof_code $1, %i0
1135 ref_return %r0
1136 """, transform=True, cc=MyFakeCallControl())
1137
11141138
11151139 def check_force_cast(FROM, TO, operations, value):
11161140 """Check that the test is correctly written..."""
22 from rpython.rtyper.annlowlevel import llstr
33 from rpython.flowspace.model import Variable, Constant, SpaceOperation
44 from rpython.jit.codewriter.support import decode_builtin_call, LLtypeHelpers
5 from rpython.jit.codewriter.support import _ll_1_int_abs
65
76 def newconst(x):
87 return Constant(x, lltype.typeOf(x))
135134 py.test.raises(AttributeError, func, llstr(None), p2)
136135
137136 def test_int_abs():
137 from rpython.jit.codewriter.support import _ll_1_int_abs
138138 assert _ll_1_int_abs(0) == 0
139139 assert _ll_1_int_abs(1) == 1
140140 assert _ll_1_int_abs(10) == 10
142142 assert _ll_1_int_abs(-1) == 1
143143 assert _ll_1_int_abs(-10) == 10
144144 assert _ll_1_int_abs(-sys.maxint) == sys.maxint
145
146 def test_int_floordiv_mod():
147 from rpython.rtyper.lltypesystem.lloperation import llop
148 from rpython.jit.codewriter.support import _ll_2_int_floordiv, _ll_2_int_mod
149 for x in range(-6, 7):
150 for y in range(-3, 4):
151 if y != 0:
152 assert (_ll_2_int_floordiv(x, y) ==
153 llop.int_floordiv(lltype.Signed, x, y))
154 assert (_ll_2_int_mod(x, y) ==
155 llop.int_mod(lltype.Signed, x, y))
6363 assert self._insns[value] is None
6464 self._insns[value] = key
6565 self.op_catch_exception = insns.get('catch_exception/L', -1)
66 self.op_rvmprof_code = insns.get('rvmprof_code/ii', -1)
6667 #
6768 all_funcs = []
6869 for key in self._insns:
269270 self.dispatch_loop = builder.dispatch_loop
270271 self.descrs = builder.descrs
271272 self.op_catch_exception = builder.op_catch_exception
273 self.op_rvmprof_code = builder.op_rvmprof_code
272274 self.count_interpreter = count_interpreter
273275 #
274276 if we_are_translated():
372374 target = ord(code[position+1]) | (ord(code[position+2])<<8)
373375 self.position = target
374376 return
377 if opcode == self.op_rvmprof_code:
378 # call the 'jit_rvmprof_code(1)' for rvmprof, but then
379 # continue popping frames. Decode the 'rvmprof_code' insn
380 # manually here.
381 from rpython.rlib.rvmprof import cintf
382 arg1 = self.registers_i[ord(code[position + 1])]
383 arg2 = self.registers_i[ord(code[position + 2])]
384 assert arg1 == 1
385 cintf.jit_rvmprof_code(arg1, arg2)
375386 # no 'catch_exception' insn follows: just reraise
376387 reraise(e)
388
389 def handle_rvmprof_enter(self):
390 code = self.jitcode.code
391 position = self.position
392 opcode = ord(code[position])
393 if opcode == self.op_rvmprof_code:
394 arg1 = self.registers_i[ord(code[position + 1])]
395 arg2 = self.registers_i[ord(code[position + 2])]
396 if arg1 == 1:
397 # we are resuming at a position that will do a
398 # jit_rvmprof_code(1), when really executed. That's a
399 # hint for the need for a jit_rvmprof_code(0).
400 from rpython.rlib.rvmprof import cintf
401 cintf.jit_rvmprof_code(0, arg2)
377402
378403 def copy_constants(self, registers, constants):
379404 """Copy jitcode.constants[0] to registers[255],
11421167
11431168 @arguments("cpu", "i", "R", "d", returns="i")
11441169 def bhimpl_residual_call_r_i(cpu, func, args_r, calldescr):
1145 workaround2200.active = True
11461170 return cpu.bh_call_i(func, None, args_r, None, calldescr)
11471171 @arguments("cpu", "i", "R", "d", returns="r")
11481172 def bhimpl_residual_call_r_r(cpu, func, args_r, calldescr):
1149 workaround2200.active = True
11501173 return cpu.bh_call_r(func, None, args_r, None, calldescr)
11511174 @arguments("cpu", "i", "R", "d")
11521175 def bhimpl_residual_call_r_v(cpu, func, args_r, calldescr):
1153 workaround2200.active = True
11541176 return cpu.bh_call_v(func, None, args_r, None, calldescr)
11551177
11561178 @arguments("cpu", "i", "I", "R", "d", returns="i")
11571179 def bhimpl_residual_call_ir_i(cpu, func, args_i, args_r, calldescr):
1158 workaround2200.active = True
11591180 return cpu.bh_call_i(func, args_i, args_r, None, calldescr)
11601181 @arguments("cpu", "i", "I", "R", "d", returns="r")
11611182 def bhimpl_residual_call_ir_r(cpu, func, args_i, args_r, calldescr):
1162 workaround2200.active = True
11631183 return cpu.bh_call_r(func, args_i, args_r, None, calldescr)
11641184 @arguments("cpu", "i", "I", "R", "d")
11651185 def bhimpl_residual_call_ir_v(cpu, func, args_i, args_r, calldescr):
1166 workaround2200.active = True
11671186 return cpu.bh_call_v(func, args_i, args_r, None, calldescr)
11681187
11691188 @arguments("cpu", "i", "I", "R", "F", "d", returns="i")
11701189 def bhimpl_residual_call_irf_i(cpu, func, args_i,args_r,args_f,calldescr):
1171 workaround2200.active = True
11721190 return cpu.bh_call_i(func, args_i, args_r, args_f, calldescr)
11731191 @arguments("cpu", "i", "I", "R", "F", "d", returns="r")
11741192 def bhimpl_residual_call_irf_r(cpu, func, args_i,args_r,args_f,calldescr):
1175 workaround2200.active = True
11761193 return cpu.bh_call_r(func, args_i, args_r, args_f, calldescr)
11771194 @arguments("cpu", "i", "I", "R", "F", "d", returns="f")
11781195 def bhimpl_residual_call_irf_f(cpu, func, args_i,args_r,args_f,calldescr):
1179 workaround2200.active = True
11801196 return cpu.bh_call_f(func, args_i, args_r, args_f, calldescr)
11811197 @arguments("cpu", "i", "I", "R", "F", "d")
11821198 def bhimpl_residual_call_irf_v(cpu, func, args_i,args_r,args_f,calldescr):
1183 workaround2200.active = True
11841199 return cpu.bh_call_v(func, args_i, args_r, args_f, calldescr)
11851200
11861201 # conditional calls - note that they cannot return stuff
12081223
12091224 @arguments("cpu", "j", "R", returns="i")
12101225 def bhimpl_inline_call_r_i(cpu, jitcode, args_r):
1211 workaround2200.active = True
12121226 return cpu.bh_call_i(jitcode.get_fnaddr_as_int(),
12131227 None, args_r, None, jitcode.calldescr)
12141228 @arguments("cpu", "j", "R", returns="r")
12151229 def bhimpl_inline_call_r_r(cpu, jitcode, args_r):
1216 workaround2200.active = True
12171230 return cpu.bh_call_r(jitcode.get_fnaddr_as_int(),
12181231 None, args_r, None, jitcode.calldescr)
12191232 @arguments("cpu", "j", "R")
12201233 def bhimpl_inline_call_r_v(cpu, jitcode, args_r):
1221 workaround2200.active = True
12221234 return cpu.bh_call_v(jitcode.get_fnaddr_as_int(),
12231235 None, args_r, None, jitcode.calldescr)
12241236
12251237 @arguments("cpu", "j", "I", "R", returns="i")
12261238 def bhimpl_inline_call_ir_i(cpu, jitcode, args_i, args_r):
1227 workaround2200.active = True
12281239 return cpu.bh_call_i(jitcode.get_fnaddr_as_int(),
12291240 args_i, args_r, None, jitcode.calldescr)
12301241 @arguments("cpu", "j", "I", "R", returns="r")
12311242 def bhimpl_inline_call_ir_r(cpu, jitcode, args_i, args_r):
1232 workaround2200.active = True
12331243 return cpu.bh_call_r(jitcode.get_fnaddr_as_int(),
12341244 args_i, args_r, None, jitcode.calldescr)
12351245 @arguments("cpu", "j", "I", "R")
12361246 def bhimpl_inline_call_ir_v(cpu, jitcode, args_i, args_r):
1237 workaround2200.active = True
12381247 return cpu.bh_call_v(jitcode.get_fnaddr_as_int(),
12391248 args_i, args_r, None, jitcode.calldescr)
12401249
12411250 @arguments("cpu", "j", "I", "R", "F", returns="i")
12421251 def bhimpl_inline_call_irf_i(cpu, jitcode, args_i, args_r, args_f):
1243 workaround2200.active = True
12441252 return cpu.bh_call_i(jitcode.get_fnaddr_as_int(),
12451253 args_i, args_r, args_f, jitcode.calldescr)
12461254 @arguments("cpu", "j", "I", "R", "F", returns="r")
12471255 def bhimpl_inline_call_irf_r(cpu, jitcode, args_i, args_r, args_f):
1248 workaround2200.active = True
12491256 return cpu.bh_call_r(jitcode.get_fnaddr_as_int(),
12501257 args_i, args_r, args_f, jitcode.calldescr)
12511258 @arguments("cpu", "j", "I", "R", "F", returns="f")
12521259 def bhimpl_inline_call_irf_f(cpu, jitcode, args_i, args_r, args_f):
1253 workaround2200.active = True
12541260 return cpu.bh_call_f(jitcode.get_fnaddr_as_int(),
12551261 args_i, args_r, args_f, jitcode.calldescr)
12561262 @arguments("cpu", "j", "I", "R", "F")
12571263 def bhimpl_inline_call_irf_v(cpu, jitcode, args_i, args_r, args_f):
1258 workaround2200.active = True
12591264 return cpu.bh_call_v(jitcode.get_fnaddr_as_int(),
12601265 args_i, args_r, args_f, jitcode.calldescr)
12611266
15191524 @arguments("cpu", "r", "r", "i", "i", "i")
15201525 def bhimpl_copyunicodecontent(cpu, src, dst, srcstart, dststart, length):
15211526 cpu.bh_copyunicodecontent(src, dst, srcstart, dststart, length)
1527
1528 @arguments("i", "i")
1529 def bhimpl_rvmprof_code(leaving, unique_id):
1530 from rpython.rlib.rvmprof import cintf
1531 cintf.jit_rvmprof_code(leaving, unique_id)
15221532
15231533 # ----------
15241534 # helpers to resume running in blackhole mode when a guard failed
15421552 if not self.nextblackholeinterp:
15431553 self._exit_frame_with_exception(current_exc)
15441554 return current_exc
1545 finally:
1546 workaround2200.active = False
15471555 #
15481556 # pass the frame's return value to the caller
15491557 caller = self.nextblackholeinterp
17161724 #
17171725 _run_forever(firstbh, current_exc)
17181726 convert_and_run_from_pyjitpl._dont_inline_ = True
1719
1720 # ____________________________________________________________
1721
1722 class WorkaroundIssue2200(object):
1723 pass
1724 workaround2200 = WorkaroundIssue2200()
1725 workaround2200.active = False
55 from rpython.rlib.rarithmetic import r_uint, intmask
66 from rpython.rlib import rstack
77 from rpython.rlib.jit import JitDebugInfo, Counters, dont_look_inside
8 from rpython.rlib.rjitlog import rjitlog as jl
89 from rpython.conftest import option
910
1011 from rpython.jit.metainterp.resoperation import ResOperation, rop,\
216217 loop_info, ops = optimize_trace(metainterp_sd, jitdriver_sd,
217218 data, metainterp.box_names_memo)
218219 except InvalidLoop:
220 metainterp_sd.jitlog.trace_aborted()
219221 trace.cut_at(cut_at)
220222 return None
221223 loop = create_empty_loop(metainterp)
249251 history = metainterp.history
250252 trace = history.trace
251253 warmstate = jitdriver_sd.warmstate
252
254 #
255 metainterp_sd.jitlog.start_new_trace(metainterp_sd,
256 faildescr=None, entry_bridge=False)
257 #
253258 enable_opts = jitdriver_sd.warmstate.enable_opts
254259 if try_disabling_unroll:
255260 if 'unroll' not in enable_opts:
274279 preamble_data,
275280 metainterp.box_names_memo)
276281 except InvalidLoop:
282 metainterp_sd.jitlog.trace_aborted()
277283 history.cut(cut_at)
278284 return None
279285
290296 loop_data,
291297 metainterp.box_names_memo)
292298 except InvalidLoop:
299 metainterp_sd.jitlog.trace_aborted()
293300 history.cut(cut_at)
294301 return None
295302
339346 metainterp_sd = metainterp.staticdata
340347 jitdriver_sd = metainterp.jitdriver_sd
341348 history = metainterp.history
342
349 #
350 metainterp_sd.jitlog.start_new_trace(metainterp_sd,
351 faildescr=resumekey, entry_bridge=False)
352 #
343353 loop_jitcell_token = metainterp.get_procedure_token(greenkey)
344354 assert loop_jitcell_token
345355
367377 loop_data,
368378 metainterp.box_names_memo)
369379 except InvalidLoop:
380 metainterp_sd.jitlog.trace_aborted()
370381 history.cut(cut)
371382 return None
372383
475486
476487 def do_compile_loop(jd_id, unique_id, metainterp_sd, inputargs, operations,
477488 looptoken, log=True, name='', memo=None):
489 # legacy
478490 metainterp_sd.logger_ops.log_loop(inputargs, operations, -2,
479491 'compiling', None, name, memo)
492 _log = metainterp_sd.jitlog.log_trace(jl.MARK_TRACE_OPT, metainterp_sd, None)
493 _log.write(inputargs, operations)
480494 return metainterp_sd.cpu.compile_loop(inputargs,
481495 operations, looptoken,
482496 jd_id=jd_id, unique_id=unique_id,
483497 log=log, name=name,
484 logger=metainterp_sd.logger_ops)
498 logger=metainterp_sd.jitlog)
485499
486500 def do_compile_bridge(metainterp_sd, faildescr, inputargs, operations,
487501 original_loop_token, log=True, memo=None):
502 # legacy
488503 metainterp_sd.logger_ops.log_bridge(inputargs, operations, "compiling",
489504 memo=memo)
505 _log = metainterp_sd.jitlog.log_trace(jl.MARK_TRACE_OPT, metainterp_sd, None)
506 _log.write(inputargs, operations)
490507 assert isinstance(faildescr, AbstractFailDescr)
491508 return metainterp_sd.cpu.compile_bridge(faildescr, inputargs, operations,
492509 original_loop_token, log=log,
493 logger=metainterp_sd.logger_ops)
510 logger=metainterp_sd.jitlog)
494511
495512 def forget_optimization_info(lst, reset_values=False):
496513 for item in lst:
510527 patch_new_loop_to_load_virtualizable_fields(loop, jitdriver_sd, vable)
511528
512529 original_jitcell_token = loop.original_jitcell_token
513 globaldata = metainterp_sd.globaldata
514 original_jitcell_token.number = n = globaldata.loopnumbering
515 globaldata.loopnumbering += 1
530 original_jitcell_token.number = n = metainterp_sd.jitlog.trace_id
516531
517532 if not we_are_translated():
518533 show_procedures(metainterp_sd, loop)
530545 operations = get_deep_immutable_oplist(loop.operations)
531546 metainterp_sd.profiler.start_backend()
532547 debug_start("jit-backend")
548 log = have_debug_prints() or jl.jitlog_enabled()
533549 try:
534550 loopname = jitdriver_sd.warmstate.get_location_str(greenkey)
535551 unique_id = jitdriver_sd.warmstate.get_unique_id(greenkey)
537553 loop.inputargs,
538554 operations, original_jitcell_token,
539555 name=loopname,
540 log=have_debug_prints(),
556 log=log,
541557 memo=memo)
542558 finally:
543559 debug_stop("jit-backend")
581597 operations = get_deep_immutable_oplist(operations)
582598 metainterp_sd.profiler.start_backend()
583599 debug_start("jit-backend")
600 log = have_debug_prints() or jl.jitlog_enabled()
584601 try:
585602 asminfo = do_compile_bridge(metainterp_sd, faildescr, inputargs,
586603 operations,
587 original_loop_token, have_debug_prints(),
604 original_loop_token, log,
588605 memo)
589606 finally:
590607 debug_stop("jit-backend")
619636 raise jitexc.DoneWithThisFrameVoid()
620637
621638 class DoneWithThisFrameDescrInt(_DoneWithThisFrameDescr):
639 def get_result(self, cpu, deadframe):
640 return cpu.get_int_value(deadframe, 0)
622641 def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
623642 assert jitdriver_sd.result_type == history.INT
624 result = metainterp_sd.cpu.get_int_value(deadframe, 0)
625 raise jitexc.DoneWithThisFrameInt(result)
643 cpu = metainterp_sd.cpu
644 raise jitexc.DoneWithThisFrameInt(self.get_result(cpu, deadframe))
626645
627646 class DoneWithThisFrameDescrRef(_DoneWithThisFrameDescr):
647 def get_result(self, cpu, deadframe):
648 return cpu.get_ref_value(deadframe, 0)
628649 def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
629650 assert jitdriver_sd.result_type == history.REF
630651 cpu = metainterp_sd.cpu
631 result = cpu.get_ref_value(deadframe, 0)
632 raise jitexc.DoneWithThisFrameRef(cpu, result)
652 raise jitexc.DoneWithThisFrameRef(cpu, self.get_result(cpu, deadframe))
633653
634654 class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr):
655 def get_result(self, cpu, deadframe):
656 return cpu.get_float_value(deadframe, 0)
635657 def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
636658 assert jitdriver_sd.result_type == history.FLOAT
637 result = metainterp_sd.cpu.get_float_value(deadframe, 0)
638 raise jitexc.DoneWithThisFrameFloat(result)
659 cpu = metainterp_sd.cpu
660 raise jitexc.DoneWithThisFrameFloat(self.get_result(cpu, deadframe))
639661
640662 class ExitFrameWithExceptionDescrRef(_DoneWithThisFrameDescr):
641663 def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
10141036
10151037 def compile_trace(metainterp, resumekey, runtime_boxes):
10161038 """Try to compile a new bridge leading from the beginning of the history
1017 to some existging place.
1039 to some existing place.
10181040 """
10191041
10201042 from rpython.jit.metainterp.optimizeopt import optimize_trace
10271049
10281050 metainterp_sd = metainterp.staticdata
10291051 jitdriver_sd = metainterp.jitdriver_sd
1052 #
1053 jd_name = jitdriver_sd.jitdriver.name
1054 metainterp_sd.jitlog.start_new_trace(metainterp_sd,
1055 faildescr=resumekey, entry_bridge=False, jd_name=jd_name)
1056 #
10301057 if isinstance(resumekey, ResumeAtPositionDescr):
10311058 inline_short_preamble = False
10321059 else:
10511078 info, newops = optimize_trace(metainterp_sd, jitdriver_sd,
10521079 data, metainterp.box_names_memo)
10531080 except InvalidLoop:
1081 metainterp_sd.jitlog.trace_aborted()
10541082 #pdb.post_mortem(sys.exc_info()[2])
10551083 debug_print("compile_new_bridge: got an InvalidLoop")
10561084 # XXX I am fairly convinced that optimize_bridge cannot actually raise
378378 rop.CALL_RELEASE_GIL_F,
379379 rop.CALL_RELEASE_GIL_N,
380380 rop.QUASIIMMUT_FIELD,
381 rop.CALL_MALLOC_GC,
381 rop.CHECK_MEMORY_ERROR,
382382 rop.CALL_MALLOC_NURSERY,
383383 rop.CALL_MALLOC_NURSERY_VARSIZE,
384384 rop.CALL_MALLOC_NURSERY_VARSIZE_FRAME,
5656 self.cache_anything = {}
5757 self.cache_seen_allocation = {}
5858
59 # set of boxes that we've seen a quasi-immut for the field on. cleared
60 # on writes to the field.
61 self.quasiimmut_seen = None
62
5963 def _clear_cache_on_write(self, seen_allocation_of_target):
6064 if not seen_allocation_of_target:
6165 self.cache_seen_allocation.clear()
6266 self.cache_anything.clear()
67 if self.quasiimmut_seen is not None:
68 self.quasiimmut_seen.clear()
6369
6470 def _seen_alloc(self, ref_box):
6571 if not isinstance(ref_box, RefFrontendOp):
9197 def invalidate_unescaped(self):
9298 self._invalidate_unescaped(self.cache_anything)
9399 self._invalidate_unescaped(self.cache_seen_allocation)
100 if self.quasiimmut_seen is not None:
101 self.quasiimmut_seen.clear()
94102
95103 def _invalidate_unescaped(self, d):
96104 for ref_box in d.keys():
483491 if isinstance(oldbox, FrontendOp) and isinstance(newbox, Const):
484492 assert newbox.same_constant(constant_from_op(oldbox))
485493 oldbox.set_replaced_with_const()
494
495 def is_quasi_immut_known(self, fielddescr, box):
496 cache = self.heap_cache.get(fielddescr, None)
497 if cache is not None and cache.quasiimmut_seen is not None:
498 return box in cache.quasiimmut_seen
499 return False
500
501 def quasi_immut_now_known(self, fielddescr, box):
502 cache = self.heap_cache.get(fielddescr, None)
503 if cache is None:
504 cache = self.heap_cache[fielddescr] = CacheEntry(self)
505 if cache.quasiimmut_seen is not None:
506 cache.quasiimmut_seen[box] = None
507 else:
508 cache.quasiimmut_seen = {box: None}
9797 def log_abort_loop(self, trace, memo=None):
9898 debug_start("jit-abort-log")
9999 if not have_debug_prints():
100 debug_stop("jit-abort-log")
100101 return
101102 inputargs, operations = self._unpack_trace(trace)
102103 logops = self._log_operations(inputargs, operations, ops_offset=None,
2323 # this is the initial size of the trace - note that we probably
2424 # want something that would fit the inital "max_trace_length"
2525 INIT_SIZE = 30000
26 MIN_SHORT = 0
27 MAX_SHORT = 2**16 - 1
28 check_range = True
26 MIN_VALUE = 0
27 MAX_VALUE = 2**16 - 1
2928
3029 class BigModel:
3130 INIT_SIZE = 30000
32 STORAGE_TP = lltype.Signed
33 check_range = False
34 # we can move SMALL ints here, if necessary
31 STORAGE_TP = rffi.UINT
32 MIN_VALUE = 0
33 MAX_VALUE = int(2**31 - 1) # we could go to 2**32-1 on 64-bit, but
34 # that seems already far too huge
3535
3636 def get_model(self):
3737 return _get_model(self.metainterp_sd)
294294 if self._pos >= len(self._ops):
295295 # grow by 2X
296296 self._ops = self._ops + [rffi.cast(model.STORAGE_TP, 0)] * len(self._ops)
297 if model.check_range:
298 if not model.MIN_SHORT <= v <= model.MAX_SHORT:
299 raise FrontendTagOverflow
297 if not model.MIN_VALUE <= v <= model.MAX_VALUE:
298 raise FrontendTagOverflow
300299 self._ops[self._pos] = rffi.cast(model.STORAGE_TP, v)
301300 self._pos += 1
302301
66 from rpython.jit.metainterp.optimizeopt.simplify import OptSimplify
77 from rpython.jit.metainterp.optimizeopt.pure import OptPure
88 from rpython.jit.metainterp.optimizeopt.earlyforce import OptEarlyForce
9 from rpython.rlib.rjitlog import rjitlog as jl
910 from rpython.rlib.jit import PARAMETERS, ENABLE_ALL_OPTS
1011 from rpython.rlib.unroll import unrolling_iterable
1112 from rpython.rlib.debug import debug_start, debug_stop, debug_print
5253 """
5354 debug_start("jit-optimize")
5455 try:
56 # mark that a new trace has been started
57 log = metainterp_sd.jitlog.log_trace(jl.MARK_TRACE, metainterp_sd, None)
58 log.write_trace(compile_data.trace)
5559 if compile_data.log_noopt:
5660 metainterp_sd.logger_noopt.log_loop_from_trace(compile_data.trace, memo=memo)
5761 if memo is None:
2020 , (rop.STRSETITEM, 0, -1)
2121 , (rop.UNICODESETITEM, 0, -1)
2222 ]
23
24 UNROLLED_MODIFY_COMPLEX_OBJ = unrolling_iterable(MODIFY_COMPLEX_OBJ)
2325
2426 LOAD_COMPLEX_OBJ = [ (rop.GETARRAYITEM_GC_I, 0, 1)
2527 , (rop.GETARRAYITEM_GC_F, 0, 1)
3840 , (rop.GETFIELD_RAW_F, 0, -1)
3941 , (rop.GETFIELD_RAW_R, 0, -1)
4042 ]
43
44 UNROLLED_LOAD_COMPLEX_OBJ = unrolling_iterable(LOAD_COMPLEX_OBJ)
4145
4246 class Path(object):
4347 def __init__(self,path):
201205 args = []
202206 op = self.op
203207 if self.modifies_complex_object():
204 for opnum, i, j in unrolling_iterable(MODIFY_COMPLEX_OBJ):
208 for opnum, i, j in UNROLLED_MODIFY_COMPLEX_OBJ: #unrolling_iterable(MODIFY_COMPLEX_OBJ):
205209 if op.getopnum() == opnum:
206210 op_args = op.getarglist()
207211 if j == -1:
722726 if node.loads_from_complex_object():
723727 # If this complex object load operation loads an index that has been
724728 # modified, the last modification should be used to put a def-use edge.
725 for opnum, i, j in unrolling_iterable(LOAD_COMPLEX_OBJ):
729 for opnum, i, j in UNROLLED_LOAD_COMPLEX_OBJ:
726730 if opnum == op.getopnum():
727731 cobj = op.getarg(i)
728732 if j != -1:
344344 opnum == rop.ENTER_PORTAL_FRAME or # no effect whatsoever
345345 opnum == rop.LEAVE_PORTAL_FRAME or # no effect whatsoever
346346 opnum == rop.COPYSTRCONTENT or # no effect on GC struct/array
347 opnum == rop.COPYUNICODECONTENT): # no effect on GC struct/array
347 opnum == rop.COPYUNICODECONTENT or # no effect on GC struct/array
348 opnum == rop.CHECK_MEMORY_ERROR): # may only abort the whole loop
348349 return
349350 if rop.is_call(op.opnum):
350351 if rop.is_call_assembler(op.getopnum()):
366366
367367 class RawBufferPtrInfo(AbstractRawPtrInfo):
368368 buffer = None
369
370 def __init__(self, cpu, size=-1):
369
370 def __init__(self, cpu, func, size=-1):
371 self.func = func
371372 self.size = size
372373 if self.size != -1:
373374 self.buffer = RawBuffer(cpu, None)
399400
400401 def _force_elements(self, op, optforce, descr):
401402 self.size = -1
403 # at this point we have just written the
404 # 'op = CALL_I(..., OS_RAW_MALLOC_VARSIZE_CHAR)'.
405 # Emit now a CHECK_MEMORY_ERROR resop.
406 check_op = ResOperation(rop.CHECK_MEMORY_ERROR, [op])
407 optforce.emit_operation(check_op)
408 #
402409 buffer = self._get_buffer()
403410 for i in range(len(buffer.offsets)):
404411 # write the value
418425 @specialize.argtype(1)
419426 def visitor_dispatch_virtual_type(self, visitor):
420427 buffer = self._get_buffer()
421 return visitor.visit_vrawbuffer(self.size,
428 return visitor.visit_vrawbuffer(self.func,
429 self.size,
422430 buffer.offsets[:],
423431 buffer.descrs[:])
424432
9696 self.emit_operation(op)
9797
9898 r = self.getintbound(op)
99 if b2.is_constant():
100 val = b2.lower
101 if val >= 0:
102 r.intersect(IntBound(0, val))
103 elif b1.is_constant():
104 val = b1.lower
105 if val >= 0:
106 r.intersect(IntBound(0, val))
107 elif b1.known_ge(IntBound(0, 0)) and b2.known_ge(IntBound(0, 0)):
108 lesser = min(b1.upper, b2.upper)
109 r.intersect(IntBound(0, next_pow2_m1(lesser)))
99 pos1 = b1.known_ge(IntBound(0, 0))
100 pos2 = b2.known_ge(IntBound(0, 0))
101 if pos1 or pos2:
102 r.make_ge(IntBound(0, 0))
103 if pos1:
104 r.make_le(b1)
105 if pos2:
106 r.make_le(b2)
110107
111108 def optimize_INT_SUB(self, op):
112109 self.emit_operation(op)
00 from rpython.rlib.rarithmetic import LONG_BIT, intmask, r_uint
1 from rpython.rlib.rbigint import rbigint, ONERBIGINT
1
22
33 from rpython.jit.metainterp.history import ConstInt
44 from rpython.jit.metainterp.resoperation import ResOperation, rop
1616 while (r_uint(1) << (i+1)) < r_uint(m):
1717 i += 1
1818
19 # k = 2**(64+i) // m + 1, computed manually using rbigint
20 # because that's the easiest
21 k1 = ONERBIGINT.lshift(LONG_BIT + i).floordiv(rbigint.fromint(m))
22 k = k1.touint() + r_uint(1)
19 # quotient = 2**(64+i) // m
20 high_word_dividend = r_uint(1) << i
21 quotient = r_uint(0)
22 for bit in range(LONG_BIT-1, -1, -1):
23 t = quotient + (r_uint(1) << bit)
24 # check: is 't * m' small enough to be < 2**(64+i), or not?
25 # note that we're really computing (2**(64+i)-1) // m, but the result
26 # is the same, because powers of two are not multiples of m.
27 if unsigned_mul_high(t, r_uint(m)) < high_word_dividend:
28 quotient = t # yes, small enough
29
30 # k = 2**(64+i) // m + 1
31 k = quotient + r_uint(1)
2332
2433 assert k != r_uint(0)
2534 # Proof that k < 2**64 holds in all cases, even with the "+1":
51875187 """
51885188 self.optimize_loop(ops, ops)
51895189
5190 def test_int_and_positive(self):
5191 ops = """
5192 [i0, i1]
5193 i2 = int_ge(i1, 0)
5194 guard_true(i2) []
5195 i3 = int_and(i0, i1)
5196 i4 = int_ge(i3, 0)
5197 guard_true(i4) []
5198 jump(i3)
5199 """
5200 expected = """
5201 [i0, i1]
5202 i2 = int_ge(i1, 0)
5203 guard_true(i2) []
5204 i3 = int_and(i0, i1)
5205 jump(i3)
5206 """
5207 self.optimize_loop(ops, expected)
5208
51905209 def test_int_or_cmp_above_bounds(self):
51915210 ops = """
51925211 [p0,p1]
52505269 jump(i2)
52515270 """
52525271 self.optimize_loop(ops, ops)
5272
5273 def test_int_xor_positive_is_positive(self):
5274 ops = """
5275 [i0, i1]
5276 i2 = int_lt(i0, 0)
5277 guard_false(i2) []
5278 i3 = int_lt(i1, 0)
5279 guard_false(i3) []
5280 i4 = int_xor(i0, i1)
5281 i5 = int_lt(i4, 0)
5282 guard_false(i5) []
5283 jump(i4, i0)
5284 """
5285 expected = """
5286 [i0, i1]
5287 i2 = int_lt(i0, 0)
5288 guard_false(i2) []
5289 i3 = int_lt(i1, 0)
5290 guard_false(i3) []
5291 i4 = int_xor(i0, i1)
5292 jump(i4, i0)
5293 """
5294 self.optimize_loop(ops, expected)
5295
5296 def test_positive_rshift_bits_minus_1(self):
5297 ops = """
5298 [i0]
5299 i2 = int_lt(i0, 0)
5300 guard_false(i2) []
5301 i3 = int_rshift(i2, %d)
5302 escape_n(i3)
5303 jump(i0)
5304 """ % (LONG_BIT - 1,)
5305 expected = """
5306 [i0]
5307 i2 = int_lt(i0, 0)
5308 guard_false(i2) []
5309 escape_n(0)
5310 jump(i0)
5311 """
5312 self.optimize_loop(ops, expected)
52535313
52545314 def test_int_or_same_arg(self):
52555315 ops = """
17691769 def test_virtual_raw_malloc_basic(self):
17701770 ops = """
17711771 [i1]
1772 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
1772 i2 = call_i(12345, 10, descr=raw_malloc_descr) # 12345 = malloc func
17731773 guard_no_exception() []
17741774 setarrayitem_raw(i2, 0, i1, descr=rawarraydescr)
17751775 i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr)
17861786 ops = """
17871787 [i1]
17881788 i5 = int_mul(10, 1)
1789 i2 = call_i('malloc', i5, descr=raw_malloc_descr)
1789 i2 = call_i(12345, i5, descr=raw_malloc_descr)
17901790 guard_no_exception() []
17911791 setarrayitem_raw(i2, 0, i1, descr=rawarraydescr)
17921792 i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr)
18021802 def test_virtual_raw_malloc_force(self):
18031803 ops = """
18041804 [i1]
1805 i2 = call_i('malloc', 20, descr=raw_malloc_descr)
1805 i2 = call_i(12345, 20, descr=raw_malloc_descr)
18061806 guard_no_exception() []
18071807 setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char)
18081808 setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char)
18161816 expected = """
18171817 [i1]
18181818 label(i1)
1819 i2 = call_i('malloc', 20, descr=raw_malloc_descr)
1820 #guard_no_exception() [] # XXX should appear
1819 i2 = call_i(12345, 20, descr=raw_malloc_descr)
1820 check_memory_error(i2)
18211821 raw_store(i2, 0, i1, descr=rawarraydescr_char)
18221822 raw_store(i2, 1, 123, descr=rawarraydescr_char)
18231823 raw_store(i2, 2, 456, descr=rawarraydescr_char)
18311831 def test_virtual_raw_malloc_invalid_write_force(self):
18321832 ops = """
18331833 [i1]
1834 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
1834 i2 = call_i(12345, 10, descr=raw_malloc_descr)
18351835 guard_no_exception() []
18361836 setarrayitem_raw(i2, 0, i1, descr=rawarraydescr)
18371837 label(i1) # we expect the buffer to be forced *after* the label
18421842 expected = """
18431843 [i1]
18441844 label(i1)
1845 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
1846 #guard_no_exception() [] # XXX should appear
1845 i2 = call_i(12345, 10, descr=raw_malloc_descr)
1846 check_memory_error(i2)
18471847 raw_store(i2, 0, i1, descr=rawarraydescr)
18481848 setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char)
18491849 call_n('free', i2, descr=raw_free_descr)
18541854 def test_virtual_raw_malloc_invalid_read_force(self):
18551855 ops = """
18561856 [i1]
1857 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
1857 i2 = call_i(12345, 10, descr=raw_malloc_descr)
18581858 guard_no_exception() []
18591859 setarrayitem_raw(i2, 0, i1, descr=rawarraydescr)
18601860 label(i1) # we expect the buffer to be forced *after* the label
18651865 expected = """
18661866 [i1]
18671867 label(i1)
1868 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
1869 #guard_no_exception() [] # XXX should appear
1868 i2 = call_i(12345, 10, descr=raw_malloc_descr)
1869 check_memory_error(i2)
18701870 raw_store(i2, 0, i1, descr=rawarraydescr)
18711871 i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr_char)
18721872 call_n('free', i2, descr=raw_free_descr)
18771877 def test_virtual_raw_slice(self):
18781878 ops = """
18791879 [i0, i1]
1880 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
1880 i2 = call_i(12345, 10, descr=raw_malloc_descr)
18811881 guard_no_exception() []
18821882 setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char)
18831883 i3 = int_add(i2, 1) # get a slice of the original buffer
18971897 def test_virtual_raw_slice_of_a_raw_slice(self):
18981898 ops = """
18991899 [i0, i1]
1900 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
1900 i2 = call_i(12345, 10, descr=raw_malloc_descr)
19011901 guard_no_exception() []
19021902 i3 = int_add(i2, 1) # get a slice of the original buffer
19031903 i4 = int_add(i3, 1) # get a slice of a slice
19151915 def test_virtual_raw_slice_force(self):
19161916 ops = """
19171917 [i0, i1]
1918 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
1918 i2 = call_i(12345, 10, descr=raw_malloc_descr)
19191919 guard_no_exception() []
19201920 setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char)
19211921 i3 = int_add(i2, 1) # get a slice of the original buffer
19281928 [i0, i1]
19291929 label(i0, i1)
19301930 # these ops are generated by VirtualRawBufferValue._really_force
1931 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
1932 #guard_no_exception() [] # XXX should appear
1931 i2 = call_i(12345, 10, descr=raw_malloc_descr)
1932 check_memory_error(i2)
19331933 raw_store(i2, 0, 42, descr=rawarraydescr_char)
19341934 raw_store(i2, 5, 4242, descr=rawarraydescr_char)
19351935 # this is generated by VirtualRawSliceValue._really_force
19451945 i1 = getarrayitem_raw_i(i0, 0, descr=rawarraydescr)
19461946 i2 = int_add(i1, 1)
19471947 call_n('free', i0, descr=raw_free_descr)
1948 i3 = call_i('malloc', 10, descr=raw_malloc_descr)
1948 i3 = call_i(12345, 10, descr=raw_malloc_descr)
19491949 guard_no_exception() []
19501950 setarrayitem_raw(i3, 0, i2, descr=rawarraydescr)
19511951 label(i2)
19571957 i2 = int_add(i1, 1)
19581958 call_n('free', i0, descr=raw_free_descr)
19591959 label(i2)
1960 i3 = call_i('malloc', 10, descr=raw_malloc_descr)
1961 #guard_no_exception() [] # XXX should appear
1960 i3 = call_i(12345, 10, descr=raw_malloc_descr)
1961 check_memory_error(i3)
19621962 raw_store(i3, 0, i2, descr=rawarraydescr)
19631963 jump(i3)
19641964 """
19671967 def test_virtual_raw_store_raw_load(self):
19681968 ops = """
19691969 [i1]
1970 i0 = call_i('malloc', 10, descr=raw_malloc_descr)
1970 i0 = call_i(12345, 10, descr=raw_malloc_descr)
19711971 guard_no_exception() []
19721972 raw_store(i0, 0, i1, descr=rawarraydescr)
19731973 i2 = raw_load_i(i0, 0, descr=rawarraydescr)
19851985 def test_virtual_raw_store_getarrayitem_raw(self):
19861986 ops = """
19871987 [f1]
1988 i0 = call_i('malloc', 16, descr=raw_malloc_descr)
1988 i0 = call_i(12345, 16, descr=raw_malloc_descr)
19891989 guard_no_exception() []
19901990 raw_store(i0, 8, f1, descr=rawarraydescr_float)
19911991 f2 = getarrayitem_raw_f(i0, 1, descr=rawarraydescr_float)
20032003 def test_virtual_setarrayitem_raw_raw_load(self):
20042004 ops = """
20052005 [f1]
2006 i0 = call_i('malloc', 16, descr=raw_malloc_descr)
2006 i0 = call_i(12345, 16, descr=raw_malloc_descr)
20072007 guard_no_exception() []
20082008 setarrayitem_raw(i0, 1, f1, descr=rawarraydescr_float)
20092009 f2 = raw_load_f(i0, 8, descr=rawarraydescr_float)
20212021 def test_virtual_raw_buffer_forced_but_slice_not_forced(self):
20222022 ops = """
20232023 [f1]
2024 i0 = call_i('malloc', 16, descr=raw_malloc_descr)
2024 i0 = call_i(12345, 16, descr=raw_malloc_descr)
20252025 guard_no_exception() []
20262026 i1 = int_add(i0, 8)
20272027 escape_n(i0)
20302030 """
20312031 expected = """
20322032 [f1]
2033 i0 = call_i('malloc', 16, descr=raw_malloc_descr)
2033 i0 = call_i(12345, 16, descr=raw_malloc_descr)
2034 check_memory_error(i0)
20342035 escape_n(i0)
20352036 i1 = int_add(i0, 8)
20362037 setarrayitem_raw(i1, 0, f1, descr=rawarraydescr_float)
88018802 ops = """
88028803 [i1]
88038804 i0 = call_i(123, 10, descr=raw_malloc_descr)
8805 guard_no_exception() []
88048806 jump(i0)
88058807 """
8806 self.optimize_loop(ops, ops)
8808 expected = """
8809 [i1]
8810 i0 = call_i(123, 10, descr=raw_malloc_descr)
8811 check_memory_error(i0)
8812 jump(i0)
8813 """
8814 self.optimize_loop(ops, expected)
88078815
88088816 def test_raw_buffer_int_is_true(self):
88098817 ops = """
88108818 [iinp]
88118819 i0 = call_i(123, 10, descr=raw_malloc_descr)
8820 guard_no_exception() []
88128821 i1 = int_is_true(i0)
88138822 guard_true(i1) []
88148823 i2 = int_is_zero(i0)
88188827 expected = """
88198828 [i2]
88208829 i0 = call_i(123, 10, descr=raw_malloc_descr)
8830 check_memory_error(i0)
88218831 jump(i0)
88228832 """
88238833 self.optimize_loop(ops, expected)
88758885 def test_resume_forced_raw_ptr(self):
88768886 ops = """
88778887 [i0]
8878 i = call_i('malloc', 10, descr=raw_malloc_descr)
8888 i = call_i(12345, 10, descr=raw_malloc_descr)
8889 guard_no_exception() []
88798890 is = int_add(i, 8)
88808891 escape_n(i)
88818892 i1 = int_add(i0, 1)
88868897 """
88878898 expected = """
88888899 [i0]
8889 i = call_i('malloc', 10, descr=raw_malloc_descr)
8900 i = call_i(12345, 10, descr=raw_malloc_descr)
8901 check_memory_error(i)
88908902 escape_n(i)
88918903 i1 = int_add(i0, 1)
88928904 i2 = int_lt(i1, 100)
89538965 def test_pending_setfield_delayed_malloc(self):
89548966 ops = """
89558967 [i0, p0]
8956 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
8968 i2 = call_i(12345, 10, descr=raw_malloc_descr)
8969 guard_no_exception() []
89578970 setarrayitem_raw(i2, 0, 13, descr=rawarraydescr)
89588971 setfield_gc(p0, i2, descr=valuedescr)
89598972 i1 = int_add(i0, 1)
89748987 def test_raw_buffer_ptr_info_intbounds_bug(self):
89758988 ops = """
89768989 []
8977 i2 = call_i('malloc', 10, descr=raw_malloc_descr)
8990 i2 = call_i(12345, 10, descr=raw_malloc_descr)
8991 guard_no_exception() []
8992 guard_value(i2, 12345) []
8993 jump()
8994 """
8995 expected = """
8996 []
8997 i2 = call_i(12345, 10, descr=raw_malloc_descr)
8998 check_memory_error(i2)
89788999 guard_value(i2, 12345) []
89799000 jump()
89809001 """
89819002 # getting InvalidLoop would be a good idea, too.
89829003 # (this test was written to show it would previously crash)
8983 self.optimize_loop(ops, ops)
9004 self.optimize_loop(ops, expected)
89849005
89859006 def test_unroll_constant_null_1(self):
89869007 ops = """
2020 from rpython.jit.metainterp.resoperation import (rop, ResOperation,
2121 InputArgRef, AbstractValue, OpHelpers)
2222 from rpython.jit.metainterp.optimizeopt.util import args_dict
23 from rpython.rlib.rjitlog import rjitlog as jl
2324
2425
2526 def test_sort_descrs():
483484 self.options = Fake()
484485 self.globaldata = Fake()
485486 self.config = get_combined_translation_config(translating=True)
487 self.jitlog = jl.JitLogger()
486488
487489 class logger_noopt:
488490 @classmethod
11 import py
22 from rpython.jit.metainterp.optimizeopt.virtualstate import VirtualStateInfo,\
33 VStructStateInfo, LEVEL_CONSTANT,\
4 VArrayStateInfo, NotVirtualStateInfo, VirtualState,\
4 VArrayStateInfo, not_virtual, VirtualState,\
55 GenerateGuardState, VirtualStatesCantMatch, VArrayStructStateInfo
66 from rpython.jit.metainterp.history import ConstInt, ConstPtr, TargetToken
77 from rpython.jit.metainterp.resoperation import InputArgInt, InputArgRef,\
3030 def setup_class(self):
3131 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
3232 value = info.InstancePtrInfo(None, classbox)
33 self.knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
33 self.knownclass_info = not_virtual(self.cpu, 'r', value)
3434 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
3535 value = info.InstancePtrInfo(None, classbox)
36 self.knownclass_info2 = NotVirtualStateInfo(self.cpu, 'r', value)
36 self.knownclass_info2 = not_virtual(self.cpu, 'r', value)
3737
3838 def guards(self, info1, info2, box, runtime_box, expected, inputargs=None):
3939 if inputargs is None:
7979 def test_make_inputargs(self):
8080 optimizer = FakeOptimizer(self.cpu)
8181 args = [InputArgInt()]
82 info0 = NotVirtualStateInfo(self.cpu, args[0].type, None)
82 info0 = not_virtual(self.cpu, args[0].type, None)
8383 vs = VirtualState([info0])
8484 assert vs.make_inputargs(args, optimizer) == args
8585 info0.level = LEVEL_CONSTANT
107107 assert info1 in state.bad and info2 in state.bad
108108
109109 for BoxType in (InputArgInt, InputArgFloat, InputArgRef):
110 info1 = NotVirtualStateInfo(self.cpu, BoxType.type, None)
111 info2 = NotVirtualStateInfo(self.cpu, BoxType.type, None)
110 info1 = not_virtual(self.cpu, BoxType.type, None)
111 info2 = not_virtual(self.cpu, BoxType.type, None)
112112 postest(info1, info2)
113113
114114 info1, info2 = VArrayStateInfo(42), VArrayStateInfo(42)
125125
126126 def test_NotVirtualStateInfo_generalization(self):
127127 def isgeneral(tp1, info1, tp2, info2):
128 info1 = NotVirtualStateInfo(self.cpu, tp1, info1)
128 info1 = not_virtual(self.cpu, tp1, info1)
129129 info1.position = 0
130 info2 = NotVirtualStateInfo(self.cpu, tp2, info2)
130 info2 = not_virtual(self.cpu, tp2, info2)
131131 info2.position = 0
132132 return VirtualState([info1]).generalization_of(VirtualState([info2]), FakeOptimizer(self.cpu))
133133
165165 assert not isgeneral('r', value1, 'r', value2)
166166
167167 def test_field_matching_generalization(self):
168 const1 = NotVirtualStateInfo(self.cpu, 'i', ConstIntBound(1))
169 const2 = NotVirtualStateInfo(self.cpu, 'i', ConstIntBound(2))
168 const1 = not_virtual(self.cpu, 'i', ConstIntBound(1))
169 const2 = not_virtual(self.cpu, 'i', ConstIntBound(2))
170170 const1.position = const2.position = 1
171171 self.check_invalid(const1, const2)
172172 self.check_invalid(const2, const1)
191191
192192 def test_known_class_generalization(self):
193193 knownclass1 = info.InstancePtrInfo(None, ConstPtr(self.myptr))
194 info1 = NotVirtualStateInfo(self.cpu, 'r', knownclass1)
194 info1 = not_virtual(self.cpu, 'r', knownclass1)
195195 info1.position = 0
196196 knownclass2 = info.InstancePtrInfo(None, ConstPtr(self.myptr))
197 info2 = NotVirtualStateInfo(self.cpu, 'r', knownclass2)
197 info2 = not_virtual(self.cpu, 'r', knownclass2)
198198 info2.position = 0
199199 self.check_no_guards(info1, info2)
200200 self.check_no_guards(info2, info1)
201201
202202 knownclass3 = info.InstancePtrInfo(None, ConstPtr(self.myptr2))
203 info3 = NotVirtualStateInfo(self.cpu, 'r', knownclass3)
203 info3 = not_virtual(self.cpu, 'r', knownclass3)
204204 info3.position = 0
205205 self.check_invalid(info1, info3)
206206 self.check_invalid(info2, info3)
221221 #unknown_val = PtrOptValue(self.nodebox)
222222 #unknownnull_val = PtrOptValue(BoxPtr(self.nullptr))
223223 opt = FakeOptimizer(self.cpu)
224 unknown_info = NotVirtualStateInfo(self.cpu, 'r', None)
225
226 nonnull_info = NotVirtualStateInfo(self.cpu, 'r', info.NonNullPtrInfo())
224 unknown_info = not_virtual(self.cpu, 'r', None)
225
226 nonnull_info = not_virtual(self.cpu, 'r', info.NonNullPtrInfo())
227227
228228 classbox1 = self.cpu.ts.cls_of_box(ConstPtr(self.nodeaddr))
229 knownclass_info = NotVirtualStateInfo(self.cpu, 'r',
230 info.InstancePtrInfo(None, classbox1))
229 knownclass_info = not_virtual(self.cpu, 'r',
230 info.InstancePtrInfo(None, classbox1))
231231 classbox2 = self.cpu.ts.cls_of_box(ConstPtr(self.node2addr))
232 knownclass2_info = NotVirtualStateInfo(self.cpu, 'r',
233 info.InstancePtrInfo(None, classbox2))
234
235 constant_info = NotVirtualStateInfo(self.cpu, 'i',
236 ConstIntBound(1))
237 constant_ptr_info = NotVirtualStateInfo(self.cpu, 'r',
232 knownclass2_info = not_virtual(self.cpu, 'r',
233 info.InstancePtrInfo(None, classbox2))
234
235 constant_info = not_virtual(self.cpu, 'i',
236 ConstIntBound(1))
237 constant_ptr_info = not_virtual(self.cpu, 'r',
238238 info.ConstPtrInfo(ConstPtr(self.nodeaddr)))
239239 constclass_val = info.ConstPtrInfo(ConstPtr(self.nodeaddr))
240 constclass_info = NotVirtualStateInfo(self.cpu, 'r', constclass_val)
241 constclass2_info = NotVirtualStateInfo(self.cpu, 'r',
240 constclass_info = not_virtual(self.cpu, 'r', constclass_val)
241 constclass2_info = not_virtual(self.cpu, 'r',
242242 info.ConstPtrInfo(ConstPtr(self.node2addr)))
243 constantnull_info = NotVirtualStateInfo(self.cpu, 'r',
243 constantnull_info = not_virtual(self.cpu, 'r',
244244 info.ConstPtrInfo(ConstPtr(self.nullptr)))
245245
246246 # unknown unknown
259259 self.check_no_guards(unknown_info, knownclass_info)
260260
261261 # unknown constant
262 self.check_no_guards(unknown_info, constant_info,
262 unknown_info_int = not_virtual(self.cpu, 'i', None)
263 self.check_no_guards(unknown_info_int, constant_info,
263264 ConstInt(1), ConstIntBound(1))
264 self.check_no_guards(unknown_info, constant_info)
265 self.check_no_guards(unknown_info_int, constant_info)
265266
266267
267268 # nonnull unknown
292293 const_nonnull = ConstPtr(self.nodeaddr)
293294 const_nonnull2 = ConstPtr(self.node2addr)
294295 const_null = ConstPtr(lltype.nullptr(llmemory.GCREF.TO))
295 self.check_no_guards(nonnull_info, constant_info, const_nonnull,
296 self.check_no_guards(nonnull_info, constant_ptr_info, const_nonnull,
296297 info.ConstPtrInfo(const_nonnull))
297298 self.check_invalid(nonnull_info, constantnull_info, const_null,
298299 info.ConstPtrInfo(const_null))
299 self.check_no_guards(nonnull_info, constant_info)
300 self.check_no_guards(nonnull_info, constant_ptr_info)
300301 self.check_invalid(nonnull_info, constantnull_info)
301302
302303
391392 value1 = IntUnbounded()
392393 value1.make_ge(IntBound(0, 10))
393394 value1.make_le(IntBound(20, 30))
394 info1 = NotVirtualStateInfo(self.cpu, 'i', value1)
395 info2 = NotVirtualStateInfo(self.cpu, 'i', IntUnbounded())
395 info1 = not_virtual(self.cpu, 'i', value1)
396 info2 = not_virtual(self.cpu, 'i', IntUnbounded())
396397 expected = """
397398 [i0]
398399 i1 = int_ge(i0, 0)
407408 value1 = IntUnbounded()
408409 value1.make_ge(IntBound(0, 10))
409410 value1.make_le(IntBound(20, 30))
410 info1 = NotVirtualStateInfo(self.cpu, 'i', value1)
411 info2 = NotVirtualStateInfo(self.cpu, 'i', ConstIntBound(10000))
411 info1 = not_virtual(self.cpu, 'i', value1)
412 info2 = not_virtual(self.cpu, 'i', ConstIntBound(10000))
412413 self.check_invalid(info1, info2)
413 info1 = NotVirtualStateInfo(self.cpu, 'i', value1)
414 info2 = NotVirtualStateInfo(self.cpu, 'i', ConstIntBound(11))
414 info1 = not_virtual(self.cpu, 'i', value1)
415 info2 = not_virtual(self.cpu, 'i', ConstIntBound(11))
415416 self.check_no_guards(info1, info2)
416417
417418 def test_known_class(self):
418419 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
419420 value1 = info.InstancePtrInfo(None, classbox)
420 info1 = NotVirtualStateInfo(self.cpu, 'r', value1)
421 info2 = NotVirtualStateInfo(self.cpu, 'r', None)
421 info1 = not_virtual(self.cpu, 'r', value1)
422 info2 = not_virtual(self.cpu, 'r', None)
422423 expected = """
423424 [p0]
424425 guard_nonnull_class(p0, ConstClass(node_vtable)) []
455456 def test_equal_inputargs(self):
456457 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
457458 value = info.InstancePtrInfo(None, classbox)
458 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
459 knownclass_info = not_virtual(self.cpu, 'r', value)
459460 vstate1 = VirtualState([knownclass_info, knownclass_info])
460461 assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
461462
462 unknown_info1 = NotVirtualStateInfo(self.cpu, 'r', None)
463 unknown_info1 = not_virtual(self.cpu, 'r', None)
463464 vstate2 = VirtualState([unknown_info1, unknown_info1])
464465 assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
465466 assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
466467 assert vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
467468
468 unknown_info1 = NotVirtualStateInfo(self.cpu, 'r', None)
469 unknown_info2 = NotVirtualStateInfo(self.cpu, 'r', None)
469 unknown_info1 = not_virtual(self.cpu, 'r', None)
470 unknown_info2 = not_virtual(self.cpu, 'r', None)
470471 vstate3 = VirtualState([unknown_info1, unknown_info2])
471472 assert vstate3.generalization_of(vstate2, FakeOptimizer(self.cpu))
472473 assert vstate3.generalization_of(vstate1, FakeOptimizer(self.cpu))
493494 def test_generate_guards_on_virtual_fields_matches_array(self):
494495 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
495496 innervalue1 = info.InstancePtrInfo(None, classbox)
496 innerinfo1 = NotVirtualStateInfo(self.cpu, 'r', innervalue1)
497 innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
497498 innerinfo1.position = 1
498 innerinfo2 = NotVirtualStateInfo(self.cpu, 'r', None)
499 innerinfo2 = not_virtual(self.cpu, 'r', None)
499500 innerinfo2.position = 1
500501
501502 descr = ArrayDescr(lltype.GcArray(llmemory.GCREF), self.cpu)
523524 def test_generate_guards_on_virtual_fields_matches_instance(self):
524525 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
525526 innervalue1 = info.InstancePtrInfo(None, classbox)
526 innerinfo1 = NotVirtualStateInfo(self.cpu, 'r', innervalue1)
527 innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
527528 innerinfo1.position = 1
528 innerinfo2 = NotVirtualStateInfo(self.cpu, 'r', None)
529 innerinfo2 = not_virtual(self.cpu, 'r', None)
529530 innerinfo2.position = 1
530531
531532 info1 = VirtualStateInfo(ConstInt(42), [self.nextdescr])
551552 def test_generate_guards_on_virtual_fields_matches_struct(self):
552553 constclassbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
553554 innervalue1 = info.InstancePtrInfo(None, constclassbox)
554 innerinfo1 = NotVirtualStateInfo(self.cpu, 'r', innervalue1)
555 innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
555556 innerinfo1.position = 1
556 innerinfo2 = NotVirtualStateInfo(self.cpu, 'r', None)
557 innerinfo2 = not_virtual(self.cpu, 'r', None)
557558 innerinfo2.position = 1
558559
559560 structdescr = self.nodesize
582583 def test_generate_guards_on_virtual_fields_matches_arraystruct(self):
583584 constclassbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
584585 innervalue1 = info.InstancePtrInfo(None, constclassbox)
585 innerinfo1 = NotVirtualStateInfo(self.cpu, 'r', innervalue1)
586 innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
586587 innerinfo1.position = 1
587 innerinfo2 = NotVirtualStateInfo(self.cpu, 'r', None)
588 innerinfo2 = not_virtual(self.cpu, 'r', None)
588589 innerinfo2.position = 1
589590
590591 NODE = lltype.Struct('NODE', ('x', llmemory.GCREF))
626627 assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
627628
628629 info2 = VirtualStateInfo(ConstInt(42), [1, 2])
629 unknown_info1 = NotVirtualStateInfo(self.cpu, 'r',
630 unknown_info1 = not_virtual(self.cpu, 'r',
630631 info.InstancePtrInfo())
631632 info2.fieldstate = [unknown_info1, unknown_info1]
632633 vstate2 = VirtualState([info2])
635636 assert vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
636637
637638 info3 = VirtualStateInfo(ConstInt(42), [1, 2])
638 unknown_info1 = NotVirtualStateInfo(self.cpu, 'r',
639 unknown_info1 = not_virtual(self.cpu, 'r',
639640 info.InstancePtrInfo())
640 unknown_info2 = NotVirtualStateInfo(self.cpu, 'r',
641 unknown_info2 = not_virtual(self.cpu, 'r',
641642 info.InstancePtrInfo())
642643 info3.fieldstate = [unknown_info1, unknown_info2]
643644 vstate3 = VirtualState([info3])
650651 info1 = VirtualStateInfo(ConstInt(42), [1, 2])
651652 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
652653 value = info.InstancePtrInfo(None, classbox)
653 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
654 knownclass_info = not_virtual(self.cpu, 'r', value)
654655 info1.fieldstate = [knownclass_info, knownclass_info]
655656 vstate1 = VirtualState([info1])
656657 assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
658659 info2 = VirtualStateInfo(ConstInt(42), [1, 2])
659660 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
660661 value = info.InstancePtrInfo(None, classbox)
661 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
662 knownclass_info = not_virtual(self.cpu, 'r', value)
662663 info2.fieldstate = [knownclass_info, knownclass_info]
663664 vstate2 = VirtualState([info2])
664665 assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
670671 info1 = VirtualStateInfo(ConstInt(42), [10, 20])
671672 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
672673 value = info.InstancePtrInfo(None, classbox)
673 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
674 knownclass_info = not_virtual(self.cpu, 'r', value)
674675 info1.fieldstate = [knownclass_info, knownclass_info]
675676 vstate1 = VirtualState([info1])
676677 assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
678679 info2 = VirtualStateInfo(ConstInt(42), [1, 2])
679680 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
680681 value = info.InstancePtrInfo(None, classbox)
681 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
682 knownclass_info = not_virtual(self.cpu, 'r', value)
682683 info2.fieldstate = [knownclass_info, knownclass_info]
683684 vstate2 = VirtualState([info2])
684685 assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
690691 info1 = VirtualStateInfo(ConstInt(42), [1, 2])
691692 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
692693 value = info.InstancePtrInfo(None, classbox)
693 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
694 knownclass_info = not_virtual(self.cpu, 'r', value)
694695 info1.fieldstate = [knownclass_info, knownclass_info]
695696 vstate1 = VirtualState([info1])
696697 assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
698699 info2 = VirtualStateInfo(ConstInt(7), [1, 2])
699700 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
700701 value = info.InstancePtrInfo(None, classbox)
701 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
702 knownclass_info = not_virtual(self.cpu, 'r', value)
702703 info2.fieldstate = [knownclass_info, knownclass_info]
703704 vstate2 = VirtualState([info2])
704705 assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
705706
706707 assert not vstate2.generalization_of(vstate1, FakeOptimizer(self.cpu))
707708 assert not vstate1.generalization_of(vstate2, FakeOptimizer(self.cpu))
708
709
709710 def test_nonvirtual_is_not_virtual(self):
710711 info1 = VirtualStateInfo(ConstInt(42), [1, 2])
711712 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
712713 value = info.InstancePtrInfo(None, classbox)
713 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
714 knownclass_info = not_virtual(self.cpu, 'r', value)
714715 info1.fieldstate = [knownclass_info, knownclass_info]
715716 vstate1 = VirtualState([info1])
716717 assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
717718
718 info2 = NotVirtualStateInfo(self.cpu, 'r', value)
719 info2 = not_virtual(self.cpu, 'r', value)
719720 vstate2 = VirtualState([info2])
720721 assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
721722
726727 info1 = VArrayStateInfo(42)
727728 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
728729 value = info.InstancePtrInfo(None, classbox)
729 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
730 knownclass_info = not_virtual(self.cpu, 'r', value)
730731 info1.fieldstate = [knownclass_info, knownclass_info]
731732 vstate1 = VirtualState([info1])
732733 assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
734735 info2 = VArrayStateInfo(42)
735736 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
736737 value = info.InstancePtrInfo(None, classbox)
737 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
738 knownclass_info = not_virtual(self.cpu, 'r', value)
738739 info2.fieldstate = [knownclass_info, knownclass_info]
739740 vstate2 = VirtualState([info2])
740741 assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
746747 info1 = VArrayStateInfo(42)
747748 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
748749 value = info.InstancePtrInfo(None, classbox)
749 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
750 knownclass_info = not_virtual(self.cpu, 'r', value)
750751 info1.fieldstate = [knownclass_info, knownclass_info]
751752 vstate1 = VirtualState([info1])
752753 assert vstate1.generalization_of(vstate1, FakeOptimizer(self.cpu))
754755 info2 = VArrayStateInfo(42)
755756 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.node2addr))
756757 value = info.InstancePtrInfo(None, classbox)
757 knownclass_info = NotVirtualStateInfo(self.cpu, 'r', value)
758 knownclass_info = not_virtual(self.cpu, 'r', value)
758759 info2.fieldstate = [knownclass_info]
759760 vstate2 = VirtualState([info2])
760761 assert vstate2.generalization_of(vstate2, FakeOptimizer(self.cpu))
792793 def test_crash_varay_clear(self):
793794 classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
794795 innervalue1 = info.InstancePtrInfo(None, classbox)
795 innerinfo1 = NotVirtualStateInfo(self.cpu, 'r', innervalue1)
796 innerinfo1 = not_virtual(self.cpu, 'r', innervalue1)
796797 innerinfo1.position = 1
797798 innerinfo1.position_in_notvirtuals = 0
798799
4444 return opinfo
4545
4646 def make_virtual_raw_memory(self, size, source_op):
47 opinfo = info.RawBufferPtrInfo(self.optimizer.cpu, size)
47 func = source_op.getarg(0).getint()
48 opinfo = info.RawBufferPtrInfo(self.optimizer.cpu, func, size)
4849 newop = self.replace_op_with(source_op, source_op.getopnum(),
4950 args=[source_op.getarg(0), ConstInt(size)])
5051 newop.set_forwarded(opinfo)
349349 def debug_header(self, indent):
350350 debug_print(indent + 'VArrayStructStateInfo(%d):' % self.position)
351351
352
353 def not_virtual(cpu, type, info):
354 if type == 'i':
355 return NotVirtualStateInfoInt(cpu, type, info)
356 if type == 'r':
357 return NotVirtualStateInfoPtr(cpu, type, info)
358 return NotVirtualStateInfo(cpu, type, info)
359
360
352361 class NotVirtualStateInfo(AbstractVirtualStateInfo):
353 lenbound = None
354 intbound = None
355362 level = LEVEL_UNKNOWN
356363 constbox = None
357 known_class = None
358
364
359365 def __init__(self, cpu, type, info):
360366 if info and info.is_constant():
361367 self.level = LEVEL_CONSTANT
362368 self.constbox = info.getconst()
363 if type == 'r':
364 self.known_class = info.get_known_class(cpu)
365 elif type == 'i':
366 self.intbound = info
367 elif type == 'r':
368 if info:
369 self.known_class = info.get_known_class(cpu)
370 if self.known_class:
371 self.level = LEVEL_KNOWNCLASS
372 elif info.is_nonnull():
373 self.level = LEVEL_NONNULL
374 self.lenbound = info.getlenbound(None)
375 elif type == 'i':
376 if isinstance(info, IntBound):
377 if info.lower < MININT / 2:
378 info.lower = MININT
379 if info.upper > MAXINT / 2:
380 info.upper = MAXINT
381 self.intbound = info
382 elif type == 'f':
383 if info and info.is_constant():
384 self.level = LEVEL_CONSTANT
385 self.constbox = info.getconst()
386369
387370 def is_const(self):
388371 return self.constbox is not None
393376 def _generate_guards(self, other, box, runtime_box, state):
394377 # XXX This will always retrace instead of forcing anything which
395378 # might be what we want sometimes?
396 if not isinstance(other, NotVirtualStateInfo):
397 raise VirtualStatesCantMatch(
398 'The VirtualStates does not match as a ' +
399 'virtual appears where a pointer is needed ' +
400 'and it is too late to force it.')
401
402
403379 extra_guards = state.extra_guards
404 cpu = state.cpu
405 if self.lenbound:
406 if other.lenbound is None:
407 other_bound = IntLowerBound(0)
408 else:
409 other_bound = other.lenbound
410 if not self.lenbound.contains_bound(other_bound):
411 raise VirtualStatesCantMatch("length bound does not match")
412
413380 if self.level == LEVEL_UNKNOWN:
414 # confusingly enough, this is done also for pointers
415 # which have the full range as the "bound", so it always works
416 return self._generate_guards_intbounds(other, box, runtime_box,
417 extra_guards,
418 state.optimizer)
419
420 # the following conditions often peek into the runtime value that the
421 # box had when tracing. This value is only used as an educated guess.
422 # It is used here to choose between either emitting a guard and jumping
423 # to an existing compiled loop or retracing the loop. Both alternatives
424 # will always generate correct behaviour, but performance will differ.
425 elif self.level == LEVEL_NONNULL:
426 if other.level == LEVEL_UNKNOWN:
427 if runtime_box is not None and runtime_box.nonnull():
428 op = ResOperation(rop.GUARD_NONNULL, [box])
429 extra_guards.append(op)
430 return
431 else:
432 raise VirtualStatesCantMatch("other not known to be nonnull")
433 elif other.level == LEVEL_NONNULL:
434 return
435 elif other.level == LEVEL_KNOWNCLASS:
436 return # implies nonnull
437 else:
438 assert other.level == LEVEL_CONSTANT
439 assert other.constbox
440 if not other.constbox.nonnull():
441 raise VirtualStatesCantMatch("constant is null")
442 return
443
444 elif self.level == LEVEL_KNOWNCLASS:
445 if other.level == LEVEL_UNKNOWN:
446 if (runtime_box and runtime_box.nonnull() and
447 self.known_class.same_constant(cpu.ts.cls_of_box(runtime_box))):
448 op = ResOperation(rop.GUARD_NONNULL_CLASS, [box, self.known_class])
449 extra_guards.append(op)
450 return
451 else:
452 raise VirtualStatesCantMatch("other's class is unknown")
453 elif other.level == LEVEL_NONNULL:
454 if (runtime_box and self.known_class.same_constant(
455 cpu.ts.cls_of_box(runtime_box))):
456 op = ResOperation(rop.GUARD_CLASS, [box, self.known_class])
457 extra_guards.append(op)
458 return
459 else:
460 raise VirtualStatesCantMatch("other's class is unknown")
461 elif other.level == LEVEL_KNOWNCLASS:
462 if self.known_class.same_constant(other.known_class):
463 return
464 raise VirtualStatesCantMatch("classes don't match")
465 else:
466 assert other.level == LEVEL_CONSTANT
467 if (other.constbox.nonnull() and
468 self.known_class.same_constant(cpu.ts.cls_of_box(other.constbox))):
469 return
470 else:
471 raise VirtualStatesCantMatch("classes don't match")
472
473 else:
381 return self._generate_guards_unkown(other, box, runtime_box,
382 extra_guards,
383 state)
384 else:
385 if not isinstance(other, NotVirtualStateInfo):
386 raise VirtualStatesCantMatch(
387 'comparing a constant against something that is a virtual')
474388 assert self.level == LEVEL_CONSTANT
475389 if other.level == LEVEL_CONSTANT:
476390 if self.constbox.same_constant(other.constbox):
484398 raise VirtualStatesCantMatch("other not constant")
485399 assert 0, "unreachable"
486400
487 def _generate_guards_intbounds(self, other, box, runtime_box, extra_guards,
488 optimizer):
489 if self.intbound is None:
490 return
491 if self.intbound.contains_bound(other.intbound):
492 return
493 if (runtime_box is not None and
494 self.intbound.contains(runtime_box.getint())):
495 # this may generate a few more guards than needed, but they are
496 # optimized away when emitting them
497 self.intbound.make_guards(box, extra_guards, optimizer)
498 return
499 raise VirtualStatesCantMatch("intbounds don't match")
401 def _generate_guards_unkown(self, other, box, runtime_box, extra_guards,
402 state):
403 return
500404
501405 def enum_forced_boxes(self, boxes, box, optimizer, force_boxes=False):
502406 if self.level == LEVEL_CONSTANT:
552456 if self.lenbound:
553457 lb = ', ' + self.lenbound.bound.__repr__()
554458
555 debug_print(indent + mark + 'NotVirtualInfo(%d' % self.position +
556 ', ' + l + ', ' + self.intbound.__repr__() + lb + ')')
459 result = indent + mark + 'NotVirtualStateInfo(%d' % self.position + ', ' + l
460 extra = self._extra_repr()
461 if extra:
462 result += ', ' + extra
463 result += lb + ')'
464 debug_print(result)
465
466 class NotVirtualStateInfoInt(NotVirtualStateInfo):
467 intbound = None
468
469 def __init__(self, cpu, type, info):
470 NotVirtualStateInfo.__init__(self, cpu, type, info)
471 assert type == 'i'
472 if isinstance(info, IntBound):
473 if info.lower < MININT / 2:
474 info.lower = MININT
475 if info.upper > MAXINT / 2:
476 info.upper = MAXINT
477 self.intbound = info
478
479 def _generate_guards_unkown(self, other, box, runtime_box, extra_guards,
480 state):
481 other_intbound = None
482 if isinstance(other, NotVirtualStateInfoInt):
483 other_intbound = other.intbound
484 if self.intbound is None:
485 return
486 if self.intbound.contains_bound(other_intbound):
487 return
488 if (runtime_box is not None and
489 self.intbound.contains(runtime_box.getint())):
490 # this may generate a few more guards than needed, but they are
491 # optimized away when emitting them
492 self.intbound.make_guards(box, extra_guards, state.optimizer)
493 return
494 raise VirtualStatesCantMatch("intbounds don't match")
495
496 def _extra_repr(self):
497 return self.intbound.__repr__()
498
499
500 class NotVirtualStateInfoPtr(NotVirtualStateInfo):
501 lenbound = None
502 known_class = None
503
504 def __init__(self, cpu, type, info):
505 if info:
506 self.known_class = info.get_known_class(cpu)
507 if self.known_class:
508 self.level = LEVEL_KNOWNCLASS
509 elif info.is_nonnull():
510 self.level = LEVEL_NONNULL
511 self.lenbound = info.getlenbound(None)
512 # might set it to LEVEL_CONSTANT
513 NotVirtualStateInfo.__init__(self, cpu, type, info)
514
515 def _generate_guards(self, other, box, runtime_box, state):
516 if not isinstance(other, NotVirtualStateInfoPtr):
517 raise VirtualStatesCantMatch(
518 'The VirtualStates does not match as a ' +
519 'virtual appears where a pointer is needed ' +
520 'and it is too late to force it.')
521 extra_guards = state.extra_guards
522 if self.lenbound:
523 if other.lenbound is None:
524 other_bound = IntLowerBound(0)
525 else:
526 other_bound = other.lenbound
527 if not self.lenbound.contains_bound(other_bound):
528 raise VirtualStatesCantMatch("length bound does not match")
529 if self.level == LEVEL_NONNULL:
530 return self._generate_guards_nonnull(other, box, runtime_box,
531 extra_guards,
532 state)
533 elif self.level == LEVEL_KNOWNCLASS:
534 return self._generate_guards_knownclass(other, box, runtime_box,
535 extra_guards,
536 state)
537 return NotVirtualStateInfo._generate_guards(self, other, box,
538 runtime_box, state)
539
540
541 # the following methods often peek into the runtime value that the
542 # box had when tracing. This value is only used as an educated guess.
543 # It is used here to choose between either emitting a guard and jumping
544 # to an existing compiled loop or retracing the loop. Both alternatives
545 # will always generate correct behaviour, but performance will differ.
546
547 def _generate_guards_nonnull(self, other, box, runtime_box, extra_guards,
548 state):
549 if not isinstance(other, NotVirtualStateInfoPtr):
550 raise VirtualStatesCantMatch('trying to match ptr with non-ptr??!')
551 if other.level == LEVEL_UNKNOWN:
552 if runtime_box is not None and runtime_box.nonnull():
553 op = ResOperation(rop.GUARD_NONNULL, [box])
554 extra_guards.append(op)
555 return
556 else:
557 raise VirtualStatesCantMatch("other not known to be nonnull")
558 elif other.level == LEVEL_NONNULL:
559 pass
560 elif other.level == LEVEL_KNOWNCLASS:
561 pass # implies nonnull
562 else:
563 assert other.level == LEVEL_CONSTANT
564 assert other.constbox
565 if not other.constbox.nonnull():
566 raise VirtualStatesCantMatch("constant is null")
567
568 def _generate_guards_knownclass(self, other, box, runtime_box, extra_guards,
569 state):
570 cpu = state.cpu
571 if not isinstance(other, NotVirtualStateInfoPtr):
572 raise VirtualStatesCantMatch('trying to match ptr with non-ptr??!')
573 if other.level == LEVEL_UNKNOWN:
574 if (runtime_box and runtime_box.nonnull() and
575 self.known_class.same_constant(cpu.ts.cls_of_box(runtime_box))):
576 op = ResOperation(rop.GUARD_NONNULL_CLASS, [box, self.known_class])
577 extra_guards.append(op)
578 else:
579 raise VirtualStatesCantMatch("other's class is unknown")
580 elif other.level == LEVEL_NONNULL:
581 if (runtime_box and self.known_class.same_constant(
582 cpu.ts.cls_of_box(runtime_box))):
583 op = ResOperation(rop.GUARD_CLASS, [box, self.known_class])
584 extra_guards.append(op)
585 else:
586 raise VirtualStatesCantMatch("other's class is unknown")
587 elif other.level == LEVEL_KNOWNCLASS:
588 if self.known_class.same_constant(other.known_class):
589 return
590 raise VirtualStatesCantMatch("classes don't match")
591 else:
592 assert other.level == LEVEL_CONSTANT
593 if (other.constbox.nonnull() and
594 self.known_class.same_constant(cpu.ts.cls_of_box(other.constbox))):
595 pass
596 else:
597 raise VirtualStatesCantMatch("classes don't match")
557598
558599
559600 class VirtualState(object):
677718 return VirtualState(state)
678719
679720 def visit_not_virtual(self, box):
680 return NotVirtualStateInfo(self.optimizer.cpu, box.type,
681 self.optimizer.getinfo(box))
721 return not_virtual(self.optimizer.cpu, box.type,
722 self.optimizer.getinfo(box))
682723
683724 def visit_virtual(self, descr, fielddescrs):
684725 known_class = ConstInt(descr.get_vtable())
1212 from rpython.jit.metainterp.logger import Logger
1313 from rpython.jit.metainterp.optimizeopt.util import args_dict
1414 from rpython.jit.metainterp.resoperation import rop, OpHelpers, GuardResOp
15 from rpython.rlib.rjitlog import rjitlog as jl
1516 from rpython.rlib import nonconst, rstack
1617 from rpython.rlib.debug import debug_start, debug_stop, debug_print
1718 from rpython.rlib.debug import have_debug_prints, make_sure_not_resized
828829 mutatefielddescr, orgpc):
829830 from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr
830831 cpu = self.metainterp.cpu
832 if self.metainterp.heapcache.is_quasi_immut_known(fielddescr, box):
833 return
831834 descr = QuasiImmutDescr(cpu, box.getref_base(), fielddescr,
832835 mutatefielddescr)
836 self.metainterp.heapcache.quasi_immut_now_known(fielddescr, box)
833837 self.metainterp.history.record(rop.QUASIIMMUT_FIELD, [box],
834838 None, descr=descr)
835839 self.metainterp.generate_guard(rop.GUARD_NOT_INVALIDATED,
14481452 metainterp.history.record(rop.VIRTUAL_REF_FINISH,
14491453 [vrefbox, nullbox], None)
14501454
1455 @arguments("int", "box")
1456 def opimpl_rvmprof_code(self, leaving, box_unique_id):
1457 from rpython.rlib.rvmprof import cintf
1458 cintf.jit_rvmprof_code(leaving, box_unique_id.getint())
1459
1460 def handle_rvmprof_enter_on_resume(self):
1461 code = self.bytecode
1462 position = self.pc
1463 opcode = ord(code[position])
1464 if opcode == self.metainterp.staticdata.op_rvmprof_code:
1465 arg1 = self.registers_i[ord(code[position + 1])].getint()
1466 arg2 = self.registers_i[ord(code[position + 2])].getint()
1467 if arg1 == 1:
1468 # we are resuming at a position that will do a
1469 # jit_rvmprof_code(1), when really executed. That's a
1470 # hint for the need for a jit_rvmprof_code(0).
1471 from rpython.rlib.rvmprof import cintf
1472 cintf.jit_rvmprof_code(0, arg2)
1473
14511474 # ------------------------------
14521475
14531476 def setup_call(self, argboxes):
17561779 self.cpu = cpu
17571780 self.stats = self.cpu.stats
17581781 self.options = options
1782 self.jitlog = jl.JitLogger(self.cpu)
17591783 self.logger_noopt = Logger(self)
17601784 self.logger_ops = Logger(self, guard_number=True)
1785 # legacy loggers
1786 self.jitlog.logger_noopt = self.logger_noopt
1787 self.jitlog.logger_ops = self.logger_ops
17611788
17621789 self.profiler = ProfilerClass()
17631790 self.profiler.cpu = cpu
17951822 opimpl = _get_opimpl_method(name, argcodes)
17961823 self.opcode_implementations[value] = opimpl
17971824 self.op_catch_exception = insns.get('catch_exception/L', -1)
1825 self.op_rvmprof_code = insns.get('rvmprof_code/ii', -1)
17981826
17991827 def setup_descrs(self, descrs):
18001828 self.opcode_descrs = descrs
18451873 def _setup_once(self):
18461874 """Runtime setup needed by the various components of the JIT."""
18471875 if not self.globaldata.initialized:
1876 self.jitlog.setup_once()
18481877 debug_print(self.jit_starting_line)
18491878 self.cpu.setup_once()
18501879 if not self.profiler.initialized:
19211950 self.initialized = False
19221951 self.indirectcall_dict = None
19231952 self.addr2name = None
1924 self.loopnumbering = 0
19251953
19261954 # ____________________________________________________________
19271955
20622090 target = ord(code[position+1]) | (ord(code[position+2])<<8)
20632091 frame.pc = target
20642092 raise ChangeFrame
2093 if opcode == self.staticdata.op_rvmprof_code:
2094 # call the 'jit_rvmprof_code(1)' for rvmprof, but then
2095 # continue popping frames. Decode the 'rvmprof_code' insn
2096 # manually here.
2097 from rpython.rlib.rvmprof import cintf
2098 arg1 = frame.registers_i[ord(code[position + 1])].getint()
2099 arg2 = frame.registers_i[ord(code[position + 2])].getint()
2100 assert arg1 == 1
2101 cintf.jit_rvmprof_code(arg1, arg2)
20652102 self.popframe()
20662103 try:
20672104 self.compile_exit_frame_with_exception(self.last_exc_box)
25392576 elif box.type == history.REF: args.append(box.getref_base())
25402577 elif box.type == history.FLOAT: args.append(box.getfloatstorage())
25412578 else: assert 0
2542 self.jitdriver_sd.warmstate.execute_assembler(loop_token, *args)
2579 res = self.jitdriver_sd.warmstate.execute_assembler(loop_token, *args)
2580 kind = history.getkind(lltype.typeOf(res))
2581 if kind == 'void': raise jitexc.DoneWithThisFrameVoid()
2582 if kind == 'int': raise jitexc.DoneWithThisFrameInt(res)
2583 if kind == 'ref': raise jitexc.DoneWithThisFrameRef(self.cpu, res)
2584 if kind == 'float': raise jitexc.DoneWithThisFrameFloat(res)
2585 raise AssertionError(kind)
25432586
25442587 def prepare_resume_from_failure(self, deadframe, inputargs, resumedescr):
25452588 exception = self.cpu.grab_exc_value(deadframe)
11561156 'CALL_RELEASE_GIL/*d/fin',
11571157 # release the GIL and "close the stack" for asmgcc
11581158 'CALL_PURE/*d/rfin', # removed before it's passed to the backend
1159 'CALL_MALLOC_GC/*d/r', # like CALL, but NULL => propagate MemoryError
1159 'CHECK_MEMORY_ERROR/1/n', # after a CALL: NULL => propagate MemoryError
11601160 'CALL_MALLOC_NURSERY/1/r', # nursery malloc, const number of bytes, zeroed
11611161 'CALL_MALLOC_NURSERY_VARSIZE/3d/r',
11621162 'CALL_MALLOC_NURSERY_VARSIZE_FRAME/1/r',
363363 def visit_varraystruct(self, arraydescr, size, fielddescrs):
364364 return VArrayStructInfo(arraydescr, size, fielddescrs)
365365
366 def visit_vrawbuffer(self, size, offsets, descrs):
367 return VRawBufferInfo(size, offsets, descrs)
366 def visit_vrawbuffer(self, func, size, offsets, descrs):
367 return VRawBufferInfo(func, size, offsets, descrs)
368368
369369 def visit_vrawslice(self, offset):
370370 return VRawSliceInfo(offset)
702702
703703 class VRawBufferInfo(VAbstractRawInfo):
704704
705 def __init__(self, size, offsets, descrs):
705 def __init__(self, func, size, offsets, descrs):
706 self.func = func
706707 self.size = size
707708 self.offsets = offsets
708709 self.descrs = descrs
710711 @specialize.argtype(1)
711712 def allocate_int(self, decoder, index):
712713 length = len(self.fieldnums)
713 buffer = decoder.allocate_raw_buffer(self.size)
714 buffer = decoder.allocate_raw_buffer(self.func, self.size)
714715 decoder.virtuals_cache.set_int(index, buffer)
715716 for i in range(len(self.offsets)):
716717 offset = self.offsets[i]
10571058 f.setup_resume_at_op(pc)
10581059 resumereader.consume_boxes(f.get_current_position_info(),
10591060 f.registers_i, f.registers_r, f.registers_f)
1061 f.handle_rvmprof_enter_on_resume()
10601062 return resumereader.liveboxes, virtualizable_boxes, virtualref_boxes
10611063
10621064
11281130 lengthbox)
11291131 return self.metainterp.execute_new_array(arraydescr, lengthbox)
11301132
1131 def allocate_raw_buffer(self, size):
1133 def allocate_raw_buffer(self, func, size):
11321134 cic = self.metainterp.staticdata.callinfocollection
1133 calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)
1135 calldescr, _ = cic.callinfo_for_oopspec(EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)
1136 # Can't use 'func' from callinfo_for_oopspec(), because we have
1137 # several variants (zero/non-zero, memory-pressure or not, etc.)
1138 # and we have to pick the correct one here; that's why we save
1139 # it in the VRawBufferInfo.
11341140 return self.metainterp.execute_and_record_varargs(
11351141 rop.CALL_I, [ConstInt(func), ConstInt(size)], calldescr)
11361142
13421348 jitcode = jitcodes[jitcode_pos]
13431349 curbh.setposition(jitcode, pc)
13441350 resumereader.consume_one_section(curbh)
1351 curbh.handle_rvmprof_enter()
13451352 return curbh
13461353
13471354 def force_from_resumedata(metainterp_sd, storage, deadframe, vinfo, ginfo):
14581465 def allocate_string(self, length):
14591466 return self.cpu.bh_newstr(length)
14601467
1461 def allocate_raw_buffer(self, size):
1462 buffer = self.cpu.bh_new_raw_buffer(size)
1463 adr = llmemory.cast_ptr_to_adr(buffer)
1464 return llmemory.cast_adr_to_int(adr, "symbolic")
1468 def allocate_raw_buffer(self, func, size):
1469 from rpython.jit.codewriter import heaptracker
1470 cic = self.callinfocollection
1471 calldescr, _ = cic.callinfo_for_oopspec(EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)
1472 return self.cpu.bh_call_i(func, [size], None, None, calldescr)
14651473
14661474 def string_setitem(self, str, index, charnum):
14671475 char = self.decode_int(charnum)
6363 testself.all_graphs = graphs
6464 result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
6565
66
67 class FakeJitDriver:
68 name = 'fakejitdriver'
69
6670 class FakeJitDriverSD:
6771 num_green_args = 0
6872 portal_graph = graphs[0]
7175 result_type = result_kind
7276 portal_runner_ptr = "???"
7377 vec = False
78 jitdriver = FakeJitDriver()
7479
7580 stats = history.Stats(None)
7681 cpu = CPUClass(rtyper, stats, None, False)
953953 return t
954954 res = self.meta_interp(f, [-5])
955955 assert res == 5+4+3+2+1+0+1+2+3+4+5+6+7+8+9
956
957 def test_int_c_div(self):
958 from rpython.rlib.rarithmetic import int_c_div
959 myjitdriver = JitDriver(greens = [], reds = ['i', 't'])
960 def f(i):
961 t = 0
962 while i < 10:
963 myjitdriver.can_enter_jit(i=i, t=t)
964 myjitdriver.jit_merge_point(i=i, t=t)
965 t += int_c_div(-100, i)
966 i += 1
967 return t
968 expected = -sum([100 // n for n in range(1, 10)])
969 assert f(1) == expected
970 res = self.meta_interp(f, [1])
971 assert res == expected
972 # should contain a call_i(..., OS=OS_INT_PY_DIV)
973
974 def test_int_c_mod(self):
975 from rpython.rlib.rarithmetic import int_c_mod
976 myjitdriver = JitDriver(greens = [], reds = ['i', 't'])
977 def f(i):
978 t = 0
979 while i < 10:
980 myjitdriver.can_enter_jit(i=i, t=t)
981 myjitdriver.jit_merge_point(i=i, t=t)
982 t += int_c_mod(-100, i)
983 i += 1
984 return t
985 expected = -sum([100 % n for n in range(1, 10)])
986 assert f(1) == expected
987 res = self.meta_interp(f, [1])
988 assert res == expected
989 # should contain a call_i(..., OS=OS_INT_PY_MOD)
990
991 def test_positive_c_div_mod(self):
992 from rpython.rlib.rarithmetic import int_c_div, int_c_mod
993 myjitdriver = JitDriver(greens = [], reds = ['i', 't'])
994 def f(i):
995 t = 0
996 while i < 10:
997 myjitdriver.can_enter_jit(i=i, t=t)
998 myjitdriver.jit_merge_point(i=i, t=t)
999 assert i > 0
1000 t += int_c_div(100, i) - int_c_mod(100, i)
1001 i += 1
1002 return t
1003 expected = sum([100 // n - 100 % n for n in range(1, 10)])
1004 assert f(1) == expected
1005 res = self.meta_interp(f, [1])
1006 assert res == expected
1007 # all the correction code should be dead now, xxx test that
1008
1009 def test_int_c_div_by_constant(self):
1010 from rpython.rlib.rarithmetic import int_c_div
1011 myjitdriver = JitDriver(greens = ['k'], reds = ['i', 't'])
1012 def f(i, k):
1013 t = 0
1014 while i < 100:
1015 myjitdriver.can_enter_jit(i=i, t=t, k=k)
1016 myjitdriver.jit_merge_point(i=i, t=t, k=k)
1017 t += int_c_div(i, k)
1018 i += 1
1019 return t
1020 expected = sum([i // 10 for i in range(51, 100)])
1021 assert f(-50, 10) == expected
1022 res = self.meta_interp(f, [-50, 10])
1023 assert res == expected
1024 self.check_resops(call=0, uint_mul_high=2)
9561025
9571026 def test_float(self):
9581027 myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
44004469
44014470 self.meta_interp(f, [])
44024471
4472 def test_issue2335_recursion(self):
4473 # Reproduces issue #2335: same as issue #2200, but the workaround
4474 # in c4c54cb69aba was not enough.
4475 driver = JitDriver(greens=["level"], reds=["i"])
4476 def enter(level, i):
4477 if level == 0:
4478 f(1) # recursive call
4479 driver.can_enter_jit(level=level, i=i)
4480 def f(level):
4481 i = 0 if level == 0 else 298
4482 while True:
4483 driver.jit_merge_point(level=level, i=i)
4484 i += 1
4485 if i >= 300:
4486 return i
4487 promote(i + 1) # a failing guard
4488 enter(level, i)
4489 def main():
4490 set_param(None, 'trace_eagerness', 999999)
4491 f(0)
4492 self.meta_interp(main, [])
4493
44034494 def test_pending_setarrayitem_with_indirect_constant_index(self):
44044495 driver = JitDriver(greens=[], reds='auto')
44054496 class X:
33 from rpython.jit.metainterp.compile import compile_loop
44 from rpython.jit.metainterp.compile import compile_tmp_callback
55 from rpython.jit.metainterp import jitexc
6 from rpython.rlib.rjitlog import rjitlog as jl
67 from rpython.jit.metainterp import jitprof, typesystem, compile
78 from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin
89 from rpython.jit.tool.oparser import parse, convert_loop_to_trace
5051 return 'location'
5152
5253 class FakeGlobalData(object):
53 loopnumbering = 0
54 pass
5455
5556 class FakeMetaInterpStaticData(object):
5657 all_descrs = []
5758 logger_noopt = FakeLogger()
5859 logger_ops = FakeLogger()
5960 config = get_combined_translation_config(translating=True)
61 jitlog = jl.JitLogger()
6062
6163 stats = Stats(None)
6264 profiler = jitprof.EmptyProfiler()
7779 cpu = FakeCPU()
7880 staticdata = FakeMetaInterpStaticData()
7981 staticdata.cpu = cpu
80 staticdata.globaldata = FakeGlobalData()
81 staticdata.globaldata.loopnumbering = 1
82 staticdata.jitlog = jl.JitLogger(cpu)
83 staticdata.jitlog.trace_id = 1
8284 #
8385 loop = parse('''
8486 [p1]
105107 jitcell_token = target_token.targeting_jitcell_token
106108 assert jitcell_token == target_token.original_jitcell_token
107109 assert jitcell_token.target_tokens == [target_token]
108 assert jitcell_token.number == 1
109 assert staticdata.globaldata.loopnumbering == 2
110 assert jitcell_token.number == 2
110111 #
111112 assert len(cpu.seen) == 1
112113 assert cpu.seen[0][2] == jitcell_token
1010 from rpython.rlib.jit_libffi import (types, CIF_DESCRIPTION, FFI_TYPE_PP,
1111 jit_ffi_call)
1212 from rpython.rlib.unroll import unrolling_iterable
13 from rpython.rlib.rarithmetic import intmask, r_longlong, r_singlefloat
13 from rpython.rlib.rarithmetic import intmask, r_longlong, r_singlefloat, r_uint
1414 from rpython.rlib.longlong2float import float2longlong
1515
1616 def get_description(atypes, rtype):
229229
230230 def test_handle_unsigned(self):
231231 self._run([types.ulong], types.ulong,
232 [rffi.cast(rffi.ULONG, sys.maxint + 91348)],
233 rffi.cast(rffi.ULONG, sys.maxint + 4242))
232 [rffi.cast(rffi.ULONG, r_uint(sys.maxint + 91348))],
233 rffi.cast(rffi.ULONG, r_uint(sys.maxint + 4242)))
234234
235235 def test_handle_unsignedchar(self):
236236 self._run([types.uint8], types.uint8,
796796 h.class_now_known(box1) # interaction of the two families of flags
797797 assert not h.is_unescaped(box1)
798798 assert h.is_likely_virtual(box1)
799
800 def test_quasiimmut_seen(self):
801 h = HeapCache()
802 box1 = RefFrontendOp(1)
803 box2 = RefFrontendOp(2)
804 box3 = RefFrontendOp(3)
805 box4 = RefFrontendOp(4)
806 assert not h.is_quasi_immut_known(descr1, box1)
807 assert not h.is_quasi_immut_known(descr1, box2)
808 assert not h.is_quasi_immut_known(descr2, box3)
809 assert not h.is_quasi_immut_known(descr2, box4)
810 h.quasi_immut_now_known(descr1, box1)
811 assert h.is_quasi_immut_known(descr1, box1)
812 assert not h.is_quasi_immut_known(descr1, box2)
813 assert not h.is_quasi_immut_known(descr2, box3)
814 assert not h.is_quasi_immut_known(descr2, box4)
815 h.quasi_immut_now_known(descr1, box2)
816 assert h.is_quasi_immut_known(descr1, box1)
817 assert h.is_quasi_immut_known(descr1, box2)
818 assert not h.is_quasi_immut_known(descr2, box3)
819 assert not h.is_quasi_immut_known(descr2, box4)
820 h.quasi_immut_now_known(descr2, box3)
821 assert h.is_quasi_immut_known(descr1, box1)
822 assert h.is_quasi_immut_known(descr1, box2)
823 assert h.is_quasi_immut_known(descr2, box3)
824 assert not h.is_quasi_immut_known(descr2, box4)
825 h.quasi_immut_now_known(descr2, box4)
826 assert h.is_quasi_immut_known(descr1, box1)
827 assert h.is_quasi_immut_known(descr1, box2)
828 assert h.is_quasi_immut_known(descr2, box3)
829 assert h.is_quasi_immut_known(descr2, box4)
830
831 # invalidate the descr1 cache
832
833 h.setfield(box1, box3, descr1)
834 assert not h.is_quasi_immut_known(descr1, box1)
835 assert not h.is_quasi_immut_known(descr1, box2)
836
837 # a call invalidates everything
838 h.invalidate_caches(
839 rop.CALL_N, FakeCallDescr(FakeEffectinfo.EF_CAN_RAISE), [])
840 assert not h.is_quasi_immut_known(descr2, box3)
841 assert not h.is_quasi_immut_known(descr2, box4)
247247 tokens = [t() for t in get_stats().jitcell_token_wrefs]
248248 # Some loops have been freed
249249 assert None in tokens
250 # Loop with number 0, h(), has not been freed
251 assert 0 in [t.number for t in tokens if t]
250 # Loop with number 1, h(), has not been freed
251 assert 1 in [t.number for t in tokens if t]
252252
253253 # ____________________________________________________________
254254
511511 assert res == 4 * 7
512512 self.check_operations_history(getfield_gc_i=2, getfield_gc_r=2)
513513
514 def test_heap_caching_quasi_immutable(self):
515 class A:
516 _immutable_fields_ = ['x?']
517 a1 = A()
518 a1.x = 5
519 a2 = A()
520 a2.x = 7
521
522 @jit.elidable
523 def get(n):
524 if n > 0:
525 return a1
526 return a2
527
528 def g(a):
529 return a.x
530
531 def fn(n):
532 jit.promote(n)
533 a = get(n)
534 return g(a) + a.x
535 res = self.interp_operations(fn, [7])
536 assert res == 10
537 self.check_operations_history(quasiimmut_field=1)
538
539
514540 def test_heap_caching_multiple_tuples(self):
515541 class Gbl(object):
516542 pass
13801380 return result
13811381
13821382 def indirection(arg):
1383 return interp(arg)
1383 return interp(arg) + 1
13841384
13851385 def run_interp(n):
13861386 f = hint(Frame(n), access_directly=True)
1616 def visit_varraystruct(self, arraydescr, fielddescrs):
1717 raise NotImplementedError("abstract base class")
1818
19 def visit_vrawbuffer(self, size, offsets, descrs):
19 def visit_vrawbuffer(self, func, size, offsets, descrs):
2020 raise NotImplementedError("abstract base class")
2121
2222 def visit_vrawslice(self, offset):
55 cast_base_ptr_to_instance, hlstr, cast_instance_to_gcref)
66 from rpython.rtyper.llannotation import lltype_to_annotation
77 from rpython.annotator import model as annmodel
8 from rpython.annotator.dictdef import DictDef
89 from rpython.rtyper.llinterp import LLException
910 from rpython.rtyper.test.test_llinterp import get_interpreter, clear_tcache
1011 from rpython.flowspace.model import SpaceOperation, Variable, Constant
118119 return interp, graph
119120 res = interp.eval_graph(graph, args)
120121 if not kwds.get('translate_support_code', False):
122 warmrunnerdesc.metainterp_sd.jitlog.finish()
121123 warmrunnerdesc.metainterp_sd.profiler.finish()
122124 warmrunnerdesc.metainterp_sd.cpu.finish_once()
123125 print '~~~ return value:', repr(res)
449451 merge_if_blocks=True,
450452 constfold=True,
451453 remove_asserts=True,
452 really_remove_asserts=True)
454 really_remove_asserts=True,
455 replace_we_are_jitted=False)
453456
454457 def prejit_optimizations_minimal_inline(self, policy, graphs):
455458 from rpython.translator.backendopt.inline import auto_inline_graphs
528531 def make_enter_function(self, jd):
529532 from rpython.jit.metainterp.warmstate import WarmEnterState
530533 state = WarmEnterState(self, jd)
531 maybe_compile_and_run = state.make_entry_point()
534 maybe_compile_and_run, EnterJitAssembler = state.make_entry_point()
532535 jd.warmstate = state
533536
534537 def crash_in_jit(e):
559562 maybe_enter_jit._always_inline_ = True
560563 jd._maybe_enter_jit_fn = maybe_enter_jit
561564 jd._maybe_compile_and_run_fn = maybe_compile_and_run
565 jd._EnterJitAssembler = EnterJitAssembler
562566
563567 def make_driverhook_graphs(self):
564 s_Str = annmodel.SomeString()
565568 #
566569 annhelper = MixLevelHelperAnnotator(self.translator.rtyper)
567570 for jd in self.jitdrivers_sd:
568571 jd._get_printable_location_ptr = self._make_hook_graph(jd,
569 annhelper, jd.jitdriver.get_printable_location, s_Str)
572 annhelper, jd.jitdriver.get_printable_location,
573 annmodel.SomeString())
570574 jd._get_unique_id_ptr = self._make_hook_graph(jd,
571575 annhelper, jd.jitdriver.get_unique_id, annmodel.SomeInteger())
572576 jd._confirm_enter_jit_ptr = self._make_hook_graph(jd,
577581 jd._should_unroll_one_iteration_ptr = self._make_hook_graph(jd,
578582 annhelper, jd.jitdriver.should_unroll_one_iteration,
579583 annmodel.s_Bool)
584 #
585 items = []
586 types = ()
587 pos = ()
588 if jd.jitdriver.get_location:
589 assert hasattr(jd.jitdriver.get_location, '_loc_types'), """
590 You must decorate your get_location function:
591
592 from rpython.rlib.rjitlog import rjitlog as jl
593 @jl.returns(jl.MP_FILENAME, jl.MP_XXX, ...)
594 def get_loc(your, green, keys):
595 name = "x.txt" # extract it from your green keys
596 return (name, ...)
597 """
598 types = jd.jitdriver.get_location._loc_types
599 del jd.jitdriver.get_location._loc_types
600 #
601 for _,type in types:
602 if type == 's':
603 items.append(annmodel.SomeString())
604 elif type == 'i':
605 items.append(annmodel.SomeInteger())
606 else:
607 raise NotImplementedError
608 s_Tuple = annmodel.SomeTuple(items)
609 jd._get_location_ptr = self._make_hook_graph(jd,
610 annhelper, jd.jitdriver.get_location, s_Tuple)
611 jd._get_loc_types = types
580612 annhelper.finish()
581613
582614 def _make_hook_graph(self, jitdriver_sd, annhelper, func,
841873 # while 1:
842874 # try:
843875 # return portal(*args)
844 # except ContinueRunningNormally, e:
845 # *args = *e.new_args
846 # except DoneWithThisFrame, e:
847 # return e.return
848 # except ExitFrameWithException, e:
849 # raise Exception, e.value
876 # except JitException, e:
877 # return handle_jitexception(e)
850878 #
851879 # def portal(*args):
852880 # while 1:
883911 rtyper = self.translator.rtyper
884912 RESULT = PORTALFUNC.RESULT
885913 result_kind = history.getkind(RESULT)
914 assert result_kind.startswith(jd.result_type)
886915 ts = self.cpu.ts
887916 state = jd.warmstate
888917 maybe_compile_and_run = jd._maybe_compile_and_run_fn
918 EnterJitAssembler = jd._EnterJitAssembler
889919
890920 def ll_portal_runner(*args):
891 start = True
892 while 1:
893 try:
894 # maybe enter from the function's start. Note that the
895 # 'start' variable is constant-folded away because it's
896 # the first statement in the loop.
897 if start:
898 maybe_compile_and_run(
899 state.increment_function_threshold, *args)
900 #
901 # then run the normal portal function, i.e. the
902 # interpreter's main loop. It might enter the jit
903 # via maybe_enter_jit(), which typically ends with
904 # handle_fail() being called, which raises on the
905 # following exceptions --- catched here, because we
906 # want to interrupt the whole interpreter loop.
907 return support.maybe_on_top_of_llinterp(rtyper,
908 portal_ptr)(*args)
909 except jitexc.ContinueRunningNormally as e:
921 try:
922 # maybe enter from the function's start.
923 maybe_compile_and_run(
924 state.increment_function_threshold, *args)
925 #
926 # then run the normal portal function, i.e. the
927 # interpreter's main loop. It might enter the jit
928 # via maybe_enter_jit(), which typically ends with
929 # handle_fail() being called, which raises on the
930 # following exceptions --- catched here, because we
931 # want to interrupt the whole interpreter loop.
932 return support.maybe_on_top_of_llinterp(rtyper,
933 portal_ptr)(*args)
934 except jitexc.JitException as e:
935 result = handle_jitexception(e)
936 if result_kind != 'void':
937 result = specialize_value(RESULT, result)
938 return result
939
940 def handle_jitexception(e):
941 # XXX there are too many exceptions all around...
942 while True:
943 if isinstance(e, EnterJitAssembler):
944 try:
945 return e.execute()
946 except jitexc.JitException as e:
947 continue
948 #
949 if isinstance(e, jitexc.ContinueRunningNormally):
910950 args = ()
911951 for ARGTYPE, attrname, count in portalfunc_ARGS:
912952 x = getattr(e, attrname)[count]
913953 x = specialize_value(ARGTYPE, x)
914954 args = args + (x,)
915 start = False
916 continue
917 except jitexc.DoneWithThisFrameVoid:
918 assert result_kind == 'void'
919 return
920 except jitexc.DoneWithThisFrameInt as e:
921 assert result_kind == 'int'
922 return specialize_value(RESULT, e.result)
923 except jitexc.DoneWithThisFrameRef as e:
924 assert result_kind == 'ref'
925 return specialize_value(RESULT, e.result)
926 except jitexc.DoneWithThisFrameFloat as e:
927 assert result_kind == 'float'
928 return specialize_value(RESULT, e.result)
929 except jitexc.ExitFrameWithExceptionRef as e:
955 try:
956 result = support.maybe_on_top_of_llinterp(rtyper,
957 portal_ptr)(*args)
958 except jitexc.JitException as e:
959 continue
960 if result_kind != 'void':
961 result = unspecialize_value(result)
962 return result
963 #
964 if result_kind == 'void':
965 if isinstance(e, jitexc.DoneWithThisFrameVoid):
966 return None
967 if result_kind == 'int':
968 if isinstance(e, jitexc.DoneWithThisFrameInt):
969 return e.result
970 if result_kind == 'ref':
971 if isinstance(e, jitexc.DoneWithThisFrameRef):
972 return e.result
973 if result_kind == 'float':
974 if isinstance(e, jitexc.DoneWithThisFrameFloat):
975 return e.result
976 #
977 if isinstance(e, jitexc.ExitFrameWithExceptionRef):
930978 value = ts.cast_to_baseclass(e.value)
931979 if not we_are_translated():
932980 raise LLException(ts.get_typeptr(value), value)
933981 else:
934982 value = cast_base_ptr_to_instance(Exception, value)
983 assert value is not None
935984 raise value
936
937 def handle_jitexception(e):
938 # XXX the bulk of this function is mostly a copy-paste from above
939 try:
940 raise e
941 except jitexc.ContinueRunningNormally as e:
942 args = ()
943 for ARGTYPE, attrname, count in portalfunc_ARGS:
944 x = getattr(e, attrname)[count]
945 x = specialize_value(ARGTYPE, x)
946 args = args + (x,)
947 result = ll_portal_runner(*args)
948 if result_kind != 'void':
949 result = unspecialize_value(result)
950 return result
951 except jitexc.DoneWithThisFrameVoid:
952 assert result_kind == 'void'
953 return
954 except jitexc.DoneWithThisFrameInt as e:
955 assert result_kind == 'int'
956 return e.result
957 except jitexc.DoneWithThisFrameRef as e:
958 assert result_kind == 'ref'
959 return e.result
960 except jitexc.DoneWithThisFrameFloat as e:
961 assert result_kind == 'float'
962 return e.result
963 except jitexc.ExitFrameWithExceptionRef as e:
964 value = ts.cast_to_baseclass(e.value)
965 if not we_are_translated():
966 raise LLException(ts.get_typeptr(value), value)
967 else:
968 value = cast_base_ptr_to_instance(Exception, value)
969 raise value
985 #
986 raise AssertionError("all cases should have been handled")
970987
971988 jd._ll_portal_runner = ll_portal_runner # for debugging
972989 jd.portal_runner_ptr = self.helper_func(jd._PTR_PORTAL_FUNCTYPE,
11 import weakref
22
33 from rpython.jit.codewriter import support, heaptracker, longlong
4 from rpython.jit.metainterp import resoperation, history
4 from rpython.jit.metainterp import resoperation, history, jitexc
55 from rpython.rlib.debug import debug_start, debug_stop, debug_print
66 from rpython.rlib.debug import have_debug_prints_for
77 from rpython.rlib.jit import PARAMETERS
8 from rpython.rlib.rjitlog import rjitlog as jl
89 from rpython.rlib.nonconst import NonConstant
910 from rpython.rlib.objectmodel import specialize, we_are_translated, r_dict
1011 from rpython.rlib.rarithmetic import intmask, r_uint
347348
348349 def make_entry_point(self):
349350 "NOT_RPYTHON"
350 if hasattr(self, 'maybe_compile_and_run'):
351 return self.maybe_compile_and_run
351 from rpython.jit.metainterp import compile
352 if hasattr(self, 'entry_point_fns'):
353 return self.entry_point_fns
352354
353355 warmrunnerdesc = self.warmrunnerdesc
354356 metainterp_sd = warmrunnerdesc.metainterp_sd
361363 confirm_enter_jit = self.confirm_enter_jit
362364 range_red_args = unrolling_iterable(
363365 range(num_green_args, num_green_args + jitdriver_sd.num_red_args))
366 name_red_args = unrolling_iterable(
367 [(i, 'arg%d' % i) for i in range(jitdriver_sd.num_red_args)])
364368 # get a new specialized copy of the method
365369 ARGS = []
366370 for kind in jitdriver_sd.red_args_types:
375379 func_execute_token = self.cpu.make_execute_token(*ARGS)
376380 cpu = self.cpu
377381 jitcounter = self.warmrunnerdesc.jitcounter
382 result_type = jitdriver_sd.result_type
378383
379384 def execute_assembler(loop_token, *args):
380385 # Call the backend to run the 'looptoken' with the given
395400 #
396401 # Handle the failure
397402 fail_descr = cpu.get_latest_descr(deadframe)
403 # First, a fast path to avoid raising and immediately catching
404 # a DoneWithThisFrame exception
405 if result_type == history.VOID:
406 if isinstance(fail_descr, compile.DoneWithThisFrameDescrVoid):
407 return None
408 if result_type == history.INT:
409 if isinstance(fail_descr, compile.DoneWithThisFrameDescrInt):
410 return fail_descr.get_result(cpu, deadframe)
411 if result_type == history.REF:
412 if isinstance(fail_descr, compile.DoneWithThisFrameDescrRef):
413 return fail_descr.get_result(cpu, deadframe)
414 if result_type == history.FLOAT:
415 if isinstance(fail_descr, compile.DoneWithThisFrameDescrFloat):
416 return fail_descr.get_result(cpu, deadframe)
417 #
418 # General case
398419 fail_descr.handle_fail(deadframe, metainterp_sd, jitdriver_sd)
399 #
400420 assert 0, "should have raised"
401421
402422 def bound_reached(hash, cell, *args):
418438
419439 def maybe_compile_and_run(increment_threshold, *args):
420440 """Entry point to the JIT. Called at the point with the
421 can_enter_jit() hint.
441 can_enter_jit() hint, and at the start of a function
442 with a different threshold.
422443 """
423444 # Look for the cell corresponding to the current greenargs.
424445 # Search for the JitCell that is of the correct subclass of
436457 # not found. increment the counter
437458 if jitcounter.tick(hash, increment_threshold):
438459 bound_reached(hash, None, *args)
439 return
440
441 # Workaround for issue #2200, maybe temporary. This is not
442 # a proper fix, but only a hack that should work well enough
443 # for PyPy's main jitdriver... See test_issue2200_recursion
444 from rpython.jit.metainterp.blackhole import workaround2200
445 if workaround2200.active:
446 workaround2200.active = False
447460 return
448461
449462 # Here, we have found 'cell'.
483496 execute_args = ()
484497 for i in range_red_args:
485498 execute_args += (unspecialize_value(args[i]), )
486 # run it! this executes until interrupted by an exception
487 execute_assembler(procedure_token, *execute_args)
488 assert 0, "should not reach this point"
499 # run it, but from outside in ll_portal_runner, not from here
500 # (this avoids RPython-level recursion with no corresponding
501 # app-level recursion, as shown by issues 2200 and 2335)
502 raise EnterJitAssembler(procedure_token, *execute_args)
503
504 class EnterJitAssembler(jitexc.JitException):
505 def __init__(self, procedure_token, *args):
506 self.procedure_token = procedure_token
507 for i, argname in name_red_args:
508 setattr(self, argname, args[i])
509 def execute(self):
510 args = ()
511 for i, argname in name_red_args:
512 args += (getattr(self, argname), )
513 return execute_assembler(self.procedure_token, *args)
489514
490515 maybe_compile_and_run._dont_inline_ = True
491 self.maybe_compile_and_run = maybe_compile_and_run
492516 self.execute_assembler = execute_assembler
493 return maybe_compile_and_run
517 self.entry_point_fns = (maybe_compile_and_run,
518 EnterJitAssembler)
519 return self.entry_point_fns
494520
495521 # ----------
496522
677703 drivername = jitdriver.name
678704 else:
679705 drivername = '<unknown jitdriver>'
680 get_location_ptr = self.jitdriver_sd._get_printable_location_ptr
681 if get_location_ptr is None:
706 # get_location returns
707 get_location_ptr = getattr(self.jitdriver_sd, '_get_location_ptr', None)
708 if get_location_ptr is not None:
709 types = self.jitdriver_sd._get_loc_types
710 unwrap_greenkey = self.make_unwrap_greenkey()
711 unrolled_types = unrolling_iterable(enumerate(types))
712 def get_location(greenkey):
713 greenargs = unwrap_greenkey(greenkey)
714 fn = support.maybe_on_top_of_llinterp(rtyper, get_location_ptr)
715 value_tuple = fn(*greenargs)
716 values = []
717 for i, (sem_type,gen_type) in unrolled_types:
718 if gen_type == "s":
719 value = getattr(value_tuple, 'item' + str(i))
720 values.append(jl.wrap(sem_type,gen_type,hlstr(value)))
721 elif gen_type == "i":
722 value = getattr(value_tuple, 'item' + str(i))
723 values.append(jl.wrap(sem_type,gen_type,intmask(value)))
724 else:
725 raise NotImplementedError
726 return values
727 self.get_location_types = list(types)
728 self.get_location = get_location
729 else:
730 self.get_location_types = None
731 self.get_location = None
732 #
733 printable_loc_ptr = self.jitdriver_sd._get_printable_location_ptr
734 if printable_loc_ptr is None:
682735 missing = '(%s: no get_printable_location)' % drivername
683736 def get_location_str(greenkey):
684737 return missing
694747 if not have_debug_prints_for("jit-"):
695748 return missing
696749 greenargs = unwrap_greenkey(greenkey)
697 fn = support.maybe_on_top_of_llinterp(rtyper, get_location_ptr)
750 fn = support.maybe_on_top_of_llinterp(rtyper, printable_loc_ptr)
698751 llres = fn(*greenargs)
699752 if not we_are_translated() and isinstance(llres, str):
700753 return llres
33
44
55 def entry_point(args):
6 """Main entry point of the stand-alone executable:
7 takes a list of strings and returns the exit code.
8 """
6 for i in range(len(argv)):
7 if argv[i] == "--jit":
8 if len(argv) == i + 1:
9 print "missing argument after --jit"
10 return 2
11 jitarg = argv[i + 1]
12 del argv[i:i+2]
13 jit.set_user_param(jitdriver, jitarg)
14 break
15
916 if len(args) < 3:
1017 print "Usage: %s filename x" % (args[0],)
1118 return 2
2532 return bytecode
2633
2734 def target(driver, args):
28 return entry_point, None
35 return entry_point
2936
3037 # ____________________________________________________________
3138
5959
6060 # ____________________________________________________________
6161
62 CONST_INT = 1
63 POP = 2
64 ADD = 3
65 RETURN = 4
66 JUMP_IF = 5
67 DUP = 6
68 SUB = 7
69 NEWSTR = 8
62 OPNAMES = []
63 HASARG = []
64
65 def define_op(name, has_arg=False):
66 globals()[name] = len(OPNAMES)
67 OPNAMES.append(name)
68 HASARG.append(has_arg)
69
70 define_op("CONST_INT", True)
71 define_op("POP")
72 define_op("ADD")
73 define_op("RETURN")
74 define_op("JUMP_IF", True)
75 define_op("DUP")
76 define_op("SUB")
77 define_op("NEWSTR", True)
78
7079
7180 # ____________________________________________________________
7281
7382 def get_printable_location(pc, bytecode):
74 return str(pc)
83 op = ord(bytecode[pc])
84 name = OPNAMES[op]
85 if HASARG[op]:
86 arg = str(ord(bytecode[pc + 1]))
87 else:
88 arg = ''
89 return "%s: %s %s" % (pc, name, arg)
7590
7691 jitdriver = JitDriver(greens=['pc', 'bytecode'],
7792 reds=['self'],
280280 large_object=8*WORD,
281281 ArenaCollectionClass=None,
282282 **kwds):
283 "NOT_RPYTHON"
283284 MovingGCBase.__init__(self, config, **kwds)
284285 assert small_request_threshold % WORD == 0
285286 self.read_from_env = read_from_env
286287 self.nursery_size = nursery_size
287
288
288289 self.small_request_threshold = small_request_threshold
289290 self.major_collection_threshold = major_collection_threshold
290291 self.growth_rate_max = growth_rate_max
643644 # Get the memory from the nursery. If there is not enough space
644645 # there, do a collect first.
645646 result = self.nursery_free
647 ll_assert(result != llmemory.NULL, "uninitialized nursery")
646648 self.nursery_free = new_free = result + totalsize
647649 if new_free > self.nursery_top:
648650 result = self.collect_and_reserve(totalsize)
702704 # Get the memory from the nursery. If there is not enough space
703705 # there, do a collect first.
704706 result = self.nursery_free
707 ll_assert(result != llmemory.NULL, "uninitialized nursery")
705708 self.nursery_free = new_free = result + totalsize
706709 if new_free > self.nursery_top:
707710 result = self.collect_and_reserve(totalsize)
11381141 Implemented a bit obscurely by checking an unrelated flag
11391142 that can never be set on a young object -- except if tid == -42.
11401143 """
1141 assert self.is_in_nursery(obj)
1144 ll_assert(self.is_in_nursery(obj),
1145 "Can't forward an object outside the nursery.")
11421146 tid = self.header(obj).tid
11431147 result = (tid & GCFLAG_FINALIZATION_ORDERING != 0)
11441148 if result:
14621466 objhdr.tid |= GCFLAG_CARDS_SET
14631467
14641468 remember_young_pointer_from_array2._dont_inline_ = True
1465 assert self.card_page_indices > 0
1469 ll_assert(self.card_page_indices > 0,
1470 "non-positive card_page_indices")
14661471 self.remember_young_pointer_from_array2 = (
14671472 remember_young_pointer_from_array2)
14681473
15121517 return True
15131518 # ^^^ a fast path of write-barrier
15141519 #
1515 if source_hdr.tid & GCFLAG_HAS_CARDS != 0:
1520 if (self.card_page_indices > 0 and # check constant-folded
1521 source_hdr.tid & GCFLAG_HAS_CARDS != 0):
15161522 #
15171523 if source_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
15181524 # The source object may have random young pointers.
15471553
15481554 def manually_copy_card_bits(self, source_addr, dest_addr, length):
15491555 # manually copy the individual card marks from source to dest
1550 assert self.card_page_indices > 0
1556 ll_assert(self.card_page_indices > 0,
1557 "non-positive card_page_indices")
15511558 bytes = self.card_marking_bytes_for_length(length)
15521559 #
15531560 anybyte = 0
16241631 # This is because these are precisely the old objects that
16251632 # have been modified and need rescanning.
16261633 self.old_objects_pointing_to_young.foreach(
1627 self._add_to_more_objects_to_trace, None)
1634 self._add_to_more_objects_to_trace_if_black, None)
1635 # Old black objects pointing to pinned objects that may no
1636 # longer be pinned now: careful,
1637 # _visit_old_objects_pointing_to_pinned() will move the
1638 # previously-pinned object, and that creates a white object.
1639 # We prevent the "black->white" situation by forcing the
1640 # old black object to become gray again.
1641 self.old_objects_pointing_to_pinned.foreach(
1642 self._add_to_more_objects_to_trace_if_black, None)
16281643 #
16291644 # First, find the roots that point to young objects. All nursery
16301645 # objects found are copied out of the nursery, and the occasional
17201735 nursery_barriers = self.AddressDeque()
17211736 prev = self.nursery
17221737 self.surviving_pinned_objects.sort()
1723 assert self.pinned_objects_in_nursery == \
1724 self.surviving_pinned_objects.length()
1738 ll_assert(
1739 self.pinned_objects_in_nursery == \
1740 self.surviving_pinned_objects.length(),
1741 "pinned_objects_in_nursery != surviving_pinned_objects.length()")
17251742 while self.surviving_pinned_objects.non_empty():
17261743 #
17271744 cur = self.surviving_pinned_objects.pop()
1728 assert cur >= prev
1745 ll_assert(
1746 cur >= prev, "pinned objects encountered in backwards order")
17291747 #
17301748 # clear the arena between the last pinned object (or arena start)
17311749 # and the pinned object
17831801 debug_stop("gc-minor")
17841802
17851803 def _reset_flag_old_objects_pointing_to_pinned(self, obj, ignore):
1786 assert self.header(obj).tid & GCFLAG_PINNED_OBJECT_PARENT_KNOWN
1804 ll_assert(self.header(obj).tid & GCFLAG_PINNED_OBJECT_PARENT_KNOWN != 0,
1805 "!GCFLAG_PINNED_OBJECT_PARENT_KNOWN, but requested to reset.")
17871806 self.header(obj).tid &= ~GCFLAG_PINNED_OBJECT_PARENT_KNOWN
17881807
17891808 def _visit_old_objects_pointing_to_pinned(self, obj, ignore):
21322151 self.header(obj).tid &= ~GCFLAG_VISITED
21332152 self.more_objects_to_trace.append(obj)
21342153
2154 def _add_to_more_objects_to_trace_if_black(self, obj, ignored):
2155 if self.header(obj).tid & GCFLAG_VISITED:
2156 self._add_to_more_objects_to_trace(obj, ignored)
2157
21352158 def minor_and_major_collection(self):
21362159 # First, finish the current major gc, if there is one in progress.
21372160 # This is a no-op if the gc_state is already STATE_SCANNING.
22442267 # For now, the same applies to rawrefcount'ed objects.
22452268 if (not self.objects_to_trace.non_empty() and
22462269 not self.more_objects_to_trace.non_empty()):
2270 #
2271 # First, 'prebuilt_root_objects' might have grown since
2272 # we scanned it in collect_roots() (rare case). Rescan.
2273 self.collect_nonstack_roots()
2274 self.visit_all_objects()
22472275 #
22482276 if self.rrc_enabled:
22492277 self.rrc_major_collection_trace()
24252453 return nobjects
24262454
24272455
2428 def collect_roots(self):
2429 # Collect all roots. Starts from all the objects
2430 # from 'prebuilt_root_objects'.
2456 def collect_nonstack_roots(self):
2457 # Non-stack roots: first, the objects from 'prebuilt_root_objects'
24312458 self.prebuilt_root_objects.foreach(self._collect_obj, None)
24322459 #
2433 # Add the roots from the other sources.
2460 # Add the roots from static prebuilt non-gc structures
24342461 self.root_walker.walk_roots(
2435 IncrementalMiniMarkGC._collect_ref_stk, # stack roots
2436 IncrementalMiniMarkGC._collect_ref_stk, # static in prebuilt non-gc structures
2462 None,
2463 IncrementalMiniMarkGC._collect_ref_stk,
24372464 None) # we don't need the static in all prebuilt gc objects
24382465 #
24392466 # If we are in an inner collection caused by a call to a finalizer,
24402467 # the 'run_finalizers' objects also need to be kept alive.
24412468 self.enum_pending_finalizers(self._collect_obj, None)
2469
2470 def collect_roots(self):
2471 # Collect all roots. Starts from the non-stack roots.
2472 self.collect_nonstack_roots()
2473 #
2474 # Add the stack roots.
2475 self.root_walker.walk_roots(
2476 IncrementalMiniMarkGC._collect_ref_stk, # stack roots
2477 None,
2478 None)
24422479
24432480 def enumerate_all_roots(self, callback, arg):
24442481 self.prebuilt_root_objects.foreach(callback, arg)
394394 if arena.nfreepages == arena.totalpages:
395395 #
396396 # The whole arena is empty. Free it.
397 llarena.arena_reset(arena.base, self.arena_size, 4)
397398 llarena.arena_free(arena.base)
398399 lltype.free(arena, flavor='raw', track_allocation=False)
399400 #
553553 assert res # we optimized it
554554 assert hdr_dst.tid & minimark.GCFLAG_TRACK_YOUNG_PTRS == 0 # and we copied the flag
555555 #
556 self.gc.card_page_indices = 128 # force > 0
556557 hdr_src.tid |= minimark.GCFLAG_TRACK_YOUNG_PTRS
557558 hdr_dst.tid |= minimark.GCFLAG_TRACK_YOUNG_PTRS
558559 hdr_src.tid |= minimark.GCFLAG_HAS_CARDS
00 import py
11 from rpython.rtyper.lltypesystem import lltype, llmemory, llarena
22 from rpython.memory.gc.incminimark import IncrementalMiniMarkGC, WORD
3 from rpython.memory.gc.incminimark import GCFLAG_VISITED
34 from test_direct import BaseDirectGCTest
45
56 T = lltype.GcForwardReference()
980981 self.gc.major_collection_step() # should not crash reading 'ptr1'!
981982
982983 del self.gc.TEST_VISIT_SINGLE_STEP
984
985
986 def test_pin_bug2(self):
987 #
988 # * we have an old object A that points to a pinned object B
989 #
990 # * we unpin B
991 #
992 # * the next minor_collection() is done in STATE_MARKING==1
993 # when the object A is already black
994 #
995 # * _minor_collection() => _visit_old_objects_pointing_to_pinned()
996 # which will move the now-unpinned B out of the nursery, to B'
997 #
998 # At that point we need to take care of colors, otherwise we
999 # get a black object (A) pointing to a white object (B'),
1000 # which must never occur.
1001 #
1002 ptrA = self.malloc(T)
1003 ptrA.someInt = 42
1004 adrA = llmemory.cast_ptr_to_adr(ptrA)
1005 res = self.gc.pin(adrA)
1006 assert res
1007
1008 ptrC = self.malloc(S)
1009 self.stackroots.append(ptrC)
1010
1011 ptrB = self.malloc(S)
1012 ptrB.data = ptrA
1013 self.stackroots.append(ptrB)
1014
1015 self.gc.collect()
1016 ptrB = self.stackroots[-1] # now old and outside the nursery
1017 ptrC = self.stackroots[-2] # another random old object, traced later
1018 adrB = llmemory.cast_ptr_to_adr(ptrB)
1019
1020 self.gc.minor_collection()
1021 assert self.gc.gc_state == self.STATE_SCANNING
1022 self.gc.major_collection_step()
1023 assert self.gc.gc_state == self.STATE_MARKING
1024 assert not (self.gc.header(adrB).tid & GCFLAG_VISITED) # not black yet
1025
1026 self.gc.TEST_VISIT_SINGLE_STEP = True
1027 self.gc.major_collection_step()
1028 assert self.gc.gc_state == self.STATE_MARKING
1029 assert self.gc.header(adrB).tid & GCFLAG_VISITED # now black
1030 # but ptrC is not traced yet, which is why we're still in STATE_MARKING
1031 assert self.gc.old_objects_pointing_to_pinned.tolist() == [adrB]
1032
1033 self.gc.unpin(adrA)
1034
1035 self.gc.DEBUG = 2
1036 self.gc.minor_collection()
1010 def __init__(self, HDR):
1111 """NOT_RPYTHON"""
1212 self.HDR = HDR
13 self.obj2header = weakref.WeakKeyDictionary()
13 #
14 # The following used to be a weakref.WeakKeyDictionary(), but
15 # the problem is that if you have a gcobj which has already a
16 # weakref cached on it and the hash already cached in that
17 # weakref, and later the hash of the gcobj changes (because it
18 # is ll2ctypes-ified), then that gcobj cannot be used as a key
19 # in a WeakKeyDictionary any more: from this point on,
20 # 'ref(gcobj)' and 'ref(gcobj, callback)' return two objects
21 # with different hashes... and so e.g. the sequence of
22 # operations 'obj2header[x]=y; assert x in obj2header' fails.
23 #
24 # Instead, just use a regular dictionary and hope that not too
25 # many objects would be reclaimed in a given GCHeaderBuilder
26 # instance.
27 self.obj2header = {}
1428 self.size_gc_header = llmemory.GCHeaderOffset(self)
1529
1630 def header_of_object(self, gcptr):
00 from rpython.memory.gctransform.transform import GCTransformer, mallocHelpers
11 from rpython.memory.gctransform.support import (get_rtti,
2 _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor)
2 _static_deallocator_body_for_type, LLTransformerOp, ll_call_destructor,
3 ll_report_finalizer_error)
34 from rpython.rtyper.lltypesystem import lltype, llmemory
45 from rpython.flowspace.model import Constant
56 from rpython.rtyper.lltypesystem.lloperation import llop
5758 self.mixlevelannotator.finish() # for now
5859 self.mixlevelannotator.backend_optimize()
5960
61 self.finalizer_triggers = []
62 self.finalizer_queue_indexes = {} # {fq: index}
63
6064 def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size):
6165 # XXX same behavior for zero=True: in theory that's wrong
6266 if TYPE._is_atomic():
113117
114118 self.finalizer_funcptrs[TYPE] = fptr
115119 return fptr
120
121 def get_finalizer_queue_index(self, hop):
122 fq_tag = hop.spaceop.args[0].value
123 assert 'FinalizerQueue TAG' in fq_tag.expr
124 fq = fq_tag.default
125 try:
126 index = self.finalizer_queue_indexes[fq]
127 except KeyError:
128 index = len(self.finalizer_queue_indexes)
129 assert index == len(self.finalizer_triggers)
130 #
131 def ll_finalizer_trigger():
132 try:
133 fq.finalizer_trigger()
134 except Exception as e:
135 ll_report_finalizer_error(e)
136 ll_trigger = self.annotate_finalizer(ll_finalizer_trigger, [],
137 lltype.Void)
138 self.finalizer_triggers.append(ll_trigger)
139 self.finalizer_queue_indexes[fq] = index
140 return index
141
142 def gct_gc_fq_register(self, hop):
143 index = self.get_finalizer_queue_index(hop)
144 c_index = rmodel.inputconst(lltype.Signed, index)
145 v_ptr = hop.spaceop.args[1]
146 hop.genop("boehm_fq_register", [c_index, v_ptr])
147
148 def gct_gc_fq_next_dead(self, hop):
149 index = self.get_finalizer_queue_index(hop)
150 c_index = rmodel.inputconst(lltype.Signed, index)
151 hop.genop("boehm_fq_next_dead", [c_index],
152 resultvar = hop.spaceop.result)
116153
117154 def gct_weakref_create(self, hop):
118155 v_instance, = hop.spaceop.args
486486 #hstrerror.argtypes = [c_int]
487487 #hstrerror.restype = c_char_p
488488
489 socket = external('socket', [rffi.INT, rffi.INT, rffi.INT], socketfd_type)
489 socket = external('socket', [rffi.INT, rffi.INT, rffi.INT], socketfd_type,
490 save_err=SAVE_ERR)
491
490492
491493 if WIN32:
492494 socketclosename = 'closesocket'
5858 def get_raw_address(self):
5959 raise ValueError("no raw buffer")
6060
61 def getformat(self):
62 return 'B'
63
64 def getitemsize(self):
65 return 1
66
67 def getndim(self):
68 return 1
69
70 def getshape(self):
71 return [self.getlength()]
72
73 def getstrides(self):
74 return [1]
6175
6276 class StringBuffer(Buffer):
6377 __slots__ = ['value']
147147 ('elements', FFI_TYPE_PP)])
148148
149149 ffi_cif = rffi_platform.Struct('ffi_cif', [])
150 ffi_closure = rffi_platform.Struct('ffi_closure', [])
150 ffi_closure = rffi_platform.Struct('ffi_closure',
151 [('user_data', rffi.VOIDP)])
151152
152153 def add_simple_type(type_name):
153154 for name in ['size', 'alignment', 'type']:
603603 get_printable_location=None, confirm_enter_jit=None,
604604 can_never_inline=None, should_unroll_one_iteration=None,
605605 name='jitdriver', check_untranslated=True, vectorize=False,
606 get_unique_id=None, is_recursive=False):
607 "NOT_RPYTHON"
606 get_unique_id=None, is_recursive=False, get_location=None):
607 """ NOT_RPYTHON
608 get_location:
609 The return value is designed to provide enough information to express the
610 state of an interpreter when invoking jit_merge_point.
611 For a bytecode interperter such as PyPy this includes, filename, line number,
612 function name, and more information. However, it should also be able to express
613 the same state for an interpreter that evaluates an AST.
614 return paremter:
615 0 -> filename. An absolute path specifying the file the interpreter invoked.
616 If the input source is no file it should start with the
617 prefix: "string://<name>"
618 1 -> line number. The line number in filename. This should at least point to
619 the enclosing name. It can however point to the specific
620 source line of the instruction executed by the interpreter.
621 2 -> enclosing name. E.g. the function name.
622 3 -> index. 64 bit number indicating the execution progress. It can either be
623 an offset to byte code, or an index to the node in an AST
624 4 -> operation name. a name further describing the current program counter.
625 this can be either a byte code name or the name of an AST node
626 """
608627 if greens is not None:
609628 self.greens = greens
610629 self.name = name
638657 assert get_jitcell_at is None, "get_jitcell_at no longer used"
639658 assert set_jitcell_at is None, "set_jitcell_at no longer used"
640659 self.get_printable_location = get_printable_location
660 self.get_location = get_location
641661 if get_unique_id is None:
642662 get_unique_id = lambda *args: 0
643663 self.get_unique_id = get_unique_id
878898 driver = self.instance.im_self
879899 h = self.annotate_hook
880900 h(driver.get_printable_location, driver.greens, **kwds_s)
901 h(driver.get_location, driver.greens, **kwds_s)
881902
882903 def annotate_hook(self, func, variables, args_s=[], **kwds_s):
883904 if func is None:
3838
3939 def specialize_call(self, hop):
4040 hop.exception_cannot_occur()
41 retval = Constant(hop.r_result.convert_const(hop.args_v[0].value))
42 retval.concretetype = hop.r_result.lowleveltype
43 return retval
44
41 return hop.inputarg(hop.r_result, arg=0)
280280 return lltype.Signed
281281
282282 malloc_zero_filled = CDefinedIntSymbolic('MALLOC_ZERO_FILLED', default=0)
283 _translated_to_c = CDefinedIntSymbolic('1 /*_translated_to_c*/', default=0)
284
285 def we_are_translated_to_c():
286 return we_are_translated() and _translated_to_c
283287
284288 # ____________________________________________________________
285289
1313 integer operation did overflow
1414 ovfcheck_float_to_int
1515 convert to an integer or raise OverflowError
16 ovfcheck_float_to_longlong
17 convert to a longlong or raise OverflowError
1618 r_longlong
1719 like r_int but double word size
1820 r_ulonglong
181183 # int(float(i)) != i because of rounding issues.
182184 # These are the minimum and maximum float value that can
183185 # successfully be casted to an int.
186
187 # The following values are not quite +/-sys.maxint.
188 # Note the "<= x <" here, as opposed to "< x <" above.
189 # This is justified by test_typed in translator/c/test.
190 def ovfcheck_float_to_longlong(x):
191 from rpython.rlib.rfloat import isnan
192 if isnan(x):
193 raise OverflowError
194 if -9223372036854776832.0 <= x < 9223372036854775296.0:
195 return r_longlong(x)
196 raise OverflowError
197
184198 if sys.maxint == 2147483647:
185199 def ovfcheck_float_to_int(x):
186200 from rpython.rlib.rfloat import isnan
190204 return int(x)
191205 raise OverflowError
192206 else:
193 # The following values are not quite +/-sys.maxint.
194 # Note the "<= x <" here, as opposed to "< x <" above.
195 # This is justified by test_typed in translator/c/test.
196207 def ovfcheck_float_to_int(x):
197 from rpython.rlib.rfloat import isnan
198 if isnan(x):
199 raise OverflowError
200 if -9223372036854776832.0 <= x < 9223372036854775296.0:
201 return int(x)
202 raise OverflowError
208 return int(ovfcheck_float_to_longlong(x))
203209
204210 def compute_restype(self_type, other_type):
205211 if self_type is other_type:
648654 from rpython.rtyper.lltypesystem import lltype
649655 from rpython.rtyper.lltypesystem.lloperation import llop
650656 return llop.int_force_ge_zero(lltype.Signed, n)
657
658 def int_c_div(x, y):
659 """Return the result of the C-style 'x / y'. This differs from the
660 Python-style division if (x < 0 xor y < 0). The JIT implements it
661 with a Python-style division followed by correction code. This
662 is not that bad, because the JIT removes the correction code if
663 x and y are both nonnegative, and if y is any nonnegative constant
664 then the division turns into a rshift or a mul.
665 """
666 from rpython.rtyper.lltypesystem import lltype
667 from rpython.rtyper.lltypesystem.lloperation import llop
668 return llop.int_floordiv(lltype.Signed, x, y)
669
670 def int_c_mod(x, y):
671 """Return the result of the C-style 'x % y'. This differs from the
672 Python-style division if (x < 0 xor y < 0).
673 """
674 from rpython.rtyper.lltypesystem import lltype
675 from rpython.rtyper.lltypesystem.lloperation import llop
676 return llop.int_mod(lltype.Signed, x, y)
651677
652678 @objectmodel.specialize.ll()
653679 def byteswap(arg):
5555 raise MemoryError
5656 end_ptr = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw')
5757 try:
58 ll_input = rffi.str2charp(input)
58 # note: don't use the class scoped_view_charp here, it
59 # break some tests because this function is used by the GC
60 ll_input, flag = rffi.get_nonmovingbuffer_final_null(input)
5961 try:
6062 result = dg_strtod(ll_input, end_ptr)
6163
6264 endpos = (rffi.cast(lltype.Signed, end_ptr[0]) -
6365 rffi.cast(lltype.Signed, ll_input))
64
65 if endpos == 0 or endpos < len(input):
66 raise ValueError("invalid input at position %d" % (endpos,))
67
68 return result
6966 finally:
70 rffi.free_charp(ll_input)
67 rffi.free_nonmovingbuffer(input, ll_input, flag)
7168 finally:
7269 lltype.free(end_ptr, flavor='raw')
70
71 if endpos == 0 or endpos < len(input):
72 raise ValueError("invalid input at position %d" % (endpos,))
73
74 return result
7375
7476 lower_special_strings = ['inf', '+inf', '-inf', 'nan']
7577 upper_special_strings = ['INF', '+INF', '-INF', 'NAN']
2525
2626 if _MAC_OS:
2727 pre_include_bits = ['#define MACOSX']
28 else:
28 else:
2929 pre_include_bits = []
3030
3131 if _FREEBSD or _NETBSD or _WIN32:
144144 else:
145145 return lltype.nullptr(rffi.VOIDP.TO)
146146
147 def _dlopen_default_mode():
148 """ The default dlopen mode if it hasn't been changed by the user.
149 """
150 mode = RTLD_NOW
151 if RTLD_LOCAL is not None:
152 mode |= RTLD_LOCAL
153 return mode
154
147155 def dlopen(name, mode=-1):
148156 """ Wrapper around C-level dlopen
149157 """
150158 if mode == -1:
151 if RTLD_LOCAL is not None:
152 mode = RTLD_LOCAL
153 else:
154 mode = 0
155 if (mode & (RTLD_LAZY | RTLD_NOW)) == 0:
159 mode = _dlopen_default_mode()
160 elif (mode & (RTLD_LAZY | RTLD_NOW)) == 0:
156161 mode |= RTLD_NOW
157162 res = c_dlopen(name, rffi.cast(rffi.INT, mode))
158163 if not res:
192197 DLLHANDLE = rwin32.HMODULE
193198 RTLD_GLOBAL = None
194199
200 def _dlopen_default_mode():
201 """ The default dlopen mode if it hasn't been changed by the user.
202 """
203 return 0
204
195205 def dlopen(name, mode=-1):
196206 # mode is unused on windows, but a consistant signature
197207 res = rwin32.LoadLibrary(name)
12671267 ptr = lltype.direct_arrayitems(array)
12681268 # ptr is a Ptr(FixedSizeArray(Char, 1)). Cast it to a rffi.CCHARP
12691269 return rffi.cast(rffi.CCHARP, ptr)
1270
1271 @jit.dont_look_inside
1272 @no_collect
1273 @specialize.ll()
1274 def ll_write_final_null_char(s):
1275 """'s' is a low-level STR; writes a terminating NULL character after
1276 the other characters in 's'. Warning, this only works because of
1277 the 'extra_item_after_alloc' hack inside the definition of STR.
1278 """
1279 from rpython.rtyper.lltypesystem import rffi
1280 PSTR = lltype.typeOf(s)
1281 assert has_final_null_char(PSTR) == 1
1282 n = llmemory.offsetof(PSTR.TO, 'chars')
1283 n += llmemory.itemoffsetof(PSTR.TO.chars, 0)
1284 n = llmemory.raw_malloc_usage(n)
1285 n += len(s.chars)
1286 # no GC operation from here!
1287 ptr = rffi.cast(rffi.CCHARP, s)
1288 ptr[n] = '\x00'
1289
1290 @specialize.memo()
1291 def has_final_null_char(PSTR):
1292 return PSTR.TO.chars._hints.get('extra_item_after_alloc', 0)
0 import py
1 import sys
2 import weakref
3 import struct
4 import os
5 import platform
6 from rpython.rlib import jit
7 from rpython.tool.udir import udir
8 from rpython.tool.version import rpythonroot
9 from rpython.rtyper.lltypesystem import lltype, rffi
10 from rpython.translator.tool.cbuild import ExternalCompilationInfo
11 from rpython.jit.metainterp import resoperation as resoperations
12 from rpython.jit.metainterp.resoperation import rop
13 from rpython.jit.metainterp.history import ConstInt, ConstFloat
14 from rpython.rlib.objectmodel import we_are_translated
15 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
16 from rpython.rlib.objectmodel import compute_unique_id, always_inline
17 from rpython.rlib.objectmodel import we_are_translated, specialize
18 from rpython.rlib.unroll import unrolling_iterable
19 from rpython.rlib.jit_hooks import register_helper
20 from rpython.annotator import model as annmodel
21
22
23 ROOT = py.path.local(rpythonroot).join('rpython', 'rlib', 'rjitlog')
24 SRC = ROOT.join('src')
25
26 _libs = []
27 if sys.platform.startswith('linux'):
28 _libs = ['dl']
29 eci_kwds = dict(
30 include_dirs = [SRC],
31 includes = ['rjitlog.h'],
32 libraries = _libs,
33 separate_module_files = [SRC.join('rjitlog.c')],
34 post_include_bits=['#define RPYTHON_JITLOG\n'],
35 )
36 eci = ExternalCompilationInfo(**eci_kwds)
37
38 # jit log functions
39 jitlog_init = rffi.llexternal("jitlog_init", [rffi.INT],
40 rffi.CCHARP, compilation_info=eci)
41 jitlog_try_init_using_env = rffi.llexternal("jitlog_try_init_using_env",
42 [], lltype.Void, compilation_info=eci)
43 jitlog_write_marked = rffi.llexternal("jitlog_write_marked",
44 [rffi.CCHARP, rffi.INT],
45 lltype.Void, compilation_info=eci,
46 releasegil=False)
47 jitlog_enabled = rffi.llexternal("jitlog_enabled", [], rffi.INT,
48 compilation_info=eci,
49 releasegil=False)
50 jitlog_teardown = rffi.llexternal("jitlog_teardown", [], lltype.Void,
51 compilation_info=eci)
52
53 class JitlogError(Exception):
54 def __init__(self, msg):
55 self.msg = msg
56 def __str__(self):
57 return self.msg
58
59 @register_helper(None)
60 def stats_flush_trace_counts(warmrunnerdesc):
61 if not we_are_translated():
62 return # first param is None untranslated
63 warmrunnerdesc.metainterp_sd.cpu.assembler.flush_trace_counters()
64
65 @jit.dont_look_inside
66 def enable_jitlog(fileno):
67 # initialize the jit log
68 p_error = jitlog_init(fileno)
69 if p_error:
70 raise JitlogError(rffi.charp2str(p_error))
71 blob = assemble_header()
72 jitlog_write_marked(MARK_JITLOG_HEADER + blob, len(blob) + 1)
73
74 def disable_jitlog():
75 stats_flush_trace_counts(None)
76 jitlog_teardown()
77
78
79 def commonprefix(a,b):
80 "Given a list of pathnames, returns the longest common leading component"
81 assert a is not None
82 assert b is not None
83 la = len(a)
84 lb = len(b)
85 c = min(la,lb)
86 if c == 0:
87 return ""
88 for i in range(c):
89 if a[i] != b[i]:
90 return a[:i] # partly matching
91 return a # full match
92
93 @always_inline
94 def encode_str(string):
95 val = len(string)
96 return ''.join([chr((val >> 0) & 0xff),
97 chr((val >> 8) & 0xff),
98 chr((val >> 16) & 0xff),
99 chr((val >> 24) & 0xff),
100 string])
101
102 @always_inline
103 def encode_le_16bit(val):
104 return chr((val >> 0) & 0xff) + chr((val >> 8) & 0xff)
105
106 @always_inline
107 def encode_le_32bit(val):
108 return ''.join([chr((val >> 0) & 0xff),
109 chr((val >> 8) & 0xff),
110 chr((val >> 16) & 0xff),
111 chr((val >> 24) & 0xff)])
112
113 @always_inline
114 def encode_le_64bit(val):
115 return ''.join([chr((val >> 0) & 0xff),
116 chr((val >> 8) & 0xff),
117 chr((val >> 16) & 0xff),
118 chr((val >> 24) & 0xff),
119 chr((val >> 32) & 0xff),
120 chr((val >> 40) & 0xff),
121 chr((val >> 48) & 0xff),
122 chr((val >> 56)& 0xff)])
123
124 @always_inline
125 def encode_le_addr(val):
126 if IS_32_BIT:
127 return encode_le_32bit(val)
128 else:
129 return encode_le_64bit(val)
130
131 def encode_type(type, value):
132 if type == "s":
133 return encode_str(value)
134 elif type == "q":
135 return encode_le_64bit(value)
136 elif type == "i":
137 return encode_le_32bit(value)
138 elif type == "h":
139 return encode_le_16bit(value)
140 else:
141 raise NotImplementedError
142
143 # more variable parameters
144 MP_STR = (0x0, "s")
145 MP_INT = (0x0, "i")
146
147 # concrete parameters
148 MP_FILENAME = (0x1, "s")
149 MP_LINENO = (0x2, "i")
150 MP_INDEX = (0x4, "i")
151 MP_SCOPE = (0x8, "s")
152 MP_OPCODE = (0x10, "s")
153
154 class WrappedValue(object):
155 def encode(self, log, i, compressor):
156 raise NotImplementedError
157
158 class StringValue(WrappedValue):
159 def __init__(self, sem_type, gen_type, value):
160 self.value = value
161
162 def encode(self, log, i, compressor):
163 str_value = self.value
164 last_prefix = compressor.get_last_written(i)
165 cp = compressor.compress(i, str_value)
166 if cp is None:
167 return b'\xff' + encode_str(str_value)
168
169 else:
170 cp_len = len(cp)
171 if cp == last_prefix:
172 # we have the same prefix
173 pass
174 else:
175 compressor.write(log, i, cp)
176 if len(str_value) == len(cp):
177 return b'\xef'
178 return b'\x00' + encode_str(str_value[len(cp):])
179
180 class IntValue(WrappedValue):
181 def __init__(self, sem_type, gen_type, value):
182 self.value = value
183
184 def encode(self, log, i, prefixes):
185 return b'\x00' + encode_le_64bit(self.value)
186
187 # note that a ...
188 # "semantic_type" is an integer denoting which meaning does a type at a merge point have
189 # there are very common ones that are predefined. E.g. MP_FILENAME
190 # "generic_type" is one of the primitive types supported (string,int)
191
192 @specialize.argtype(2)
193 def wrap(sem_type, gen_type, value):
194 if isinstance(value, int):
195 return IntValue(sem_type, gen_type, value)
196 elif isinstance(value, str):
197 return StringValue(sem_type, gen_type, value)
198 raise NotImplementedError
199
200 def returns(*args):
201 """ Decorate your get_location function to specify the types.
202 Use MP_* constant as parameters. An example impl for get_location
203 would return the following:
204
205 @returns(MP_FILENAME, MP_LINENO)
206 def get_location(...):
207 return ("a.py", 0)
208 """
209 def decor(method):
210 method._loc_types = args
211 return method
212 return decor
213
214 JITLOG_VERSION = 3
215 JITLOG_VERSION_16BIT_LE = struct.pack("<H", JITLOG_VERSION)
216
217 marks = [
218 ('INPUT_ARGS',),
219 ('RESOP_META',),
220 ('RESOP',),
221 ('RESOP_DESCR',),
222 ('ASM_ADDR',),
223 ('ASM',),
224
225 # which type of trace is logged after this
226 # the trace as it is recorded by the tracer
227 ('TRACE',),
228 # the trace that has passed the optimizer
229 ('TRACE_OPT',),
230 # the trace assembled to machine code (after rewritten)
231 ('TRACE_ASM',),
232
233 # the machine code was patched (e.g. guard)
234 ('STITCH_BRIDGE',),
235
236 ('START_TRACE',),
237
238 ('JITLOG_COUNTER',),
239 ('INIT_MERGE_POINT',),
240
241 ('JITLOG_HEADER',),
242 ('MERGE_POINT',),
243 ('COMMON_PREFIX',),
244 ('ABORT_TRACE',),
245 ('SOURCE_CODE',),
246 ('REDIRECT_ASSEMBLER',),
247 ]
248
249 start = 0x11
250 for mark, in marks:
251 globals()['MARK_' + mark] = chr(start)
252 start += 1
253
254 if __name__ == "__main__":
255 print("# generated constants from rpython/rlib/jitlog.py")
256 print 'MARK_JITLOG_START = struct.pack("b", "%s")' % hex(0x10)
257 for mark, in marks:
258 nmr = globals()['MARK_' + mark]
259 h = hex(ord(nmr))
260 print '%s = struct.pack("b", "%s")' % ('MARK_' + mark, h)
261 print 'MARK_JITLOG_END = struct.pack("b", "%s")' % hex(start)
262 for key,value in locals().items():
263 if key.startswith("MP_"):
264 print '%s = (%s,"%s")' % (key, hex(value[0]), value[1])
265 print 'SEM_TYPE_NAMES = {'
266 for key,value in locals().items():
267 if key.startswith("MP_") and value[0] != 0:
268 print ' %s: "%s",' % (hex(value[0]), key[3:].lower())
269 print '}'
270
271 MP_STR = (0x0, "s")
272 MP_INT = (0x0, "i")
273
274 # concrete parameters
275 MP_FILENAME = (0x1, "s")
276 MP_LINENO = (0x2, "i")
277 MP_INDEX = (0x4, "i")
278 MP_SCOPE = (0x8, "s")
279 MP_OPCODE = (0x10, "s")
280
281 del marks
282 del start
283
284 IS_32_BIT = sys.maxint == 2**31-1
285
286 MACHINE_NAME = platform.machine()
287
288 def assemble_header():
289 version = JITLOG_VERSION_16BIT_LE
290 count = len(resoperations.opname)
291 is_32bit = chr(0x1)
292 if not IS_32_BIT:
293 is_32bit = chr(0x0)
294 content = [version, is_32bit, encode_str(MACHINE_NAME),
295 MARK_RESOP_META, encode_le_16bit(count)]
296 for opnum, opname in resoperations.opname.items():
297 content.append(encode_le_16bit(opnum))
298 content.append(encode_str(opname.lower()))
299 return ''.join(content)
300
301 def _log_jit_counter(struct):
302 if not jitlog_enabled():
303 return
304 # addr is either a number (trace_id), or the address
305 # of the descriptor. for entries it is a the trace_id,
306 # for any label/bridge entry the addr is the address
307 list = [MARK_JITLOG_COUNTER, encode_le_addr(struct.number),
308 struct.type, encode_le_64bit(struct.i)]
309 content = ''.join(list)
310 jitlog_write_marked(content, len(content))
311
312 def redirect_assembler(oldtoken, newtoken, target):
313 if not jitlog_enabled():
314 return
315 descr_nmr = compute_unique_id(oldtoken)
316 new_descr_nmr = compute_unique_id(newtoken)
317 list = [MARK_REDIRECT_ASSEMBLER, encode_le_addr(descr_nmr),
318 encode_le_addr(new_descr_nmr), encode_le_addr(target)]
319 content = ''.join(list)
320 jitlog_write_marked(content, len(content))
321
322
323 class JitLogger(object):
324 def __init__(self, cpu=None):
325 self.cpu = cpu
326 self.memo = {}
327 self.trace_id = 0
328 self.metainterp_sd = None
329 # legacy
330 self.logger_ops = None
331 self.logger_noopt = None
332
333 def setup_once(self):
334 if jitlog_enabled():
335 return
336 jitlog_try_init_using_env()
337 if not jitlog_enabled():
338 return
339 blob = assemble_header()
340 jitlog_write_marked(MARK_JITLOG_HEADER + blob, len(blob) + 1)
341
342 def finish(self):
343 jitlog_teardown()
344
345 def start_new_trace(self, metainterp_sd, faildescr=None, entry_bridge=False, jd_name=""):
346 # even if the logger is not enabled, increment the trace id
347 self.trace_id += 1
348 if not jitlog_enabled():
349 return
350 self.metainterp_sd = metainterp_sd
351 content = [encode_le_addr(self.trace_id)]
352 if faildescr:
353 content.append(encode_str('bridge'))
354 descrnmr = compute_unique_id(faildescr)
355 content.append(encode_le_addr(descrnmr))
356 else:
357 content.append(encode_str('loop'))
358 content.append(encode_le_addr(int(entry_bridge)))
359 content.append(encode_str(jd_name))
360 self._write_marked(MARK_START_TRACE, ''.join(content))
361
362 def trace_aborted(self):
363 if not jitlog_enabled():
364 return
365 self._write_marked(MARK_ABORT_TRACE, encode_le_addr(self.trace_id))
366
367 def _write_marked(self, mark, line):
368 if not we_are_translated():
369 assert jitlog_enabled()
370 jitlog_write_marked(mark + line, len(line) + 1)
371
372 def log_jit_counter(self, struct):
373 _log_jit_counter(struct)
374
375 def log_trace(self, tag, metainterp_sd, mc, memo=None):
376 if not jitlog_enabled():
377 return EMPTY_TRACE_LOG
378 assert self.metainterp_sd is not None
379 if memo is None:
380 memo = {}
381 return LogTrace(tag, memo, self.metainterp_sd, mc, self)
382
383 def log_patch_guard(self, descr_number, addr):
384 if not jitlog_enabled():
385 return
386 le_descr_number = encode_le_addr(descr_number)
387 le_addr = encode_le_addr(addr)
388 lst = [le_descr_number, le_addr]
389 self._write_marked(MARK_STITCH_BRIDGE, ''.join(lst))
390
391 class BaseLogTrace(object):
392 def write_trace(self, trace):
393 return None
394
395 def write(self, args, ops, ops_offset={}):
396 return None
397
398 EMPTY_TRACE_LOG = BaseLogTrace()
399
400 class PrefixCompressor(object):
401 def __init__(self, count):
402 self.prefixes = [None] * count
403 self.written_prefixes = [None] * count
404
405 def get_last(self, index):
406 return self.prefixes[index]
407
408 def get_last_written(self, index):
409 return self.written_prefixes[index]
410
411 def compress(self, index, string):
412 assert string is not None
413 last = self.get_last(index)
414 if last is None:
415 self.prefixes[index] = string
416 return None
417 cp = commonprefix(last, string)
418 if len(cp) <= 1: # prevent very small common prefixes (like "/")
419 self.prefixes[index] = string
420 return None
421 return cp
422
423
424 def write(self, log, index, prefix):
425 # we have a new prefix
426 log._write_marked(MARK_COMMON_PREFIX, chr(index) \
427 + encode_str(prefix))
428 self.written_prefixes[index] = prefix
429
430 def encode_merge_point(log, compressor, values):
431 line = []
432 unrolled = unrolling_iterable(values)
433 i = 0
434 for value in unrolled:
435 line.append(value.encode(log,i,compressor))
436 i += 1
437 return ''.join(line)
438
439
440 class LogTrace(BaseLogTrace):
441 def __init__(self, tag, memo, metainterp_sd, mc, logger):
442 self.memo = memo
443 self.metainterp_sd = metainterp_sd
444 self.ts = None
445 if self.metainterp_sd is not None:
446 self.ts = metainterp_sd.cpu.ts
447 self.tag = tag
448 self.mc = mc
449 self.logger = logger
450 self.common_prefix = None
451
452 def write_trace(self, trace):
453 ops = []
454 i = trace.get_iter()
455 while not i.done():
456 ops.append(i.next())
457 self.write(i.inputargs, ops)
458
459 def write(self, args, ops, ops_offset={}):
460 log = self.logger
461 tid = self.logger.trace_id
462 log._write_marked(self.tag, encode_le_addr(tid))
463
464 # input args
465 str_args = [self.var_to_str(arg) for arg in args]
466 string = encode_str(','.join(str_args))
467 log._write_marked(MARK_INPUT_ARGS, string)
468
469 # assembler address (to not duplicate it in write_code_dump)
470 if self.mc is not None:
471 absaddr = self.mc.absolute_addr()
472 rel = self.mc.get_relative_pos()
473 # packs <start addr> <end addr> as two unsigend longs
474 le_addr1 = encode_le_addr(absaddr)
475 le_addr2 = encode_le_addr(absaddr + rel)
476 log._write_marked(MARK_ASM_ADDR, le_addr1 + le_addr2)
477 for i,op in enumerate(ops):
478 if rop.DEBUG_MERGE_POINT == op.getopnum():
479 self.encode_debug_info(op)
480 continue
481 mark, line = self.encode_op(op)
482 log._write_marked(mark, line)
483 self.write_core_dump(ops, i, op, ops_offset)
484
485 self.memo = {}
486
487 def encode_once(self):
488 pass
489
490 def encode_debug_info(self, op):
491 # the idea is to write the debug merge point as it's own well known
492 # tag. Compression for common prefixes is implemented:
493
494 log = self.logger
495 jd_sd = self.metainterp_sd.jitdrivers_sd[op.getarg(0).getint()]
496 if not jd_sd.warmstate.get_location:
497 return
498 values = jd_sd.warmstate.get_location(op.getarglist()[3:])
499 if values is None:
500 # indicates that this function is not provided to the jit driver
501 return
502 types = jd_sd.warmstate.get_location_types
503
504 if self.common_prefix is None:
505 # first time visiting a merge point
506 # setup the common prefix
507 self.common_prefix = PrefixCompressor(len(types))
508 encoded_types = []
509 for i, (semantic_type, generic_type) in enumerate(types):
510 encoded_types.append(chr(semantic_type))
511 encoded_types.append(generic_type)
512 count = encode_le_16bit(len(types))
513 log._write_marked(MARK_INIT_MERGE_POINT, count + ''.join(encoded_types))
514
515 # the types have already been written
516 encoded = encode_merge_point(log, self.common_prefix, values)
517 log._write_marked(MARK_MERGE_POINT, encoded)
518
519 def encode_op(self, op):
520 """ an operation is written as follows:
521 <marker> <opid (16 bit)> \
522 <len (32 bit)> \
523 <res_val>,<arg_0>,...,<arg_n> \
524 <descr>
525 <failarg_0>,...<failarg_n>
526 The marker indicates if the last argument is
527 a descr or a normal argument.
528 """
529 str_args = [self.var_to_str(arg) for arg in op.getarglist()]
530 descr = op.getdescr()
531 le_opnum = encode_le_16bit(op.getopnum())
532 str_res = self.var_to_str(op)
533 line = ','.join([str_res] + str_args)
534 failargslist = op.getfailargs()
535 failargs = ''
536 if failargslist:
537 failargs = ','.join([self.var_to_str(farg) for farg in failargslist])
538 #
539 if descr:
540 descr_str = descr.repr_of_descr()
541 line = line + ',' + descr_str
542 string = encode_str(line)
543 descr_number = compute_unique_id(descr)
544 le_descr_number = encode_le_addr(descr_number)
545 return MARK_RESOP_DESCR, le_opnum + string + le_descr_number + encode_str(failargs)
546 else:
547 string = encode_str(line)
548 return MARK_RESOP, le_opnum + string + encode_str(failargs)
549
550
551 def write_core_dump(self, operations, i, op, ops_offset):
552 if self.mc is None:
553 return
554
555 op2 = None
556 j = i+1
557 # find the next op that is in the offset hash
558 while j < len(operations):
559 op2 = operations[j]
560 if op in ops_offset:
561 break
562 j += 1
563
564 # this op has no known offset in the machine code (it might be
565 # a debug operation)
566 if op not in ops_offset:
567 return
568 # there is no well defined boundary for the end of the
569 # next op in the assembler
570 if op2 is not None and op2 not in ops_offset:
571 return
572 dump = []
573
574 start_offset = ops_offset[op]
575 assert start_offset >= 0
576 # end offset is either the last pos in the assembler
577 # or the offset of op2
578 if op2 is None:
579 end_offset = self.mc.get_relative_pos()
580 else:
581 end_offset = ops_offset[op2]
582
583 count = end_offset - start_offset
584 dump = self.copy_core_dump(self.mc.absolute_addr(), start_offset, count)
585 offset = encode_le_16bit(start_offset)
586 edump = encode_str(dump)
587 self.logger._write_marked(MARK_ASM, offset + edump)
588
589 def copy_core_dump(self, addr, offset=0, count=-1):
590 dump = []
591 src = rffi.cast(rffi.CCHARP, addr)
592 end = self.mc.get_relative_pos()
593 if count != -1:
594 end = offset + count
595 for p in range(offset, end):
596 dump.append(src[p])
597 return ''.join(dump)
598
599 def var_to_str(self, arg):
600 if arg is None:
601 return '-'
602 try:
603 mv = self.memo[arg]
604 except KeyError:
605 mv = len(self.memo)
606 self.memo[arg] = mv
607 if isinstance(arg, ConstInt):
608 if self.metainterp_sd and int_could_be_an_address(arg.value):
609 addr = arg.getaddr()
610 name = self.metainterp_sd.get_name_from_address(addr)
611 if name:
612 return 'ConstClass(' + name + ')'
613 return str(arg.value)
614 elif self.ts is not None and isinstance(arg, self.ts.ConstRef):
615 if arg.value:
616 return 'ConstPtr(ptr' + str(mv) + ')'
617 return 'ConstPtr(null)'
618 if isinstance(arg, ConstFloat):
619 return str(arg.getfloat())
620 elif arg is None:
621 return 'None'
622 elif arg.is_vector():
623 return 'v' + str(mv)
624 elif arg.type == 'i':
625 return 'i' + str(mv)
626 elif arg.type == 'r':
627 return 'p' + str(mv)
628 elif arg.type == 'f':
629 return 'f' + str(mv)
630 else:
631 return '?'
632
633 def int_could_be_an_address(x):
634 if we_are_translated():
635 x = rffi.cast(lltype.Signed, x) # force it
636 return not (-32768 <= x <= 32767)
637 else:
638 return isinstance(x, llmemory.AddressAsInt)
0 #define _GNU_SOURCE 1
1
2 #ifdef RPYTHON_LL2CTYPES
3 /* only for testing: ll2ctypes sets RPY_EXTERN from the command-line */
4 #ifndef RPY_EXTERN
5 #define RPY_EXTERN RPY_EXPORTED
6 #endif
7 #ifdef _WIN32
8 #define RPY_EXPORTED __declspec(dllexport)
9 #else
10 #define RPY_EXPORTED extern __attribute__((visibility("default")))
11 #endif
12 #else
13 #include "common_header.h"
14 #include "structdef.h"
15 #include "src/threadlocal.h"
16 #include "rjitlog.h"
17 #endif
18
19 #include <string.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #ifndef _WIN32
26 #include <unistd.h>
27 #endif
28 #include <errno.h>
29
30 static int jitlog_fd = -1;
31 static int jitlog_ready = 0;
32
33 RPY_EXTERN
34 int jitlog_enabled()
35 {
36 return jitlog_ready;
37 }
38
39 RPY_EXTERN
40 void jitlog_try_init_using_env(void) {
41 char * filename;
42 if (jitlog_ready) { return; }
43
44 filename = getenv("JITLOG");
45
46 if (filename && filename[0]) {
47 // mode is 775
48 #ifdef _WIN32
49 int mode = _S_IWRITE | _S_IREAD | _S_IEXEC;
50 #else
51 mode_t mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
52 #endif
53 jitlog_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
54 if (jitlog_fd == -1) {
55 fprintf(stderr, "could not open '%s': ", filename);
56 perror(NULL);
57 exit(-1);
58 }
59 } else {
60 jitlog_ready = 0;
61 return;
62 }
63 #ifndef _WIN32
64 unsetenv("JITLOG");
65 #else
66 putenv("JITLOG=");
67 #endif
68 jitlog_ready = 1;
69 }
70
71 RPY_EXTERN
72 char *jitlog_init(int fd)
73 {
74 jitlog_fd = fd;
75 jitlog_ready = 1;
76 return NULL;
77 }
78
79 RPY_EXTERN
80 void jitlog_teardown()
81 {
82 jitlog_ready = 0;
83 if (jitlog_fd == -1) {
84 return;
85 }
86 // close the jitlog file descriptor
87 close(jitlog_fd);
88 jitlog_fd = -1;
89 }
90
91 RPY_EXTERN
92 void jitlog_write_marked(char * text, int length)
93 {
94 if (!jitlog_ready) { return; }
95
96 write(jitlog_fd, text, length);
97 }
0
1 RPY_EXTERN char * jitlog_init(int);
2 RPY_EXTERN void jitlog_try_init_using_env(void);
3 RPY_EXTERN int jitlog_enabled();
4 RPY_EXTERN void jitlog_write_marked(char*, int);
5 RPY_EXTERN void jitlog_teardown();
0 import py
1 import sys
2 from rpython.jit.tool.oparser import pure_parse
3 from rpython.jit.metainterp.optimizeopt.util import equaloplists
4 from rpython.jit.metainterp.resoperation import ResOperation, rop
5 from rpython.jit.backend.model import AbstractCPU
6 from rpython.jit.metainterp.history import ConstInt, ConstPtr
7 from rpython.rlib.rjitlog import rjitlog as jl
8 from rpython.jit.metainterp.history import AbstractDescr
9 from rpython.rlib.objectmodel import compute_unique_id
10
11 class FakeCallAssemblerLoopToken(AbstractDescr):
12 def __init__(self, target):
13 self._ll_function_addr = target
14
15 def repr_of_descr(self):
16 return 'looptoken'
17
18 class FakeLog(object):
19 def __init__(self):
20 self.values = []
21
22 def _write_marked(self, id, text):
23 self.values.append(id + text)
24
25 def _get_location(greenkey_list):
26 assert len(greenkey_list) == 0
27 return '/home/pypy/jit.py', 0, 'enclosed', 99, 'DEL'
28
29 class TestLogger(object):
30
31 def make_metainterp_sd(self):
32 class FakeJitDriver(object):
33 class warmstate(object):
34 get_location_types = [jl.MP_FILENAME,jl.MP_INT,jl.MP_SCOPE, jl.MP_INT, jl.MP_OPCODE]
35 @staticmethod
36 def get_location(greenkey_list):
37 return [jl.wrap(jl.MP_FILENAME[0],'s','/home/pypy/jit.py'),
38 jl.wrap(jl.MP_INT[0], 'i', 0),
39 jl.wrap(jl.MP_SCOPE[0], 's', 'enclosed'),
40 jl.wrap(jl.MP_INT[0], 'i', 99),
41 jl.wrap(jl.MP_OPCODE[0], 's', 'DEL')
42 ]
43
44
45 class FakeMetaInterpSd:
46 cpu = AbstractCPU()
47 cpu.ts = None
48 jitdrivers_sd = [FakeJitDriver()]
49 def get_name_from_address(self, addr):
50 return 'Name'
51 return FakeMetaInterpSd()
52
53 def test_debug_merge_point(self, tmpdir):
54 logger = jl.JitLogger()
55 file = tmpdir.join('binary_file')
56 file.ensure()
57 fd = file.open('wb')
58 jl.jitlog_init(fd.fileno())
59 logger.start_new_trace(self.make_metainterp_sd(), jd_name='jdname')
60 log_trace = logger.log_trace(jl.MARK_TRACE, None, None)
61 op = ResOperation(rop.DEBUG_MERGE_POINT, [ConstInt(0), ConstInt(0), ConstInt(0)])
62 log_trace.write([], [op])
63 #the next line will close 'fd', instead of logger.finish()
64 fd.close()
65 binary = file.read()
66 is_32bit = chr(sys.maxint == 2**31-1)
67 assert binary == (jl.MARK_START_TRACE) + jl.encode_le_addr(1) + \
68 jl.encode_str('loop') + jl.encode_le_addr(0) + \
69 jl.encode_str('jdname') + \
70 (jl.MARK_TRACE) + jl.encode_le_addr(1) + \
71 (jl.MARK_INPUT_ARGS) + jl.encode_str('') + \
72 (jl.MARK_INIT_MERGE_POINT) + b'\x05\x00\x01s\x00i\x08s\x00i\x10s' + \
73 (jl.MARK_MERGE_POINT) + \
74 b'\xff' + jl.encode_str('/home/pypy/jit.py') + \
75 b'\x00' + jl.encode_le_64bit(0) + \
76 b'\xff' + jl.encode_str('enclosed') + \
77 b'\x00' + jl.encode_le_64bit(99) + \
78 b'\xff' + jl.encode_str('DEL')
79
80 def test_common_prefix(self):
81 fakelog = FakeLog()
82 compressor = jl.PrefixCompressor(1)
83 # nothing to compress yet!
84 result = jl.encode_merge_point(fakelog, compressor, [jl.StringValue(0x0,'s','hello')])
85 assert result == b"\xff\x05\x00\x00\x00hello"
86 assert fakelog.values == []
87 #
88 result = jl.encode_merge_point(fakelog, compressor, [jl.StringValue(0x0,'s','hello')])
89 assert result == b"\xef"
90 assert fakelog.values == [(jl.MARK_COMMON_PREFIX) + "\x00\x05\x00\x00\x00hello"]
91 #
92 fakelog.values = []
93 result = jl.encode_merge_point(fakelog, compressor, [jl.StringValue(0x0,'s','heiter')])
94 assert result == b"\x00\x04\x00\x00\x00iter"
95 assert fakelog.values == [(jl.MARK_COMMON_PREFIX) + "\x00\x02\x00\x00\x00he"]
96 #
97 fakelog.values = []
98 result = jl.encode_merge_point(fakelog, compressor, [jl.StringValue(0x0,'s','heute')])
99 assert result == b"\x00\x03\x00\x00\x00ute"
100 assert fakelog.values == []
101 #
102 fakelog.values = []
103 result = jl.encode_merge_point(fakelog, compressor, [jl.StringValue(0x0,'s','welt')])
104 assert result == b"\xff\x04\x00\x00\x00welt"
105 assert fakelog.values == []
106 #
107 fakelog.values = []
108 result = jl.encode_merge_point(fakelog, compressor, [jl.StringValue(0x0,'s','welle')])
109 assert result == b"\x00\x02\x00\x00\x00le"
110 assert fakelog.values == [(jl.MARK_COMMON_PREFIX) + "\x00\x03\x00\x00\x00wel"]
111
112 def test_common_prefix_func(self):
113 assert jl.commonprefix("","") == ""
114 assert jl.commonprefix("/hello/world","/path/to") == "/"
115 assert jl.commonprefix("pyramid","python") == "py"
116 assert jl.commonprefix("0"*100,"0"*100) == "0"*100
117 with py.test.raises(AssertionError):
118 jl.commonprefix(None,None)
119
120 def test_redirect_assembler(self, tmpdir):
121 looptoken = FakeCallAssemblerLoopToken(0x0)
122 newlooptoken = FakeCallAssemblerLoopToken(0x1234)
123 #
124 logger = jl.JitLogger()
125 file = tmpdir.join('binary_file')
126 file.ensure()
127 fd = file.open('wb')
128 jl.jitlog_init(fd.fileno())
129 logger.start_new_trace(self.make_metainterp_sd(), jd_name='jdname')
130 log_trace = logger.log_trace(jl.MARK_TRACE, None, None)
131 op = ResOperation(rop.CALL_ASSEMBLER_I, [], descr=looptoken)
132 log_trace.write([], [op])
133 jl.redirect_assembler(looptoken, newlooptoken, 0x1234)
134 #the next line will close 'fd', instead of logger.finish()
135 fd.close()
136 binary = file.read()
137 opnum = jl.encode_le_16bit(rop.CALL_ASSEMBLER_I)
138 id_looptoken = compute_unique_id(looptoken)
139 new_id_looptoken = compute_unique_id(newlooptoken)
140 end = jl.MARK_RESOP_DESCR + opnum + jl.encode_str('i0,looptoken') + \
141 jl.encode_le_addr(id_looptoken) + jl.encode_str('') + \
142 jl.MARK_REDIRECT_ASSEMBLER + \
143 jl.encode_le_addr(id_looptoken) + \
144 jl.encode_le_addr(new_id_looptoken) + \
145 jl.encode_le_addr(newlooptoken._ll_function_addr)
146 assert binary.endswith(end)
147
6969 CConfig.MREMAP_MAYMOVE = (
7070 rffi_platform.DefinedConstantInteger("MREMAP_MAYMOVE"))
7171 CConfig.has_mremap = rffi_platform.Has('mremap(NULL, 0, 0, 0)')
72 # a dirty hack, this is probably a macro
72 CConfig.has_madvise = rffi_platform.Has('madvise(NULL, 0, 0)')
73 # ^^ both are a dirty hack, this is probably a macro
74
75 CConfig.MADV_DONTNEED = (
76 rffi_platform.DefinedConstantInteger('MADV_DONTNEED'))
77 CConfig.MADV_FREE = (
78 rffi_platform.DefinedConstantInteger('MADV_FREE'))
7379
7480 elif _MS_WINDOWS:
7581 constant_names = ['PAGE_READONLY', 'PAGE_READWRITE', 'PAGE_WRITECOPY',
7682 'FILE_MAP_READ', 'FILE_MAP_WRITE', 'FILE_MAP_COPY',
7783 'DUPLICATE_SAME_ACCESS', 'MEM_COMMIT', 'MEM_RESERVE',
78 'MEM_RELEASE', 'PAGE_EXECUTE_READWRITE', 'PAGE_NOACCESS']
84 'MEM_RELEASE', 'PAGE_EXECUTE_READWRITE', 'PAGE_NOACCESS',
85 'MEM_RESET']
7986 for name in constant_names:
8087 setattr(CConfig, name, rffi_platform.ConstantInteger(name))
8188
143150
144151 if _POSIX:
145152 has_mremap = cConfig['has_mremap']
153 has_madvise = cConfig['has_madvise']
146154 c_mmap, c_mmap_safe = external('mmap', [PTR, size_t, rffi.INT, rffi.INT,
147155 rffi.INT, off_t], PTR, macro=True,
148156 save_err_on_unsafe=rffi.RFFI_SAVE_ERRNO)
153161 if has_mremap:
154162 c_mremap, _ = external('mremap',
155163 [PTR, size_t, size_t, rffi.ULONG], PTR)
164 if has_madvise:
165 _, c_madvise_safe = external('madvise', [PTR, size_t, rffi.INT],
166 rffi.INT, _nowrapper=True)
156167
157168 # this one is always safe
158169 _pagesize = rffi_platform.getintegerfunctionresult('getpagesize',
221232 VirtualAlloc, VirtualAlloc_safe = winexternal('VirtualAlloc',
222233 [rffi.VOIDP, rffi.SIZE_T, DWORD, DWORD],
223234 rffi.VOIDP)
235 _, _VirtualAlloc_safe_no_wrapper = winexternal('VirtualAlloc',
236 [rffi.VOIDP, rffi.SIZE_T, DWORD, DWORD],
237 rffi.VOIDP, _nowrapper=True)
224238 _, _VirtualProtect_safe = winexternal('VirtualProtect',
225239 [rffi.VOIDP, rffi.SIZE_T, DWORD, LPDWORD],
226240 BOOL)
753767 free = c_free_safe
754768 else:
755769 free = c_munmap_safe
770
771 if sys.platform.startswith('linux'):
772 assert has_madvise
773 assert MADV_DONTNEED is not None
774 if MADV_FREE is None:
775 MADV_FREE = 8 # from the kernel sources of Linux >= 4.5
776 class CanUseMadvFree:
777 ok = -1
778 can_use_madv_free = CanUseMadvFree()
779 def madvise_free(addr, map_size):
780 # We don't know if we are running on a recent enough kernel
781 # that supports MADV_FREE. Check that at runtime: if the
782 # first call to madvise(MADV_FREE) fails, we assume it's
783 # because of EINVAL and we fall back to MADV_DONTNEED.
784 if can_use_madv_free.ok != 0:
785 res = c_madvise_safe(rffi.cast(PTR, addr),
786 rffi.cast(size_t, map_size),
787 rffi.cast(rffi.INT, MADV_FREE))
788 if can_use_madv_free.ok == -1:
789 can_use_madv_free.ok = (rffi.cast(lltype.Signed, res) == 0)
790 if can_use_madv_free.ok == 0:
791 c_madvise_safe(rffi.cast(PTR, addr),
792 rffi.cast(size_t, map_size),
793 rffi.cast(rffi.INT, MADV_DONTNEED))
794 elif has_madvise and not (MADV_FREE is MADV_DONTNEED is None):
795 use_flag = MADV_FREE if MADV_FREE is not None else MADV_DONTNEED
796 def madvise_free(addr, map_size):
797 c_madvise_safe(rffi.cast(PTR, addr),
798 rffi.cast(size_t, map_size),
799 rffi.cast(rffi.INT, use_flag))
800 else:
801 def madvise_free(addr, map_size):
802 "No madvise() on this platform"
756803
757804 elif _MS_WINDOWS:
758805 def mmap(fileno, length, tagname="", access=_ACCESS_DEFAULT, offset=0):
906953 def free(ptr, map_size):
907954 VirtualFree_safe(ptr, 0, MEM_RELEASE)
908955
909 # register_external here?
956 def madvise_free(addr, map_size):
957 r = _VirtualAlloc_safe_no_wrapper(
958 rffi.cast(rffi.VOIDP, addr),
959 rffi.cast(rffi.SIZE_T, map_size),
960 rffi.cast(DWORD, MEM_RESET),
961 rffi.cast(DWORD, PAGE_READWRITE))
962 #from rpython.rlib import debug
963 #debug.debug_print("madvise_free:", r)
585585 HASH_MALLOC_SIZE = EVP_MD_SIZE + EVP_MD_CTX_SIZE \
586586 + rffi.sizeof(EVP_MD) * 2 + 208
587587
588 OBJ_NAME_CALLBACK = lltype.Ptr(lltype.FuncType(
589 [OBJ_NAME, rffi.VOIDP], lltype.Void))
590 OBJ_NAME_do_all = external(
591 'OBJ_NAME_do_all', [rffi.INT, OBJ_NAME_CALLBACK, rffi.VOIDP], lltype.Void)
592
593588 def init_ssl():
594589 libssl_SSL_load_error_strings()
595590 libssl_SSL_library_init()
9595 return 0;
9696 }
9797 ''',]
98 post_include_bits=['RPY_EXTERN int _PyVerify_fd(int);']
9899 else:
99100 separate_module_sources = []
101 post_include_bits = []
100102 includes=['errno.h','stdio.h']
101103 errno_eci = ExternalCompilationInfo(
102104 includes=includes,
103105 separate_module_sources=separate_module_sources,
106 post_include_bits=post_include_bits,
104107 )
105108
106109 # Direct getters/setters, don't use directly!
219222 pass
220223
221224 if _WIN32:
222 includes = ['io.h', 'sys/utime.h', 'sys/types.h']
225 includes = ['io.h', 'sys/utime.h', 'sys/types.h', 'process.h']
223226 libraries = []
224227 else:
225228 if sys.platform.startswith(('darwin', 'netbsd', 'openbsd')):
246249 OFF_T_SIZE = rffi_platform.SizeOf('off_t')
247250
248251 HAVE_UTIMES = rffi_platform.Has('utimes')
252 HAVE_D_TYPE = rffi_platform.Has('DT_UNKNOWN')
249253 UTIMBUF = rffi_platform.Struct('struct %sutimbuf' % UNDERSCORE_ON_WIN32,
250254 [('actime', rffi.INT),
251255 ('modtime', rffi.INT)])
252256 if not _WIN32:
257 UID_T = rffi_platform.SimpleType('uid_t', rffi.UINT)
258 GID_T = rffi_platform.SimpleType('gid_t', rffi.UINT)
253259 CLOCK_T = rffi_platform.SimpleType('clock_t', rffi.INT)
254260
255261 TMS = rffi_platform.Struct(
597603 class CConfig:
598604 _compilation_info_ = eci
599605 DIRENT = rffi_platform.Struct('struct dirent',
600 [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1))])
606 [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1))]
607 + [('d_type', rffi.INT)] if HAVE_D_TYPE else [])
608 if HAVE_D_TYPE:
609 DT_UNKNOWN = rffi_platform.ConstantInteger('DT_UNKNOWN')
610 DT_REG = rffi_platform.ConstantInteger('DT_REG')
611 DT_DIR = rffi_platform.ConstantInteger('DT_DIR')
612 DT_LNK = rffi_platform.ConstantInteger('DT_LNK')
601613
602614 DIRP = rffi.COpaquePtr('DIR')
603 config = rffi_platform.configure(CConfig)
604 DIRENT = config['DIRENT']
615 dirent_config = rffi_platform.configure(CConfig)
616 DIRENT = dirent_config['DIRENT']
605617 DIRENTP = lltype.Ptr(DIRENT)
606618 c_opendir = external('opendir',
607619 [rffi.CCHARP], DIRP, save_err=rffi.RFFI_SAVE_ERRNO)
608620 c_fdopendir = external('fdopendir',
609621 [rffi.INT], DIRP, save_err=rffi.RFFI_SAVE_ERRNO)
622 c_rewinddir = external('rewinddir',
623 [DIRP], lltype.Void, releasegil=False)
610624 # XXX macro=True is hack to make sure we get the correct kind of
611625 # dirent struct (which depends on defines)
612626 c_readdir = external('readdir', [DIRP], DIRENTP,
613627 macro=True, save_err=rffi.RFFI_FULL_ERRNO_ZERO)
614 c_closedir = external('closedir', [DIRP], rffi.INT)
615
616 def _listdir(dirp):
628 c_closedir = external('closedir', [DIRP], rffi.INT, releasegil=False)
629 c_dirfd = external('dirfd', [DIRP], rffi.INT, releasegil=False)
630 else:
631 dirent_config = {}
632
633 def _listdir(dirp, rewind=False):
617634 result = []
618635 while True:
619636 direntp = c_readdir(dirp)
624641 name = rffi.charp2str(namep)
625642 if name != '.' and name != '..':
626643 result.append(name)
644 if rewind:
645 c_rewinddir(dirp)
627646 c_closedir(dirp)
628647 if error:
629648 raise OSError(error, "readdir failed")
634653 Like listdir(), except that the directory is specified as an open
635654 file descriptor.
636655
637 Note: fdlistdir() closes the file descriptor.
656 Note: fdlistdir() closes the file descriptor. To emulate the
657 Python 3.x 'os.opendir(dirfd)', you must first duplicate the
658 file descriptor.
638659 """
639660 dirp = c_fdopendir(dirfd)
640661 if not dirp:
641 raise OSError(get_saved_errno(), "opendir failed")
642 return _listdir(dirp)
662 error = get_saved_errno()
663 c_close(dirfd)
664 raise OSError(error, "opendir failed")
665 return _listdir(dirp, rewind=True)
643666
644667 @replace_os_function('listdir')
645668 @specialize.argtype(0)
703726 c_execve = external('execve',
704727 [rffi.CCHARP, rffi.CCHARPP, rffi.CCHARPP], rffi.INT,
705728 save_err=rffi.RFFI_SAVE_ERRNO)
706 c_spawnv = external('spawnv',
729 c_spawnv = external(UNDERSCORE_ON_WIN32 + 'spawnv',
707730 [rffi.INT, rffi.CCHARP, rffi.CCHARPP], rffi.INT,
708731 save_err=rffi.RFFI_SAVE_ERRNO)
709 c_spawnve = external('spawnve',
732 c_spawnve = external(UNDERSCORE_ON_WIN32 + 'spawnve',
710733 [rffi.INT, rffi.CCHARP, rffi.CCHARPP, rffi.CCHARPP],
711734 rffi.INT,
712735 save_err=rffi.RFFI_SAVE_ERRNO)
14491472 def setpgid(pid, gid):
14501473 handle_posix_error('setpgid', c_setpgid(pid, gid))
14511474
1452 PID_GROUPS_T = rffi.CArrayPtr(rffi.PID_T)
1453 c_getgroups = external('getgroups', [rffi.INT, PID_GROUPS_T], rffi.INT,
1454 save_err=rffi.RFFI_SAVE_ERRNO)
1455 c_setgroups = external('setgroups', [rffi.SIZE_T, PID_GROUPS_T], rffi.INT,
1456 save_err=rffi.RFFI_SAVE_ERRNO)
1457 c_initgroups = external('initgroups', [rffi.CCHARP, rffi.PID_T], rffi.INT,
1458 save_err=rffi.RFFI_SAVE_ERRNO)
1475 if not _WIN32:
1476 GID_GROUPS_T = rffi.CArrayPtr(GID_T)
1477 c_getgroups = external('getgroups', [rffi.INT, GID_GROUPS_T], rffi.INT,
1478 save_err=rffi.RFFI_SAVE_ERRNO)
1479 c_setgroups = external('setgroups', [rffi.SIZE_T, GID_GROUPS_T], rffi.INT,
1480 save_err=rffi.RFFI_SAVE_ERRNO)
1481 c_initgroups = external('initgroups', [rffi.CCHARP, GID_T], rffi.INT,
1482 save_err=rffi.RFFI_SAVE_ERRNO)
14591483
14601484 @replace_os_function('getgroups')
14611485 def getgroups():
14621486 n = handle_posix_error('getgroups',
1463 c_getgroups(0, lltype.nullptr(PID_GROUPS_T.TO)))
1464 groups = lltype.malloc(PID_GROUPS_T.TO, n, flavor='raw')
1487 c_getgroups(0, lltype.nullptr(GID_GROUPS_T.TO)))
1488 groups = lltype.malloc(GID_GROUPS_T.TO, n, flavor='raw')
14651489 try:
14661490 n = handle_posix_error('getgroups', c_getgroups(n, groups))
1467 return [widen(groups[i]) for i in range(n)]
1491 return [widen_gid(groups[i]) for i in range(n)]
14681492 finally:
14691493 lltype.free(groups, flavor='raw')
14701494
14711495 @replace_os_function('setgroups')
14721496 def setgroups(gids):
14731497 n = len(gids)
1474 groups = lltype.malloc(PID_GROUPS_T.TO, n, flavor='raw')
1498 groups = lltype.malloc(GID_GROUPS_T.TO, n, flavor='raw')
14751499 try:
14761500 for i in range(n):
1477 groups[i] = rffi.cast(rffi.PID_T, gids[i])
1501 groups[i] = rffi.cast(GID_T, gids[i])
14781502 handle_posix_error('setgroups', c_setgroups(n, groups))
14791503 finally:
14801504 lltype.free(groups, flavor='raw')
15251549
15261550 #___________________________________________________________________
15271551
1528 c_getuid = external('getuid', [], rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
1529 c_geteuid = external('geteuid', [], rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
1530 c_setuid = external('setuid', [rffi.INT], rffi.INT,
1531 save_err=rffi.RFFI_SAVE_ERRNO)
1532 c_seteuid = external('seteuid', [rffi.INT], rffi.INT,
1533 save_err=rffi.RFFI_SAVE_ERRNO)
1534 c_getgid = external('getgid', [], rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
1535 c_getegid = external('getegid', [], rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO)
1536 c_setgid = external('setgid', [rffi.INT], rffi.INT,
1537 save_err=rffi.RFFI_SAVE_ERRNO)
1538 c_setegid = external('setegid', [rffi.INT], rffi.INT,
1539 save_err=rffi.RFFI_SAVE_ERRNO)
1540
1541 @replace_os_function('getuid')
1542 def getuid():
1543 return handle_posix_error('getuid', c_getuid())
1544
1545 @replace_os_function('geteuid')
1546 def geteuid():
1547 return handle_posix_error('geteuid', c_geteuid())
1548
1549 @replace_os_function('setuid')
1550 def setuid(uid):
1551 handle_posix_error('setuid', c_setuid(uid))
1552
1553 @replace_os_function('seteuid')
1554 def seteuid(uid):
1555 handle_posix_error('seteuid', c_seteuid(uid))
1556
1557 @replace_os_function('getgid')
1558 def getgid():
1559 return handle_posix_error('getgid', c_getgid())
1560
1561 @replace_os_function('getegid')
1562 def getegid():
1563 return handle_posix_error('getegid', c_getegid())
1564
1565 @replace_os_function('setgid')
1566 def setgid(gid):
1567 handle_posix_error('setgid', c_setgid(gid))
1568
1569 @replace_os_function('setegid')
1570 def setegid(gid):
1571 handle_posix_error('setegid', c_setegid(gid))
1572
1573 c_setreuid = external('setreuid', [rffi.INT, rffi.INT], rffi.INT,
1574 save_err=rffi.RFFI_SAVE_ERRNO)
1575 c_setregid = external('setregid', [rffi.INT, rffi.INT], rffi.INT,
1576 save_err=rffi.RFFI_SAVE_ERRNO)
1577
1578 @replace_os_function('setreuid')
1579 def setreuid(ruid, euid):
1580 handle_posix_error('setreuid', c_setreuid(ruid, euid))
1581
1582 @replace_os_function('setregid')
1583 def setregid(rgid, egid):
1584 handle_posix_error('setregid', c_setregid(rgid, egid))
1585
1586 c_getresuid = external('getresuid', [rffi.INTP] * 3, rffi.INT,
1587 save_err=rffi.RFFI_SAVE_ERRNO)
1588 c_getresgid = external('getresgid', [rffi.INTP] * 3, rffi.INT,
1589 save_err=rffi.RFFI_SAVE_ERRNO)
1590 c_setresuid = external('setresuid', [rffi.INT] * 3, rffi.INT,
1591 save_err=rffi.RFFI_SAVE_ERRNO)
1592 c_setresgid = external('setresgid', [rffi.INT] * 3, rffi.INT,
1593 save_err=rffi.RFFI_SAVE_ERRNO)
1594
1595 @replace_os_function('getresuid')
1596 def getresuid():
1597 out = lltype.malloc(rffi.INTP.TO, 3, flavor='raw')
1598 try:
1599 handle_posix_error('getresuid',
1600 c_getresuid(rffi.ptradd(out, 0),
1601 rffi.ptradd(out, 1),
1602 rffi.ptradd(out, 2)))
1603 return (widen(out[0]), widen(out[1]), widen(out[2]))
1604 finally:
1605 lltype.free(out, flavor='raw')
1606
1607 @replace_os_function('getresgid')
1608 def getresgid():
1609 out = lltype.malloc(rffi.INTP.TO, 3, flavor='raw')
1610 try:
1611 handle_posix_error('getresgid',
1612 c_getresgid(rffi.ptradd(out, 0),
1613 rffi.ptradd(out, 1),
1614 rffi.ptradd(out, 2)))
1615 return (widen(out[0]), widen(out[1]), widen(out[2]))
1616 finally:
1617 lltype.free(out, flavor='raw')
1618
1619 @replace_os_function('setresuid')
1620 def setresuid(ruid, euid, suid):
1621 handle_posix_error('setresuid', c_setresuid(ruid, euid, suid))
1622
1623 @replace_os_function('setresgid')
1624 def setresgid(rgid, egid, sgid):
1625 handle_posix_error('setresgid', c_setresgid(rgid, egid, sgid))
1552 if not _WIN32:
1553 c_getuid = external('getuid', [], UID_T)
1554 c_geteuid = external('geteuid', [], UID_T)
1555 c_setuid = external('setuid', [UID_T], rffi.INT,
1556 save_err=rffi.RFFI_SAVE_ERRNO)
1557 c_seteuid = external('seteuid', [UID_T], rffi.INT,
1558 save_err=rffi.RFFI_SAVE_ERRNO)
1559 c_getgid = external('getgid', [], GID_T)
1560 c_getegid = external('getegid', [], GID_T)
1561 c_setgid = external('setgid', [GID_T], rffi.INT,
1562 save_err=rffi.RFFI_SAVE_ERRNO)
1563 c_setegid = external('setegid', [GID_T], rffi.INT,
1564 save_err=rffi.RFFI_SAVE_ERRNO)
1565
1566 def widen_uid(x):
1567 return rffi.cast(lltype.Unsigned, x)
1568 widen_gid = widen_uid
1569
1570 # NOTE: the resulting type of functions that return a uid/gid is
1571 # always Unsigned. The argument type of functions that take a
1572 # uid/gid should also be Unsigned.
1573
1574 @replace_os_function('getuid')
1575 def getuid():
1576 return widen_uid(c_getuid())
1577
1578 @replace_os_function('geteuid')
1579 def geteuid():
1580 return widen_uid(c_geteuid())
1581
1582 @replace_os_function('setuid')
1583 def setuid(uid):
1584 handle_posix_error('setuid', c_setuid(uid))
1585
1586 @replace_os_function('seteuid')
1587 def seteuid(uid):
1588 handle_posix_error('seteuid', c_seteuid(uid))
1589
1590 @replace_os_function('getgid')
1591 def getgid():
1592 return widen_gid(c_getgid())
1593
1594 @replace_os_function('getegid')
1595 def getegid():
1596 return widen_gid(c_getegid())
1597
1598 @replace_os_function('setgid')
1599 def setgid(gid):
1600 handle_posix_error('setgid', c_setgid(gid))
1601
1602 @replace_os_function('setegid')
1603 def setegid(gid):
1604 handle_posix_error('setegid', c_setegid(gid))
1605
1606 c_setreuid = external('setreuid', [UID_T, UID_T], rffi.INT,
1607 save_err=rffi.RFFI_SAVE_ERRNO)
1608 c_setregid = external('setregid', [GID_T, GID_T], rffi.INT,
1609 save_err=rffi.RFFI_SAVE_ERRNO)
1610
1611 @replace_os_function('setreuid')
1612 def setreuid(ruid, euid):
1613 handle_posix_error('setreuid', c_setreuid(ruid, euid))
1614
1615 @replace_os_function('setregid')
1616 def setregid(rgid, egid):
1617 handle_posix_error('setregid', c_setregid(rgid, egid))
1618
1619 UID_T_P = lltype.Ptr(lltype.Array(UID_T, hints={'nolength': True}))
1620 GID_T_P = lltype.Ptr(lltype.Array(GID_T, hints={'nolength': True}))
1621 c_getresuid = external('getresuid', [UID_T_P] * 3, rffi.INT,
1622 save_err=rffi.RFFI_SAVE_ERRNO)
1623 c_getresgid = external('getresgid', [GID_T_P] * 3, rffi.INT,
1624 save_err=rffi.RFFI_SAVE_ERRNO)
1625 c_setresuid = external('setresuid', [UID_T] * 3, rffi.INT,
1626 save_err=rffi.RFFI_SAVE_ERRNO)
1627 c_setresgid = external('setresgid', [GID_T] * 3, rffi.INT,
1628 save_err=rffi.RFFI_SAVE_ERRNO)
1629
1630 @replace_os_function('getresuid')
1631 def getresuid():
1632 out = lltype.malloc(UID_T_P.TO, 3, flavor='raw')
1633 try:
1634 handle_posix_error('getresuid',
1635 c_getresuid(rffi.ptradd(out, 0),
1636 rffi.ptradd(out, 1),
1637 rffi.ptradd(out, 2)))
1638 return (widen_uid(out[0]), widen_uid(out[1]), widen_uid(out[2]))
1639 finally:
1640 lltype.free(out, flavor='raw')
1641
1642 @replace_os_function('getresgid')
1643 def getresgid():
1644 out = lltype.malloc(GID_T_P.TO, 3, flavor='raw')
1645 try:
1646 handle_posix_error('getresgid',
1647 c_getresgid(rffi.ptradd(out, 0),
1648 rffi.ptradd(out, 1),
1649 rffi.ptradd(out, 2)))
1650 return (widen_gid(out[0]), widen_gid(out[1]), widen_gid(out[2]))
1651 finally:
1652 lltype.free(out, flavor='raw')
1653
1654 @replace_os_function('setresuid')
1655 def setresuid(ruid, euid, suid):
1656 handle_posix_error('setresuid', c_setresuid(ruid, euid, suid))
1657
1658 @replace_os_function('setresgid')
1659 def setresgid(rgid, egid, sgid):
1660 handle_posix_error('setresgid', c_setresgid(rgid, egid, sgid))
16261661
16271662 #___________________________________________________________________
16281663
17641799 # Support for f... and ...at families of POSIX functions
17651800
17661801 class CConfig:
1767 _compilation_info_ = ExternalCompilationInfo(
1768 includes=['sys/stat.h',
1769 'sys/time.h',
1770 'unistd.h',
1771 'fcntl.h'],
1772 )
1802 _compilation_info_ = eci
17731803 for _name in """faccessat fchdir fchmod fchmodat fchown fchownat fexecve
17741804 fdopendir fpathconf fstat fstatat fstatvfs ftruncate
17751805 futimens futimes futimesat linkat chflags lchflags lchmod lchown
20452075 def mknodat(path, mode, device, dir_fd=AT_FDCWD):
20462076 error = c_mknodat(dir_fd, path, mode, device)
20472077 handle_posix_error('mknodat', error)
2078
2079
2080 eci_inheritable = eci.merge(ExternalCompilationInfo(
2081 separate_module_sources=["""
2082 RPY_EXTERN
2083 int rpy_set_inheritable(int fd, int inheritable)
2084 {
2085 /* XXX minimal impl. XXX */
2086 int request = inheritable ? FIONCLEX : FIOCLEX;
2087 return ioctl(fd, request, NULL);
2088 }
2089 RPY_EXTERN
2090 int rpy_get_inheritable(int fd)
2091 {
2092 int flags = fcntl(fd, F_GETFD, 0);
2093 if (flags == -1)
2094 return -1;
2095 return !(flags & FD_CLOEXEC);
2096 }
2097 """],
2098 post_include_bits=['RPY_EXTERN int rpy_set_inheritable(int, int);']))
2099
2100 c_set_inheritable = external('rpy_set_inheritable', [rffi.INT, rffi.INT],
2101 rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
2102 compilation_info=eci_inheritable)
2103 c_get_inheritable = external('rpy_get_inheritable', [rffi.INT],
2104 rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO,
2105 compilation_info=eci_inheritable)
2106
2107 def set_inheritable(fd, inheritable):
2108 error = c_set_inheritable(fd, inheritable)
2109 handle_posix_error('set_inheritable', error)
2110
2111 def get_inheritable(fd):
2112 res = c_get_inheritable(fd)
2113 res = handle_posix_error('get_inheritable', res)
2114 return res != 0
0 from rpython.rlib import rposix
1 from rpython.rlib.objectmodel import specialize
2 from rpython.rtyper.lltypesystem import lltype, rffi
3
4
5 @specialize.argtype(0)
6 def opendir(path):
7 path = rposix._as_bytes0(path)
8 return opendir_bytes(path)
9
10 def opendir_bytes(path):
11 dirp = rposix.c_opendir(path)
12 if not dirp:
13 raise OSError(rposix.get_saved_errno(), "opendir failed")
14 return dirp
15
16 def closedir(dirp):
17 rposix.c_closedir(dirp)
18
19 NULL_DIRP = lltype.nullptr(rposix.DIRP.TO)
20
21 def nextentry(dirp):
22 """Read the next entry and returns an opaque object.
23 Use the methods has_xxx() and get_xxx() to read from that
24 opaque object. The opaque object is valid until the next
25 time nextentry() or closedir() is called. This may raise
26 OSError, or return a NULL pointer when exhausted. Note
27 that this doesn't filter out the "." and ".." entries.
28 """
29 direntp = rposix.c_readdir(dirp)
30 if direntp:
31 error = rposix.get_saved_errno()
32 if error:
33 raise OSError(error, "readdir failed")
34 return direntp
35
36 def has_name_bytes(direntp):
37 return True
38
39 def get_name_bytes(direntp):
40 namep = rffi.cast(rffi.CCHARP, direntp.c_d_name)
41 return rffi.charp2str(namep)
42
43 DT_UNKNOWN = rposix.dirent_config.get('DT_UNKNOWN', 0)
44 DT_REG = rposix.dirent_config.get('DT_REG', 255)
45 DT_DIR = rposix.dirent_config.get('DT_DIR', 255)
46 DT_LNK = rposix.dirent_config.get('DT_LNK', 255)
47
48 def get_known_type(direntp):
49 if rposix.HAVE_D_TYPE:
50 return rffi.getintfield(direntp, 'c_d_type')
51 return DT_UNKNOWN
845845 if res < 0:
846846 raise self.error_handler()
847847
848 def wait_for_data(self, for_writing):
849 timeout = self._select(for_writing)
850 if timeout != 0:
851 if timeout == 1:
852 raise SocketTimeout
853 else:
854 raise self.error_handler()
855
848856 def recv(self, buffersize, flags=0):
849857 """Receive up to buffersize bytes from the socket. For the optional
850858 flags argument, see the Unix manual. When no data is available, block
851859 until at least one byte is available or until the remote end is closed.
852860 When the remote end is closed and all data is read, return the empty
853861 string."""
854 timeout = self._select(False)
855 if timeout == 1:
856 raise SocketTimeout
857 elif timeout == 0:
858 with rffi.scoped_alloc_buffer(buffersize) as buf:
859 read_bytes = _c.socketrecv(self.fd,
860 rffi.cast(rffi.VOIDP, buf.raw),
861 buffersize, flags)
862 if read_bytes >= 0:
863 return buf.str(read_bytes)
862 self.wait_for_data(False)
863 with rffi.scoped_alloc_buffer(buffersize) as buf:
864 read_bytes = _c.socketrecv(self.fd, buf.raw, buffersize, flags)
865 if read_bytes >= 0:
866 return buf.str(read_bytes)
864867 raise self.error_handler()
865868
866869 def recvinto(self, rwbuffer, nbytes, flags=0):
867 buf = self.recv(nbytes, flags)
868 rwbuffer.setslice(0, buf)
869 return len(buf)
870 try:
871 rwbuffer.get_raw_address()
872 except ValueError:
873 buf = self.recv(nbytes, flags)
874 rwbuffer.setslice(0, buf)
875 return len(buf)
876 else:
877 self.wait_for_data(False)
878 raw = rwbuffer.get_raw_address()
879 read_bytes = _c.socketrecv(self.fd, raw, nbytes, flags)
880 keepalive_until_here(rwbuffer)
881 if read_bytes >= 0:
882 return read_bytes
883 raise self.error_handler()
870884
871885 @jit.dont_look_inside
872886 def recvfrom(self, buffersize, flags=0):
873887 """Like recv(buffersize, flags) but also return the sender's
874888 address."""
875 read_bytes = -1
876 timeout = self._select(False)
877 if timeout == 1:
878 raise SocketTimeout
879 elif timeout == 0:
880 with rffi.scoped_alloc_buffer(buffersize) as buf:
881 address, addr_p, addrlen_p = self._addrbuf()
882 try:
883 read_bytes = _c.recvfrom(self.fd, buf.raw, buffersize, flags,
884 addr_p, addrlen_p)
885 addrlen = rffi.cast(lltype.Signed, addrlen_p[0])
886 finally:
887 lltype.free(addrlen_p, flavor='raw')
888 address.unlock()
889 if read_bytes >= 0:
890 if addrlen:
891 address.addrlen = addrlen
892 else:
893 address = None
894 data = buf.str(read_bytes)
895 return (data, address)
889 self.wait_for_data(False)
890 with rffi.scoped_alloc_buffer(buffersize) as buf:
891 address, addr_p, addrlen_p = self._addrbuf()
892 try:
893 read_bytes = _c.recvfrom(self.fd, buf.raw, buffersize, flags,
894 addr_p, addrlen_p)
895 addrlen = rffi.cast(lltype.Signed, addrlen_p[0])
896 finally:
897 lltype.free(addrlen_p, flavor='raw')
898 address.unlock()
899 if read_bytes >= 0:
900 if addrlen:
901 address.addrlen = addrlen
902 else:
903 address = None
904 data = buf.str(read_bytes)
905 return (data, address)
896906 raise self.error_handler()
897907
898908 def recvfrom_into(self, rwbuffer, nbytes, flags=0):
899 buf, addr = self.recvfrom(nbytes, flags)
900 rwbuffer.setslice(0, buf)
901 return len(buf), addr
909 try:
910 rwbuffer.get_raw_address()
911 except ValueError:
912 buf, addr = self.recvfrom(nbytes, flags)
913 rwbuffer.setslice(0, buf)
914 return len(buf), addr
915 else:
916 self.wait_for_data(False)
917 address, addr_p, addrlen_p = self._addrbuf()
918 try:
919 raw = rwbuffer.get_raw_address()
920 read_bytes = _c.recvfrom(self.fd, raw, nbytes, flags,
921 addr_p, addrlen_p)
922 keepalive_until_here(rwbuffer)
923 addrlen = rffi.cast(lltype.Signed, addrlen_p[0])
924 finally:
925 lltype.free(addrlen_p, flavor='raw')
926 address.unlock()
927 if read_bytes >= 0:
928 if addrlen:
929 address.addrlen = addrlen
930 else:
931 address = None
932 return (read_bytes, address)
933 raise self.error_handler()
902934
903935 def send_raw(self, dataptr, length, flags=0):
904936 """Send data from a CCHARP buffer."""
905 res = -1
906 timeout = self._select(True)
907 if timeout == 1:
908 raise SocketTimeout
909 elif timeout == 0:
910 res = _c.send(self.fd, dataptr, length, flags)
937 self.wait_for_data(True)
938 res = _c.send(self.fd, dataptr, length, flags)
911939 if res < 0:
912940 raise self.error_handler()
913941 return res
941969 def sendto(self, data, flags, address):
942970 """Like send(data, flags) but allows specifying the destination
943971 address. (Note that 'flags' is mandatory here.)"""
944 res = -1
945 timeout = self._select(True)
946 if timeout == 1:
947 raise SocketTimeout
948 elif timeout == 0:
949 addr = address.lock()
950 res = _c.sendto(self.fd, data, len(data), flags,
951 addr, address.addrlen)
952 address.unlock()
972 self.wait_for_data(True)
973 addr = address.lock()
974 res = _c.sendto(self.fd, data, len(data), flags,
975 addr, address.addrlen)
976 address.unlock()
953977 if res < 0:
954978 raise self.error_handler()
955979 return res
22 from rpython.rlib import jit
33 from rpython.rlib.objectmodel import fetch_translated_config
44 from rpython.rtyper.lltypesystem import lltype, llmemory
5 from rpython.rlib.rvmprof import cintf
56
67 DEBUG = False
78
2324 def new(self, callback, arg=llmemory.NULL):
2425 if DEBUG:
2526 callback = _debug_wrapper(callback)
26 h = self._gcrootfinder.new(self, callback, arg)
27 x = cintf.save_rvmprof_stack()
28 try:
29 cintf.empty_rvmprof_stack()
30 h = self._gcrootfinder.new(self, callback, arg)
31 finally:
32 cintf.restore_rvmprof_stack(x)
2733 if DEBUG:
2834 debug.add(h)
2935 return h
3339 def switch(self, stacklet):
3440 if DEBUG:
3541 debug.remove(stacklet)
36 h = self._gcrootfinder.switch(stacklet)
42 x = cintf.save_rvmprof_stack()
43 try:
44 h = self._gcrootfinder.switch(stacklet)
45 finally:
46 cintf.restore_rvmprof_stack(x)
3747 if DEBUG:
3848 debug.add(h)
3949 return h
55 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
66 from rpython.translator.tool.cbuild import ExternalCompilationInfo
77 from rpython.rtyper.tool import rffi_platform as platform
8 from rpython.rlib import rthread
8 from rpython.rlib import rthread, jit
9 from rpython.rlib.objectmodel import we_are_translated
910
1011 class VMProfPlatformUnsupported(Exception):
1112 pass
5455 [rffi.INT], lltype.Void,
5556 compilation_info=eci,
5657 _nowrapper=True)
58
5759 return CInterface(locals())
5860
5961
9496 return s
9597
9698 def leave_code(s):
99 if not we_are_translated():
100 assert vmprof_tl_stack.getraw() == s
97101 vmprof_tl_stack.setraw(s.c_next)
98102 lltype.free(s, flavor='raw')
103
104 #
105 # JIT notes:
106 #
107 # - When running JIT-generated assembler code, we have different custom
108 # code to build the VMPROFSTACK, so the functions above are not used.
109 # (It uses kind == VMPROF_JITTED_TAG and the VMPROFSTACK is allocated
110 # in the C stack.)
111 #
112 # - The jitcode for decorated_jitted_function() in rvmprof.py is
113 # special-cased by jtransform.py to produce this:
114 #
115 # rvmprof_code(0, unique_id)
116 # res = inline_call FUNC <- for func(*args)
117 # rvmprof_code(1, unique_id)
118 # return res
119 #
120 # There is no 'catch_exception', but the second 'rvmprof_code' is
121 # meant to be executed even in case there was an exception. This is
122 # done by a special case in pyjitpl.py and blackhole.py. The point
123 # is that the above simple pattern can be detected by the blackhole
124 # interp, when it first rebuilds all the intermediate RPython
125 # frames; at that point it needs to call jit_rvmprof_code(0) on all
126 # intermediate RPython frames, so it does pattern matching to
127 # recognize when it must call that and with which 'unique_id' value.
128 #
129 # - The jitcode opcode 'rvmprof_code' doesn't produce any resop. When
130 # meta-interpreting, it causes pyjitpl to call jit_rvmprof_code().
131 # As mentioned above, there is logic to call jit_rvmprof_code(1)
132 # even if we exit with an exception, even though there is no
133 # 'catch_exception'. There is similar logic inside the blackhole
134 # interpreter.
135
136
137 def jit_rvmprof_code(leaving, unique_id):
138 if leaving == 0:
139 enter_code(unique_id) # ignore the return value
140 else:
141 s = vmprof_tl_stack.getraw()
142 assert s.c_value == unique_id and s.c_kind == VMPROF_CODE_TAG
143 leave_code(s)
144
145 #
146 # stacklet support
147
148 def save_rvmprof_stack():
149 return vmprof_tl_stack.get_or_make_raw()
150
151 def empty_rvmprof_stack():
152 vmprof_tl_stack.setraw(lltype.nullptr(VMPROFSTACK))
153
154 def restore_rvmprof_stack(x):
155 vmprof_tl_stack.setraw(x)
33 from rpython.rlib.rvmprof import cintf
44 from rpython.rtyper.annlowlevel import cast_instance_to_gcref
55 from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance
6 from rpython.rtyper.lltypesystem import rffi, llmemory
6 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
77 from rpython.rtyper.lltypesystem.lloperation import llop
88 from rpython.rlib.rweaklist import RWeakListMixin
99
2424 def __str__(self):
2525 return self.msg
2626
27 class FakeWeakCodeObjectList(object):
28 def add_handle(self, handle):
29 pass
30
2731 class VMProf(object):
2832
2933 _immutable_fields_ = ['is_enabled?']
34
35 use_weaklist = True # False for tests
3036
3137 def __init__(self):
3238 "NOT_RPYTHON: use _get_vmprof()"
3945 def _cleanup_(self):
4046 self.is_enabled = False
4147
48 @jit.dont_look_inside
4249 @specialize.argtype(1)
4350 def register_code(self, code, full_name_func):
4451 """Register the code object. Call when a new code object is made.
5562 self._code_unique_id = uid
5663 if self.is_enabled:
5764 self._write_code_registration(uid, full_name_func(code))
58 else:
65 elif self.use_weaklist:
5966 code._vmprof_weak_list.add_handle(code)
6067
6168 def register_code_object_class(self, CodeClass, full_name_func):
8087 if CodeClass in self._code_classes:
8188 return
8289 CodeClass._vmprof_unique_id = 0 # default value: "unknown"
90 immut = CodeClass.__dict__.get('_immutable_fields_', [])
91 CodeClass._immutable_fields_ = list(immut) + ['_vmprof_unique_id']
92 attrs = CodeClass.__dict__.get('_attrs_', None)
93 if attrs is not None:
94 CodeClass._attrs_ = list(attrs) + ['_vmprof_unique_id']
8395 self._code_classes.add(CodeClass)
8496 #
8597 class WeakCodeObjectList(RWeakListMixin):
8698 def __init__(self):
8799 self.initialize()
88 CodeClass._vmprof_weak_list = WeakCodeObjectList()
100 if self.use_weaklist:
101 CodeClass._vmprof_weak_list = WeakCodeObjectList()
102 else:
103 CodeClass._vmprof_weak_list = FakeWeakCodeObjectList()
89104 #
90105 def gather_all_code_objs():
91106 all_code_wrefs = CodeClass._vmprof_weak_list.get_all_handles()
101116 prev = self._gather_all_code_objs
102117 self._gather_all_code_objs = gather_all_code_objs
103118
119 @jit.dont_look_inside
104120 def enable(self, fileno, interval):
105121 """Enable vmprof. Writes go to the given 'fileno'.
106122 The sampling interval is given by 'interval' as a number of
121137 raise VMProfError(os.strerror(rposix.get_saved_errno()))
122138 self.is_enabled = True
123139
140 @jit.dont_look_inside
124141 def disable(self):
125142 """Disable vmprof.
126143 Raises VMProfError if something goes wrong.
139156 if self.cintf.vmprof_register_virtual_function(name, uid, 500000) < 0:
140157 raise VMProfError("vmprof buffers full! disk full or too slow")
141158
142 def vmprof_execute_code(name, get_code_fn, result_class=None):
159 def vmprof_execute_code(name, get_code_fn, result_class=None,
160 _hack_update_stack_untranslated=False):
143161 """Decorator to be used on the function that interprets a code object.
144162
145163 'name' must be a unique name.
149167
150168 'result_class' is ignored (backward compatibility).
151169 """
170 if _hack_update_stack_untranslated:
171 from rpython.rtyper.annlowlevel import llhelper
172 enter_code = llhelper(lltype.Ptr(
173 lltype.FuncType([lltype.Signed], cintf.PVMPROFSTACK)),
174 cintf.enter_code)
175 leave_code = llhelper(lltype.Ptr(
176 lltype.FuncType([cintf.PVMPROFSTACK], lltype.Void)),
177 cintf.leave_code)
178 else:
179 enter_code = cintf.enter_code
180 leave_code = cintf.leave_code
181
152182 def decorate(func):
153183 try:
154184 _get_vmprof()
155185 except cintf.VMProfPlatformUnsupported:
156186 return func
157187
188 @jit.oopspec("rvmprof.jitted(unique_id)")
189 def decorated_jitted_function(unique_id, *args):
190 return func(*args)
191
158192 def decorated_function(*args):
159 # If we are being JITted, we want to skip the trampoline, else the
160 # JIT cannot see through it.
193 unique_id = get_code_fn(*args)._vmprof_unique_id
194 unique_id = rffi.cast(lltype.Signed, unique_id)
195 # ^^^ removes the "known non-negative" hint for annotation
161196 if not jit.we_are_jitted():
162 unique_id = get_code_fn(*args)._vmprof_unique_id
163 x = cintf.enter_code(unique_id)
197 x = enter_code(unique_id)
164198 try:
165199 return func(*args)
166200 finally:
167 cintf.leave_code(x)
201 leave_code(x)
168202 else:
169 return func(*args)
203 return decorated_jitted_function(unique_id, *args)
170204
171205 decorated_function.__name__ = func.__name__ + '_rvmprof'
172206 return decorated_function
1515 # include "structdef.h"
1616 # include "src/threadlocal.h"
1717 # include "rvmprof.h"
18
1918 #endif
2019
2120
00 #if !defined(__OpenBSD__)
1 #define HAVE_SYS_UCONTEXT_H
1 # define HAVE_SYS_UCONTEXT_H
2 #else
3 # define HAVE_SIGNAL_H
24 #endif
3 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
5
6 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
47 #ifdef __i386__
58 #define PC_FROM_UCONTEXT uc_mcontext.mc_eip
69 #else
6464 #elif defined(HAVE_CYGWIN_SIGNAL_H)
6565 #include <cygwin/signal.h>
6666 typedef ucontext ucontext_t;
67 #elif defined(__OpenBSD__)
67 #elif defined(HAVE_SIGNAL_H)
6868 #include <signal.h>
69 #else
70 # error "don't know how to get the pc on this platform"
6971 #endif
7072
7173
141141
142142 def compute_result_annotation(self, s_keyclass, s_valueclass):
143143 assert s_keyclass.is_constant()
144 s_key = self.bookkeeper.immutablevalue(s_keyclass.const())
144 s_key = self.bookkeeper.valueoftype(s_keyclass.const)
145145 return SomeWeakValueDict(
146146 s_key,
147147 _getclassdef(s_valueclass))
157157 bk = self.bookkeeper
158158 x = self.instance
159159 return SomeWeakValueDict(
160 bk.immutablevalue(x._keyclass()),
160 bk.valueoftype(x._keyclass),
161161 bk.getuniqueclassdef(x._valueclass))
162162
163163 def _getclassdef(s_instance):
66 from rpython.annotator.annrpython import RPythonAnnotator
77 from rpython.conftest import option
88 from rpython.annotator.model import SomeInstance
9 from rpython.rtyper.test.test_llinterp import interpret
910
1011 def test_nonconst():
1112 def nonconst_f():
1617 s = a.build_types(nonconst_f, [])
1718 assert s.knowntype is int
1819 assert not hasattr(s, 'const')
19
2020
2121 def test_nonconst_list():
2222 def nonconst_l():
5555
5656 if option.view:
5757 a.translator.view()
58
59 def test_already_not_const():
60 def fn(x):
61 return NonConstant(x)
62 assert interpret(fn, [5]) == 5
11 from rpython.rtyper.test.test_llinterp import interpret
22 from rpython.rlib.rarithmetic import *
33 from rpython.rlib.rstring import ParseStringError, ParseStringOverflowError
4 from hypothesis import given, strategies
45 import sys
56 import py
67
392393 assert not int_between(1, 2, 2)
393394 assert not int_between(1, 1, 1)
394395
396 def test_int_force_ge_zero():
397 assert int_force_ge_zero(42) == 42
398 assert int_force_ge_zero(0) == 0
399 assert int_force_ge_zero(-42) == 0
400
401 @given(strategies.integers(min_value=0, max_value=sys.maxint),
402 strategies.integers(min_value=1, max_value=sys.maxint))
403 def test_int_c_div_mod(x, y):
404 assert int_c_div(~x, y) == -(abs(~x) // y)
405 assert int_c_div( x,-y) == -(x // y)
406 if (x, y) == (sys.maxint, 1):
407 py.test.skip("would overflow")
408 assert int_c_div(~x,-y) == +(abs(~x) // y)
409 for x1 in [x, ~x]:
410 for y1 in [y, -y]:
411 assert int_c_div(x1, y1) * y1 + int_c_mod(x1, y1) == x1
412
395413 # these can't be prebuilt on 32bit
396414 U1 = r_ulonglong(0x0102030405060708L)
397415 U2 = r_ulonglong(0x0807060504030201L)
44 from rpython.rlib.rarithmetic import intmask
55 from rpython.rlib import rmmap as mmap
66 from rpython.rlib.rmmap import RTypeError, RValueError, alloc, free
7 from rpython.rlib.rmmap import madvise_free
8
79
810 class TestMMap:
911 def setup_class(cls):
489491 data[i] = chr(i & 0xff)
490492 for i in range(0, map_size, 171):
491493 assert data[i] == chr(i & 0xff)
494 madvise_free(data, map_size)
492495 free(data, map_size)
493496
494497 def test_compile_alloc_free():
551551 # Note: fdlistdir() always closes dirfd
552552 assert result == ['file']
553553
554 @rposix_requires('fdlistdir')
555 def test_fdlistdir_rewinddir(tmpdir):
556 tmpdir.join('file').write('text')
557 dirfd = os.open(str(tmpdir), os.O_RDONLY)
558 result1 = rposix.fdlistdir(os.dup(dirfd))
559 result2 = rposix.fdlistdir(dirfd)
560 assert result1 == result2 == ['file']
561
554562 @rposix_requires('symlinkat')
555563 def test_symlinkat(tmpdir):
556564 tmpdir.join('file').write('text')
571579 os.close(dirfd)
572580 assert tmpdir.join('file').check(exists=False)
573581 assert tmpdir.join('file2').check(exists=True)
582
583 def test_set_inheritable():
584 fd1, fd2 = os.pipe()
585 rposix.set_inheritable(fd1, True)
586 assert rposix.get_inheritable(fd1) == True
587 rposix.set_inheritable(fd1, False)
588 assert rposix.get_inheritable(fd1) == False
589 os.close(fd1)
590 os.close(fd2)
0 import sys, os
1 import py
2 from rpython.rlib import rposix_scandir
3
4
5 class TestScanDir(object):
6
7 @py.test.mark.skipif("sys.platform == 'win32'") # XXX
8 def test_name_bytes(self):
9 scan = rposix_scandir.opendir('/')
10 found = []
11 while True:
12 p = rposix_scandir.nextentry(scan)
13 if not p:
14 break
15 assert rposix_scandir.has_name_bytes(p)
16 found.append(rposix_scandir.get_name_bytes(p))
17 rposix_scandir.closedir(scan)
18 found.remove('.')
19 found.remove('..')
20 assert sorted(found) == sorted(os.listdir('/'))
118118 s1.close()
119119 s2.close()
120120
121 def test_socketpair_recvinto():
121 def test_socketpair_recvinto_1():
122122 class Buffer:
123123 def setslice(self, start, string):
124124 self.x = string
125125
126 def as_str(self):
127 return self.x
126 def get_raw_address(self):
127 raise ValueError
128128
129129 if sys.platform == "win32":
130130 py.test.skip('No socketpair on Windows')
131131 s1, s2 = socketpair()
132132 buf = Buffer()
133133 s1.sendall('?')
134 s2.recvinto(buf, 1)
135 assert buf.as_str() == '?'
134 n = s2.recvinto(buf, 1)
135 assert n == 1
136 assert buf.x == '?'
136137 count = s2.send('x'*99)
137138 assert 1 <= count <= 99
138 s1.recvinto(buf, 100)
139 assert buf.as_str() == 'x'*count
139 n = s1.recvinto(buf, 100)
140 assert n == count
141 assert buf.x == 'x'*count
142 s1.close()
143 s2.close()
144
145 def test_socketpair_recvinto_2():
146 class Buffer:
147 def __init__(self):
148 self._p = lltype.malloc(rffi.CCHARP.TO, 100, flavor='raw',
149 track_allocation=False)
150
151 def _as_str(self, count):
152 return rffi.charpsize2str(self._p, count)
153
154 def get_raw_address(self):
155 return self._p
156
157 if sys.platform == "win32":
158 py.test.skip('No socketpair on Windows')
159 s1, s2 = socketpair()
160 buf = Buffer()
161 s1.sendall('?')
162 n = s2.recvinto(buf, 1)
163 assert n == 1
164 assert buf._as_str(1) == '?'
165 count = s2.send('x'*99)
166 assert 1 <= count <= 99
167 n = s1.recvinto(buf, 100)
168 assert n == count
169 assert buf._as_str(n) == 'x'*count
170 s1.close()
171 s2.close()
172
173 def test_socketpair_recvfrom_into_1():
174 class Buffer:
175 def setslice(self, start, string):
176 self.x = string
177
178 def get_raw_address(self):
179 raise ValueError
180
181 if sys.platform == "win32":
182 py.test.skip('No socketpair on Windows')
183 s1, s2 = socketpair()
184 buf = Buffer()
185 s1.sendall('?')
186 n, addr = s2.recvfrom_into(buf, 1)
187 assert n == 1
188 assert addr is None
189 assert buf.x == '?'
190 count = s2.send('x'*99)
191 assert 1 <= count <= 99
192 n, addr = s1.recvfrom_into(buf, 100)
193 assert n == count
194 assert addr is None
195 assert buf.x == 'x'*count
196 s1.close()
197 s2.close()
198
199 def test_socketpair_recvfrom_into_2():
200 class Buffer:
201 def __init__(self):
202 self._p = lltype.malloc(rffi.CCHARP.TO, 100, flavor='raw',
203 track_allocation=False)
204
205 def _as_str(self, count):
206 return rffi.charpsize2str(self._p, count)
207
208 def get_raw_address(self):
209 return self._p
210
211 if sys.platform == "win32":
212 py.test.skip('No socketpair on Windows')
213 s1, s2 = socketpair()
214 buf = Buffer()
215 s1.sendall('?')
216 n, addr = s2.recvfrom_into(buf, 1)
217 assert n == 1
218 assert addr is None
219 assert buf._as_str(1) == '?'
220 count = s2.send('x'*99)
221 assert 1 <= count <= 99
222 n, addr = s1.recvfrom_into(buf, 100)
223 assert n == count
224 assert addr is None
225 assert buf._as_str(n) == 'x'*count
140226 s1.close()
141227 s2.close()
142228
312398 assert isinstance(lst, list)
313399 found = False
314400 for family, socktype, protocol, canonname, addr in lst:
315 if addr.get_host() == '104.130.43.121':
401 if addr.get_host() in ('104.130.43.121', '23.253.135.79'):
316402 found = True
403 elif family == AF_INET:
404 print 'pydotorg changed to', addr.get_host()
317405 result[i] += found
318406
319407 def test_getaddrinfo_pydotorg():
588676 return 0
589677 fc = compile(f, [], thread=True)
590678 assert fc() == 0
679
680 def test_socket_saves_errno(tmpdir):
681 # ensure errno is set to a known value...
682 unconnected_sock = RSocket()
683 e = py.test.raises(CSocketError, unconnected_sock.recv, 1024)
684 # ...which is ENOTCONN
685 assert e.value.errno == errno.ENOTCONN
686
687 e = py.test.raises(CSocketError,
688 RSocket,
689 family=AF_INET, type=SOCK_STREAM, proto=SOL_UDP)
690 assert e.value.errno in (errno.EPROTOTYPE, errno.EPROTONOSUPPORT)
179179 RWeakValueDictionary(str, X).get("foobar")
180180 RWeakValueDictionary(int, Y).get(42)
181181 interpret(g, [])
182
183 def test_key_instance():
184 class K(object):
185 pass
186 keys = [K(), K(), K()]
187
188 def g(d):
189 assert d.get(keys[3]) is None
190 x1 = X(); x2 = X(); x3 = X()
191 d.set(keys[0], x1)
192 d.set(keys[1], x2)
193 d.set(keys[2], x3)
194 assert d.get(keys[0]) is x1
195 assert d.get(keys[1]) is x2
196 assert d.get(keys[2]) is x3
197 assert d.get(keys[3]) is None
198 return x1, x3 # x2 dies
199 def f():
200 keys.append(K())
201 d = RWeakValueDictionary(K, X)
202 x1, x3 = g(d)
203 rgc.collect(); rgc.collect()
204 assert d.get(keys[0]) is x1
205 assert d.get(keys[1]) is None
206 assert d.get(keys[2]) is x3
207 assert d.get(keys[3]) is None
208 d.set(keys[0], None)
209 assert d.get(keys[0]) is None
210 assert d.get(keys[1]) is None
211 assert d.get(keys[2]) is x3
212 assert d.get(keys[3]) is None
213 f()
214 interpret(f, [])
347347 _about_ = llhelper
348348
349349 def compute_result_annotation(self, s_F, s_callable):
350 from rpython.annotator.description import FunctionDesc
350351 assert s_F.is_constant()
351 assert s_callable.is_constant()
352 assert isinstance(s_callable, annmodel.SomePBC)
352353 F = s_F.const
353354 FUNC = F.TO
354355 args_s = [lltype_to_annotation(T) for T in FUNC.ARGS]
355 key = (llhelper, s_callable.const)
356 s_res = self.bookkeeper.emulate_pbc_call(key, s_callable, args_s)
357 assert lltype_to_annotation(FUNC.RESULT).contains(s_res)
356 for desc in s_callable.descriptions:
357 assert isinstance(desc, FunctionDesc)
358 assert desc.pyobj is not None
359 if s_callable.is_constant():
360 assert s_callable.const is desc.pyobj
361 key = (llhelper, desc.pyobj)
362 s_res = self.bookkeeper.emulate_pbc_call(key, s_callable, args_s)
363 assert lltype_to_annotation(FUNC.RESULT).contains(s_res)
358364 return SomePtr(F)
359365
360366 def specialize_call(self, hop):
361367 hop.exception_cannot_occur()
362 return hop.args_r[1].get_unique_llfn()
368 if hop.args_s[1].is_constant():
369 return hop.args_r[1].get_unique_llfn()
370 else:
371 F = hop.args_s[0].const
372 assert hop.args_r[1].lowleveltype == F
373 return hop.inputarg(hop.args_r[1], 1)
363374
364375 # ____________________________________________________________
365376
165165 })
166166
167167 if '__int128_t' in rffi.TYPES:
168 _ctypes_cache[rffi.__INT128_T] = ctypes.c_longlong # XXX: Not right at all. But for some reason, It started by while doing JIT compile after a merge with default. Can't extend ctypes, because thats a python standard, right?
168 class c_int128(ctypes.Array): # based on 2 ulongs
169 _type_ = ctypes.c_uint64
170 _length_ = 2
171 @property
172 def value(self):
173 res = self[0] | (self[1] << 64)
174 if res >= (1 << 127):
175 res -= 1 << 128
176 return res
177 _ctypes_cache[rffi.__INT128_T] = c_int128
169178
170179 # for unicode strings, do not use ctypes.c_wchar because ctypes
171180 # automatically converts arrays into unicode strings.
240249
241250 if not A._hints.get('nolength'):
242251 _fields_ = [('length', lentype),
243 ('items', max_n * ctypes_item)]
252 ('items',
253 (max_n + A._hints.get('extra_item_after_alloc', 0))
254 * ctypes_item)]
244255 else:
245256 _fields_ = [('items', max_n * ctypes_item)]
246257
684695 def getbounds(self):
685696 # we have no clue, so we allow whatever index
686697 return 0, maxint
698
699 def shrinklength(self, newlength):
700 raise NotImplementedError
687701
688702 def getitem(self, index, uninitialized_ok=False):
689703 res = self._storage.contents._getitem(index, boundscheck=False)
5151 del self.objectptrs[offset]
5252 del self.objectsizes[offset]
5353 obj._free()
54 if zero and zero != 3:
54 if zero in (1, 2):
5555 initialbyte = "0"
5656 else:
5757 initialbyte = "#"
334334 * 1: clear, optimized for a very large area of memory
335335 * 2: clear, optimized for a small or medium area of memory
336336 * 3: fill with garbage
337 * 4: large area of memory that can benefit from MADV_FREE
338 (i.e. contains garbage, may be zero-filled or not)
337339 """
338340 arena_addr = getfakearenaaddress(arena_addr)
339341 arena_addr.arena.reset(zero, arena_addr.offset, size)
409411 self.pagesize = 0
410412 def _cleanup_(self):
411413 self.pagesize = 0
414 def get(self):
415 pagesize = self.pagesize
416 if pagesize == 0:
417 pagesize = rffi.cast(lltype.Signed, legacy_getpagesize())
418 self.pagesize = pagesize
419 return pagesize
420
412421 posixpagesize = PosixPageSize()
413422
414423 def clear_large_memory_chunk(baseaddr, size):
415424 from rpython.rlib import rmmap
416425
417 pagesize = posixpagesize.pagesize
418 if pagesize == 0:
419 pagesize = rffi.cast(lltype.Signed, legacy_getpagesize())
420 posixpagesize.pagesize = pagesize
421
426 pagesize = posixpagesize.get()
422427 if size > 2 * pagesize:
423428 lowbits = rffi.cast(lltype.Signed, baseaddr) & (pagesize - 1)
424429 if lowbits: # clear the initial misaligned part, if any
442447 # them immediately.
443448 clear_large_memory_chunk = llmemory.raw_memclear
444449
450 class PosixPageSize:
451 def get(self):
452 from rpython.rlib import rmmap
453 return rmmap.PAGESIZE
454 posixpagesize = PosixPageSize()
455
456 def madvise_arena_free(baseaddr, size):
457 from rpython.rlib import rmmap
458
459 pagesize = posixpagesize.get()
460 baseaddr = rffi.cast(lltype.Signed, baseaddr)
461 aligned_addr = (baseaddr + pagesize - 1) & ~(pagesize - 1)
462 size -= (aligned_addr - baseaddr)
463 if size >= pagesize:
464 rmmap.madvise_free(rffi.cast(rmmap.PTR, aligned_addr),
465 size & ~(pagesize - 1))
466
467
445468 if os.name == "posix":
446469 from rpython.translator.tool.cbuild import ExternalCompilationInfo
447470 _eci = ExternalCompilationInfo(includes=['sys/mman.h'])
508531 clear_large_memory_chunk(arena_addr, size)
509532 elif zero == 3:
510533 llop.raw_memset(lltype.Void, arena_addr, ord('#'), size)
534 elif zero == 4:
535 madvise_arena_free(arena_addr, size)
511536 else:
512537 llmemory.raw_memclear(arena_addr, size)
513538 llimpl_arena_reset._always_inline_ = True
303303 return cast_ptr_to_adr(p)
304304
305305 def raw_memcopy(self, srcadr, dstadr):
306 # should really copy the length field, but we can't
307 pass
306 # copy the length field, if we can
307 srclen = srcadr.ptr._obj.getlength()
308 dstlen = dstadr.ptr._obj.getlength()
309 if dstlen != srclen:
310 assert dstlen > srclen, "can't increase the length"
311 # a decrease in length occurs in the GC tests when copying a STR:
312 # the copy is initially allocated with really one extra char,
313 # the 'extra_item_after_alloc', and must be fixed.
314 dstadr.ptr._obj.shrinklength(srclen)
308315
309316
310317 class ArrayLengthOffset(AddressOffset):
389396 else:
390397 raise Exception("don't know how to take the size of a %r"%TYPE)
391398
399 @specialize.memo()
400 def extra_item_after_alloc(ARRAY):
401 assert isinstance(ARRAY, lltype.Array)
402 return ARRAY._hints.get('extra_item_after_alloc', 0)
403
392404 @specialize.arg(0)
393405 def sizeof(TYPE, n=None):
406 """Return the symbolic size of TYPE.
407 For a Struct with no varsized part, it must be called with n=None.
408 For an Array or a Struct with a varsized part, it is the number of items.
409 There is a special case to return 1 more than requested if the array
410 has the hint 'extra_item_after_alloc' set to 1.
411 """
394412 if n is None:
395413 return _sizeof_none(TYPE)
396414 elif isinstance(TYPE, lltype.Array):
415 n += extra_item_after_alloc(TYPE)
397416 return itemoffsetof(TYPE) + _sizeof_none(TYPE.OF) * n
398417 else:
399418 return _sizeof_int(TYPE, n)
10351054 _reccopy(subsrc, subdst)
10361055 else:
10371056 # this is a hack XXX de-hack this
1038 llvalue = source._obj.getitem(i, uninitialized_ok=True)
1057 llvalue = source._obj.getitem(i, uninitialized_ok=2)
10391058 if not isinstance(llvalue, lltype._uninitialized):
10401059 dest._obj.setitem(i, llvalue)
10411060 elif isinstance(T, lltype.Struct):
540540 'threadlocalref_enum': LLOp(sideeffects=False), # enum all threadlocalrefs
541541
542542 # __________ debugging __________
543 'debug_view': LLOp(),
544 'debug_print': LLOp(canrun=True),
545 'debug_start': LLOp(canrun=True),
546 'debug_stop': LLOp(canrun=True),
547 'have_debug_prints': LLOp(canrun=True),
548 'have_debug_prints_for':LLOp(canrun=True),
549 'debug_offset': LLOp(canrun=True),
550 'debug_flush': LLOp(canrun=True),
551 'debug_assert': LLOp(tryfold=True),
552 'debug_fatalerror': LLOp(canrun=True),
553 'debug_llinterpcall': LLOp(canraise=(Exception,)),
543 'debug_view': LLOp(),
544 'debug_print': LLOp(canrun=True),
545 'debug_start': LLOp(canrun=True),
546 'debug_stop': LLOp(canrun=True),
547 'have_debug_prints': LLOp(canrun=True),
548 'have_debug_prints_for': LLOp(canrun=True),
549 'debug_offset': LLOp(canrun=True),
550 'debug_flush': LLOp(canrun=True),
551 'debug_assert': LLOp(tryfold=True),
552 'debug_fatalerror': LLOp(canrun=True),
553 'debug_llinterpcall': LLOp(canraise=(Exception,)),
554554 # Python func call 'res=arg[0](*arg[1:])'
555555 # in backends, abort() or whatever is fine
556556 'debug_start_traceback': LLOp(),
811811 if tp is long:
812812 if -maxint-1 <= val <= maxint:
813813 return Signed
814 elif longlongmask(val) == val:
815 return SignedLongLong
814816 else:
815 return SignedLongLong
817 raise OverflowError("integer %r is out of bounds" % (val,))
816818 if tp is bool:
817819 return Bool
818820 if issubclass(tp, base_int):
19231925 return 0, stop
19241926
19251927 def getitem(self, index, uninitialized_ok=False):
1926 v = self.items[index]
1928 try:
1929 v = self.items[index]
1930 except IndexError:
1931 if (index == len(self.items) and uninitialized_ok == 2 and
1932 self._TYPE._hints.get('extra_item_after_alloc')):
1933 # special case: reading the extra final char returns
1934 # an uninitialized, if 'uninitialized_ok==2'
1935 return _uninitialized(self._TYPE.OF)
1936 raise
19271937 if isinstance(v, _uninitialized) and not uninitialized_ok:
19281938 raise UninitializedMemoryAccess("%r[%s]"%(self, index))
19291939 return v
19301940
19311941 def setitem(self, index, value):
19321942 assert typeOf(value) == self._TYPE.OF
1933 self.items[index] = value
1943 try:
1944 self.items[index] = value
1945 except IndexError:
1946 if (index == len(self.items) and value == '\x00' and
1947 self._TYPE._hints.get('extra_item_after_alloc')):
1948 # special case: writing NULL to the extra final char
1949 return
1950 raise
19341951
19351952 assert not '__dict__' in dir(_array)
19361953 assert not '__dict__' in dir(_struct)
579579 return hlstr(x)
580580 return x
581581
582 def op_debug_flush_log():
583 debug.debug_flush_log()
584
582585 def op_debug_print(*args):
583586 debug.debug_print(*map(_normalize, args))
584587
1414 from rpython.rtyper.tool.rfficache import platform, sizeof_c_type
1515 from rpython.translator.tool.cbuild import ExternalCompilationInfo
1616 from rpython.rtyper.annlowlevel import llhelper
17 from rpython.rlib.objectmodel import we_are_translated
17 from rpython.rlib.objectmodel import we_are_translated, we_are_translated_to_c
1818 from rpython.rlib.rstring import StringBuilder, UnicodeBuilder, assert_str0
1919 from rpython.rlib import jit
2020 from rpython.rtyper.lltypesystem import llmemory
231231 call_external_function = jit.dont_look_inside(
232232 call_external_function)
233233
234 def _oops():
235 raise AssertionError("can't pass (any more) a unicode string"
236 " directly to a VOIDP argument")
237 _oops._annspecialcase_ = 'specialize:memo'
238
234239 unrolling_arg_tps = unrolling_iterable(enumerate(args))
235240 def wrapper(*args):
236241 real_args = ()
242 # XXX 'to_free' leaks if an allocation fails with MemoryError
243 # and was not the first in this function
237244 to_free = ()
238245 for i, TARGET in unrolling_arg_tps:
239246 arg = args[i]
240 freeme = None
241 if TARGET == CCHARP:
247 if TARGET == CCHARP or TARGET is VOIDP:
242248 if arg is None:
243249 arg = lltype.nullptr(CCHARP.TO) # None => (char*)NULL
244 freeme = arg
250 to_free = to_free + (arg, '\x04')
245251 elif isinstance(arg, str):
246 arg = str2charp(arg)
247 # XXX leaks if a str2charp() fails with MemoryError
248 # and was not the first in this function
249 freeme = arg
252 tup = get_nonmovingbuffer_final_null(arg)
253 to_free = to_free + tup
254 arg = tup[0]
255 elif isinstance(arg, unicode):
256 _oops()
250257 elif TARGET == CWCHARP:
251258 if arg is None:
252259 arg = lltype.nullptr(CWCHARP.TO) # None => (wchar_t*)NULL
253 freeme = arg
260 to_free = to_free + (arg,)
254261 elif isinstance(arg, unicode):
255262 arg = unicode2wcharp(arg)
256 # XXX leaks if a unicode2wcharp() fails with MemoryError
257 # and was not the first in this function
258 freeme = arg
259 elif TARGET is VOIDP:
260 if arg is None:
261 arg = lltype.nullptr(VOIDP.TO)
262 elif isinstance(arg, str):
263 arg = str2charp(arg)
264 freeme = arg
265 elif isinstance(arg, unicode):
266 arg = unicode2wcharp(arg)
267 freeme = arg
263 to_free = to_free + (arg,)
268264 elif _isfunctype(TARGET) and not _isllptr(arg):
269265 # XXX pass additional arguments
270266 use_gil = invoke_around_handlers
282278 or TARGET is lltype.Bool)):
283279 arg = cast(TARGET, arg)
284280 real_args = real_args + (arg,)
285 to_free = to_free + (freeme,)
286281 res = call_external_function(*real_args)
287282 for i, TARGET in unrolling_arg_tps:
288 if to_free[i]:
289 lltype.free(to_free[i], flavor='raw')
283 arg = args[i]
284 if TARGET == CCHARP or TARGET is VOIDP:
285 if arg is None:
286 to_free = to_free[2:]
287 elif isinstance(arg, str):
288 free_nonmovingbuffer(arg, to_free[0], to_free[1])
289 to_free = to_free[2:]
290 elif TARGET == CWCHARP:
291 if arg is None:
292 to_free = to_free[1:]
293 elif isinstance(arg, unicode):
294 free_wcharp(to_free[0])
295 to_free = to_free[1:]
296 assert len(to_free) == 0
290297 if rarithmetic.r_int is not r_int:
291298 if result is INT:
292299 return cast(lltype.Signed, res)
815822 string is already nonmovable or could be pinned. Must be followed by a
816823 free_nonmovingbuffer call.
817824
818 First bool returned indicates if 'data' was pinned. Second bool returned
819 indicates if we did a raw alloc because pinning failed. Both bools
820 should never be true at the same time.
825 Also returns a char:
826 * \4: no pinning, returned pointer is inside 'data' which is nonmovable
827 * \5: 'data' was pinned, returned pointer is inside
828 * \6: pinning failed, returned pointer is raw malloced
829
830 For strings (not unicodes), the len()th character of the resulting
831 raw buffer is available, but not initialized. Use
832 get_nonmovingbuffer_final_null() instead of get_nonmovingbuffer()
833 to get a regular null-terminated "char *".
821834 """
822835
823836 lldata = llstrtype(data)
824837 count = len(data)
825838
826 pinned = False
827 if rgc.can_move(data):
828 if rgc.pin(data):
829 pinned = True
839 if we_are_translated_to_c() and not rgc.can_move(data):
840 flag = '\x04'
841 else:
842 if we_are_translated_to_c() and rgc.pin(data):
843 flag = '\x05'
830844 else:
831 buf = lltype.malloc(TYPEP.TO, count, flavor='raw')
845 buf = lltype.malloc(TYPEP.TO, count + (TYPEP is CCHARP),
846 flavor='raw')
832847 copy_string_to_raw(lldata, buf, 0, count)
833 return buf, pinned, True
848 return buf, '\x06'
834849 # ^^^ raw malloc used to get a nonmovable copy
835850 #
836 # following code is executed if:
851 # following code is executed after we're translated to C, if:
837852 # - rgc.can_move(data) and rgc.pin(data) both returned true
838853 # - rgc.can_move(data) returned false
839854 data_start = cast_ptr_to_adr(lldata) + \
840855 offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0)
841856
842 return cast(TYPEP, data_start), pinned, False
857 return cast(TYPEP, data_start), flag
843858 # ^^^ already nonmovable. Therefore it's not raw allocated nor
844859 # pinned.
845860 get_nonmovingbuffer._always_inline_ = 'try' # get rid of the returned tuple
846861 get_nonmovingbuffer._annenforceargs_ = [strtype]
847862
848 # (str, char*, bool, bool) -> None
863 @jit.dont_look_inside
864 def get_nonmovingbuffer_final_null(data):
865 tup = get_nonmovingbuffer(data)
866 buf, flag = tup
867 buf[len(data)] = lastchar
868 return tup
869 get_nonmovingbuffer_final_null._always_inline_ = 'try'
870 get_nonmovingbuffer_final_null._annenforceargs_ = [strtype]
871
872 # (str, char*, char) -> None
849873 # Can't inline this because of the raw address manipulation.
850874 @jit.dont_look_inside
851 def free_nonmovingbuffer(data, buf, is_pinned, is_raw):
875 def free_nonmovingbuffer(data, buf, flag):
852876 """
853 Keep 'data' alive and unpin it if it was pinned ('is_pinned' is true).
854 Otherwise free the non-moving copy ('is_raw' is true).
877 Keep 'data' alive and unpin it if it was pinned (flag==\5).
878 Otherwise free the non-moving copy (flag==\6).
855879 """
856 if is_pinned:
880 if flag == '\x05':
857881 rgc.unpin(data)
858 if is_raw:
882 if flag == '\x06':
859883 lltype.free(buf, flavor='raw')
860 # if is_pinned and is_raw are false: data was already nonmovable,
884 # if flag == '\x04': data was already nonmovable,
861885 # we have nothing to clean up
862886 keepalive_until_here(data)
863 free_nonmovingbuffer._annenforceargs_ = [strtype, None, bool, bool]
887 free_nonmovingbuffer._annenforceargs_ = [strtype, None, None]
864888
865889 # int -> (char*, str, int)
866890 # Can't inline this because of the raw address manipulation.
946970
947971 return (str2charp, free_charp, charp2str,
948972 get_nonmovingbuffer, free_nonmovingbuffer,
973 get_nonmovingbuffer_final_null,
949974 alloc_buffer, str_from_buffer, keep_buffer_alive_until_here,
950975 charp2strn, charpsize2str, str2chararray, str2rawmem,
951976 )
952977
953978 (str2charp, free_charp, charp2str,
954 get_nonmovingbuffer, free_nonmovingbuffer,
979 get_nonmovingbuffer, free_nonmovingbuffer, get_nonmovingbuffer_final_null,
955980 alloc_buffer, str_from_buffer, keep_buffer_alive_until_here,
956981 charp2strn, charpsize2str, str2chararray, str2rawmem,
957982 ) = make_string_mappings(str)
958983
959984 (unicode2wcharp, free_wcharp, wcharp2unicode,
960 get_nonmoving_unicodebuffer, free_nonmoving_unicodebuffer,
985 get_nonmoving_unicodebuffer, free_nonmoving_unicodebuffer, __not_usable,
961986 alloc_unicodebuffer, unicode_from_buffer, keep_unicodebuffer_alive_until_here,
962987 wcharp2unicoden, wcharpsize2unicode, unicode2wchararray, unicode2rawmem,
963988 ) = make_string_mappings(unicode)
11931218 def __init__(self, data):
11941219 self.data = data
11951220 def __enter__(self):
1196 self.buf, self.pinned, self.is_raw = get_nonmovingbuffer(self.data)
1221 self.buf, self.flag = get_nonmovingbuffer(self.data)
11971222 return self.buf
11981223 def __exit__(self, *args):
1199 free_nonmovingbuffer(self.data, self.buf, self.pinned, self.is_raw)
1224 free_nonmovingbuffer(self.data, self.buf, self.flag)
1225 __init__._always_inline_ = 'try'
1226 __enter__._always_inline_ = 'try'
1227 __exit__._always_inline_ = 'try'
1228
1229 class scoped_view_charp:
1230 """Returns a 'char *' that (tries to) point inside the given RPython
1231 string (which must not be None). You can replace scoped_str2charp()
1232 with scoped_view_charp() in all places that guarantee that the
1233 content of the 'char[]' array will not be modified.
1234 """
1235 def __init__(self, data):
1236 self.data = data
1237 __init__._annenforceargs_ = [None, annmodel.SomeString(can_be_None=False)]
1238 def __enter__(self):
1239 self.buf, self.flag = get_nonmovingbuffer_final_null(self.data)
1240 return self.buf
1241 def __exit__(self, *args):
1242 free_nonmovingbuffer(self.data, self.buf, self.flag)
12001243 __init__._always_inline_ = 'try'
12011244 __enter__._always_inline_ = 'try'
12021245 __exit__._always_inline_ = 'try'
12051248 def __init__(self, data):
12061249 self.data = data
12071250 def __enter__(self):
1208 self.buf, self.pinned, self.is_raw = get_nonmoving_unicodebuffer(self.data)
1251 self.buf, self.flag = get_nonmoving_unicodebuffer(self.data)
12091252 return self.buf
12101253 def __exit__(self, *args):
1211 free_nonmoving_unicodebuffer(self.data, self.buf, self.pinned, self.is_raw)
1254 free_nonmoving_unicodebuffer(self.data, self.buf, self.flag)
12121255 __init__._always_inline_ = 'try'
12131256 __enter__._always_inline_ = 'try'
12141257 __exit__._always_inline_ = 'try'
647647
648648 @staticmethod
649649 @jit.elidable
650 @signature(types.any(), types.any(), types.int(), types.int(), returns=types.int())
650651 def ll_rfind_char(s, ch, start, end):
651652 if end > len(s.chars):
652653 end = len(s.chars)
12371238 # ____________________________________________________________
12381239
12391240 STR.become(GcStruct('rpy_string', ('hash', Signed),
1240 ('chars', Array(Char, hints={'immutable': True})),
1241 ('chars', Array(Char, hints={'immutable': True,
1242 'extra_item_after_alloc': 1})),
12411243 adtmeths={'malloc' : staticAdtMethod(mallocstr),
12421244 'empty' : staticAdtMethod(emptystrfun),
12431245 'copy_contents' : staticAdtMethod(copy_string_contents),
0 import py
1
2 from rpython.rtyper.lltypesystem import lltype, llmemory
0 import py, os
1
2 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, llarena
33 from rpython.rtyper.lltypesystem.llarena import (arena_malloc, arena_reset,
44 arena_reserve, arena_free, round_up_for_allocation, ArenaError,
55 arena_new_view, arena_shrink_obj, arena_protect, has_protect)
298298 p.x = 125
299299 assert p.x == 125
300300
301 def test_madvise_arena_free():
302 from rpython.rlib import rmmap
303
304 if os.name != 'posix':
305 py.test.skip("posix only")
306 pagesize = llarena.posixpagesize.get()
307 prev = rmmap.madvise_free
308 try:
309 seen = []
310 def my_madvise_free(addr, size):
311 assert lltype.typeOf(addr) == rmmap.PTR
312 seen.append((addr, size))
313 rmmap.madvise_free = my_madvise_free
314 llarena.madvise_arena_free(
315 rffi.cast(llmemory.Address, 123 * pagesize + 1),
316 pagesize * 7 - 2)
317 finally:
318 rmmap.madvise_free = prev
319 assert len(seen) == 1
320 addr, size = seen[0]
321 assert rffi.cast(lltype.Signed, addr) == 124 * pagesize
322 assert size == pagesize * 5
323
301324
302325 class TestStandalone(test_standalone.StandaloneTests):
303326 def test_compiled_arena_protect(self):
515515 def test_nonmovingbuffer(self):
516516 d = 'some cool data that should not move'
517517 def f():
518 buf, is_pinned, is_raw = get_nonmovingbuffer(d)
518 buf, flag = get_nonmovingbuffer(d)
519519 try:
520520 counter = 0
521521 for i in range(len(d)):
523523 counter += 1
524524 return counter
525525 finally:
526 free_nonmovingbuffer(d, buf, is_pinned, is_raw)
526 free_nonmovingbuffer(d, buf, flag)
527527 assert f() == len(d)
528528 fn = self.compile(f, [], gcpolicy='ref')
529529 assert fn() == len(d)
533533 def f():
534534 counter = 0
535535 for n in range(32):
536 buf, is_pinned, is_raw = get_nonmovingbuffer(d)
536 buf, flag = get_nonmovingbuffer(d)
537537 try:
538538 for i in range(len(d)):
539539 if buf[i] == d[i]:
540540 counter += 1
541541 finally:
542 free_nonmovingbuffer(d, buf, is_pinned, is_raw)
542 free_nonmovingbuffer(d, buf, flag)
543543 return counter
544544 fn = self.compile(f, [], gcpolicy='semispace')
545545 # The semispace gc uses raw_malloc for its internal data structs
554554 def f():
555555 counter = 0
556556 for n in range(32):
557 buf, is_pinned, is_raw = get_nonmovingbuffer(d)
557 buf, flag = get_nonmovingbuffer(d)
558558 try:
559559 for i in range(len(d)):
560560 if buf[i] == d[i]:
561561 counter += 1
562562 finally:
563 free_nonmovingbuffer(d, buf, is_pinned, is_raw)
563 free_nonmovingbuffer(d, buf, flag)
564564 return counter
565565 fn = self.compile(f, [], gcpolicy='incminimark')
566566 # The incminimark gc uses raw_malloc for its internal data structs
824824 assert charp2str(p2) == "helLD"
825825 free_charp(p1)
826826 free_charp(p2)
827
828 def test_sign_when_casting_uint_to_larger_int():
829 from rpython.rtyper.lltypesystem import rffi
830 from rpython.rlib.rarithmetic import r_uint32, r_uint64
831 #
832 value = 0xAAAABBBB
833 assert cast(lltype.SignedLongLong, r_uint32(value)) == value
834 if hasattr(rffi, '__INT128_T'):
835 value = 0xAAAABBBBCCCCDDDD
836 assert cast(rffi.__INT128_T, r_uint64(value)) == value
837
838 def test_scoped_view_charp():
839 s = 'bar'
840 with scoped_view_charp(s) as buf:
841 assert buf[0] == 'b'
842 assert buf[1] == 'a'
843 assert buf[2] == 'r'
844 assert buf[3] == '\x00'
235235 return _rtype_template(hop, 'mul_ovf')
236236
237237 def rtype_floordiv(_, hop):
238 return _rtype_call_helper(hop, 'floordiv', [ZeroDivisionError])
238 return _rtype_call_helper(hop, 'py_div', [ZeroDivisionError])
239239 rtype_inplace_floordiv = rtype_floordiv
240240
241241 def rtype_floordiv_ovf(_, hop):
242 return _rtype_call_helper(hop, 'floordiv_ovf', [ZeroDivisionError])
242 return _rtype_call_helper(hop, 'py_div_ovf', [ZeroDivisionError])
243243
244244 # turn 'div' on integers into 'floordiv'
245245 rtype_div = rtype_floordiv
249249 # 'def rtype_truediv' is delegated to the superclass FloatRepr
250250
251251 def rtype_mod(_, hop):
252 return _rtype_call_helper(hop, 'mod', [ZeroDivisionError])
252 return _rtype_call_helper(hop, 'py_mod', [ZeroDivisionError])
253253 rtype_inplace_mod = rtype_mod
254254
255255 def rtype_mod_ovf(_, hop):
256 return _rtype_call_helper(hop, 'mod_ovf', [ZeroDivisionError])
256 return _rtype_call_helper(hop, 'py_mod_ovf', [ZeroDivisionError])
257257
258258 def rtype_xor(_, hop):
259259 return _rtype_template(hop, 'xor')
318318 vlist = hop.inputargs(repr, repr2)
319319 prefix = repr.opprefix
320320
321 if '_ovf' in func or func.startswith(('mod', 'floordiv')):
321 if '_ovf' in func or func.startswith(('py_mod', 'py_div')):
322322 if prefix+func not in ('int_add_ovf', 'int_add_nonneg_ovf',
323323 'int_sub_ovf', 'int_mul_ovf'):
324324 raise TyperError("%r should not be used here any more" % (func,))
352352 any_implicit_exception = True
353353
354354 if not any_implicit_exception:
355 if not func.startswith(('mod', 'floordiv')):
355 if not func.startswith(('py_mod', 'py_div')):
356356 return _rtype_template(hop, func)
357357
358358 repr = hop.r_result
387387 # ---------- floordiv ----------
388388
389389 @jit.oopspec("int.py_div(x, y)")
390 def ll_int_floordiv(x, y):
390 def ll_int_py_div(x, y):
391391 # Python, and RPython, assume that integer division truncates
392392 # towards -infinity. However, in C, integer division truncates
393393 # towards 0. So assuming that, we need to apply a correction
399399 return r + (u >> INT_BITS_1)
400400
401401 @jit.oopspec("int.py_div(x, y)")
402 def ll_int_floordiv_nonnegargs(x, y):
402 def ll_int_py_div_nonnegargs(x, y):
403403 from rpython.rlib.debug import ll_assert
404404 r = llop.int_floordiv(Signed, x, y) # <= truncates like in C
405 ll_assert(r >= 0, "int_floordiv_nonnegargs(): one arg is negative")
405 ll_assert(r >= 0, "int_py_div_nonnegargs(): one arg is negative")
406406 return r
407407
408 def ll_int_floordiv_zer(x, y):
408 def ll_int_py_div_zer(x, y):
409409 if y == 0:
410410 raise ZeroDivisionError("integer division")
411 return ll_int_floordiv(x, y)
412
413 def ll_int_floordiv_ovf(x, y):
411 return ll_int_py_div(x, y)
412
413 def ll_int_py_div_ovf(x, y):
414414 # JIT: intentionally not short-circuited to produce only one guard
415415 # and to remove the check fully if one of the arguments is known
416416 if (x == -sys.maxint - 1) & (y == -1):
417417 raise OverflowError("integer division")
418 return ll_int_floordiv(x, y)
419
420 def ll_int_floordiv_ovf_zer(x, y):
418 return ll_int_py_div(x, y)
419
420 def ll_int_py_div_ovf_zer(x, y):
421421 if y == 0:
422422 raise ZeroDivisionError("integer division")
423 return ll_int_floordiv_ovf(x, y)
423 return ll_int_py_div_ovf(x, y)
424424
425425 @jit.oopspec("int.udiv(x, y)")
426 def ll_uint_floordiv(x, y):
426 def ll_uint_py_div(x, y):
427427 return llop.uint_floordiv(Unsigned, x, y)
428428
429 def ll_uint_floordiv_zer(x, y):
429 def ll_uint_py_div_zer(x, y):
430430 if y == 0:
431431 raise ZeroDivisionError("unsigned integer division")
432 return ll_uint_floordiv(x, y)
432 return ll_uint_py_div(x, y)
433433
434434 if SignedLongLong == Signed:
435 ll_llong_floordiv = ll_int_floordiv
436 ll_llong_floordiv_zer = ll_int_floordiv_zer
437 ll_ullong_floordiv = ll_uint_floordiv
438 ll_ullong_floordiv_zer = ll_uint_floordiv_zer
435 ll_llong_py_div = ll_int_py_div
436 ll_llong_py_div_zer = ll_int_py_div_zer
437 ll_ullong_py_div = ll_uint_py_div
438 ll_ullong_py_div_zer = ll_uint_py_div_zer
439439 else:
440440 @jit.dont_look_inside
441 def ll_llong_floordiv(x, y):
441 def ll_llong_py_div(x, y):
442442 r = llop.llong_floordiv(SignedLongLong, x, y) # <= truncates like in C
443443 p = r * y
444444 if y < 0: u = p - x
445445 else: u = x - p
446446 return r + (u >> LLONG_BITS_1)
447447
448 def ll_llong_floordiv_zer(x, y):
448 def ll_llong_py_div_zer(x, y):
449449 if y == 0:
450450 raise ZeroDivisionError("longlong division")
451 return ll_llong_floordiv(x, y)
451 return ll_llong_py_div(x, y)
452452
453453 @jit.dont_look_inside
454 def ll_ullong_floordiv(x, y):
454 def ll_ullong_py_div(x, y):
455455 return llop.ullong_floordiv(UnsignedLongLong, x, y)
456456
457 def ll_ullong_floordiv_zer(x, y):
457 def ll_ullong_py_div_zer(x, y):
458458 if y == 0:
459459 raise ZeroDivisionError("unsigned longlong division")
460 return ll_ullong_floordiv(x, y)
460 return ll_ullong_py_div(x, y)
461461
462462 @jit.dont_look_inside
463 def ll_lllong_floordiv(x, y):
463 def ll_lllong_py_div(x, y):
464464 r = llop.lllong_floordiv(SignedLongLongLong, x, y) # <= truncates like in C
465465 p = r * y
466466 if y < 0: u = p - x
467467 else: u = x - p
468468 return r + (u >> LLLONG_BITS_1)
469469
470 def ll_lllong_floordiv_zer(x, y):
470 def ll_lllong_py_div_zer(x, y):
471471 if y == 0:
472472 raise ZeroDivisionError("longlonglong division")
473 return ll_lllong_floordiv(x, y)
473 return ll_lllong_py_div(x, y)
474474
475475
476476 # ---------- mod ----------
477477
478478 @jit.oopspec("int.py_mod(x, y)")
479 def ll_int_mod(x, y):
479 def ll_int_py_mod(x, y):
480480 r = llop.int_mod(Signed, x, y) # <= truncates like in C
481481 if y < 0: u = -r
482482 else: u = r
483483 return r + (y & (u >> INT_BITS_1))
484484
485485 @jit.oopspec("int.py_mod(x, y)")
486 def ll_int_mod_nonnegargs(x, y):
486 def ll_int_py_mod_nonnegargs(x, y):
487487 from rpython.rlib.debug import ll_assert
488488 r = llop.int_mod(Signed, x, y) # <= truncates like in C
489 ll_assert(r >= 0, "int_mod_nonnegargs(): one arg is negative")
489 ll_assert(r >= 0, "int_py_mod_nonnegargs(): one arg is negative")
490490 return r
491491
492 def ll_int_mod_zer(x, y):
492 def ll_int_py_mod_zer(x, y):
493493 if y == 0:
494494 raise ZeroDivisionError
495 return ll_int_mod(x, y)
496
497 def ll_int_mod_ovf(x, y):
498 # see comment in ll_int_floordiv_ovf
495 return ll_int_py_mod(x, y)
496
497 def ll_int_py_mod_ovf(x, y):
498 # see comment in ll_int_py_div_ovf
499499 if (x == -sys.maxint - 1) & (y == -1):
500500 raise OverflowError
501 return ll_int_mod(x, y)
502
503 def ll_int_mod_ovf_zer(x, y):
501 return ll_int_py_mod(x, y)
502
503 def ll_int_py_mod_ovf_zer(x, y):
504504 if y == 0:
505505 raise ZeroDivisionError
506 return ll_int_mod_ovf(x, y)
506 return ll_int_py_mod_ovf(x, y)
507507
508508 @jit.oopspec("int.umod(x, y)")
509 def ll_uint_mod(x, y):
509 def ll_uint_py_mod(x, y):
510510 return llop.uint_mod(Unsigned, x, y)
511511
512 def ll_uint_mod_zer(x, y):
512 def ll_uint_py_mod_zer(x, y):
513513 if y == 0:
514514 raise ZeroDivisionError
515 return ll_uint_mod(x, y)
515 return ll_uint_py_mod(x, y)
516516
517517 if SignedLongLong == Signed:
518 ll_llong_mod = ll_int_mod
519 ll_llong_mod_zer = ll_int_mod_zer
520 ll_ullong_mod = ll_uint_mod
521 ll_ullong_mod_zer = ll_uint_mod_zer
518 ll_llong_py_mod = ll_int_py_mod
519 ll_llong_py_mod_zer = ll_int_py_mod_zer
520 ll_ullong_py_mod = ll_uint_py_mod
521 ll_ullong_py_mod_zer = ll_uint_py_mod_zer
522522 else:
523523 @jit.dont_look_inside
524 def ll_llong_mod(x, y):
524 def ll_llong_py_mod(x, y):
525525 r = llop.llong_mod(SignedLongLong, x, y) # <= truncates like in C
526526 if y < 0: u = -r
527527 else: u = r
528528 return r + (y & (u >> LLONG_BITS_1))
529529
530 def ll_llong_mod_zer(x, y):
530 def ll_llong_py_mod_zer(x, y):
531531 if y == 0:
532532 raise ZeroDivisionError
533 return ll_llong_mod(x, y)
533 return ll_llong_py_mod(x, y)
534534
535535 @jit.dont_look_inside
536 def ll_ullong_mod(x, y):
536 def ll_ullong_py_mod(x, y):
537537 return llop.ullong_mod(UnsignedLongLong, x, y)
538538
539 def ll_ullong_mod_zer(x, y):
539 def ll_ullong_py_mod_zer(x, y):
540540 if y == 0:
541541 raise ZeroDivisionError
542542 return llop.ullong_mod(UnsignedLongLong, x, y)
543543
544544 @jit.dont_look_inside
545 def ll_lllong_mod(x, y):
545 def ll_lllong_py_mod(x, y):
546546 r = llop.lllong_mod(SignedLongLongLong, x, y) # <= truncates like in C
547547 if y < 0: u = -r
548548 else: u = r
549549 return r + (y & (u >> LLLONG_BITS_1))
550550
551 def ll_lllong_mod_zer(x, y):
551 def ll_lllong_py_mod_zer(x, y):
552552 if y == 0:
553553 raise ZeroDivisionError
554 return ll_lllong_mod(x, y)
554 return ll_lllong_py_mod(x, y)
555555
556556
557557 # ---------- lshift, neg, abs ----------
413413 if self.s_pbc.can_be_None:
414414 self.descriptions.insert(0, None)
415415 POINTER_TABLE = Array(self.pointer_repr.lowleveltype,
416 hints={'nolength': True})
416 hints={'nolength': True, 'immutable': True})
417417 pointer_table = malloc(POINTER_TABLE, len(self.descriptions),
418418 immortal=True)
419419 for i, desc in enumerate(self.descriptions):
563563 if r_to in r_from._conversion_tables:
564564 return r_from._conversion_tables[r_to]
565565 else:
566 t = malloc(Array(Char, hints={'nolength': True}),
566 t = malloc(Array(Char, hints={'nolength': True, 'immutable': True}),
567567 len(r_from.descriptions), immortal=True)
568568 l = []
569569 for i, d in enumerate(r_from.descriptions):
576576 if l == range(len(r_from.descriptions)):
577577 r = None
578578 else:
579 r = inputconst(Ptr(Array(Char, hints={'nolength': True})), t)
579 r = inputconst(typeOf(t), t)
580580 r_from._conversion_tables[r_to] = r
581581 return r
582582
198198 self.r_baseiter = r_baseiter
199199 self.lowleveltype = r_baseiter.lowleveltype
200200 # only supports for now enumerate() on sequence types whose iterators
201 # have a method ll_getnextindex. It's easy to add one for most
202 # iterator types, but I didn't do it so far.
201 # have a method ll_getnextindex. It could be added for most
202 # iterator types, but it's a bit messy for no clear benefit.
203 if not hasattr(r_baseiter, 'll_getnextindex'):
204 raise TyperError("not implemented for now: enumerate(x) where x "
205 "is not a regular list (got %r)" % (r_baseiter,))
203206 self.ll_getnextindex = r_baseiter.ll_getnextindex
204207
205208 def rtype_next(self, hop):
590590
591591 class __extend__(pairtype(IntegerRepr, AbstractStringRepr)):
592592 def rtype_mul((r_int, r_str), hop):
593 return pair(r_str, r_int).rtype_mul(hop)
593 str_repr = r_str.repr
594 v_int, v_str = hop.inputargs(Signed, str_repr)
595 return hop.gendirectcall(r_str.ll.ll_str_mul, v_str, v_int)
594596 rtype_inplace_mul = rtype_mul
595597
596598
112112 return s
113113 res = self.interpret(g, [])
114114 assert res == 6
115
116 def test_generator_with_unreachable_yields(self):
117 def f(n):
118 if n < 0:
119 yield 42
120 yield n
121 if n < 0:
122 yield 43
123 yield n
124 if n < 0:
125 yield 44
126 def main(n):
127 y = 0
128 for x in f(abs(n)):
129 y += x
130 return y
131 res = self.interpret(main, [-100])
132 assert res == 200
461461 res = interpret(h, [8, 5, 2])
462462 assert res == 99
463463
464 def test_llhelper_multiple_functions():
465 S = GcStruct('S', ('x', Signed), ('y', Signed))
466 def f(s):
467 return s.x - s.y
468 def g(s):
469 return s.x + s.y
470
471 F = Ptr(FuncType([Ptr(S)], Signed))
472
473 myfuncs = [f, g]
474
475 def h(x, y, z):
476 s = malloc(S)
477 s.x = x
478 s.y = y
479 fptr = llhelper(F, myfuncs[z])
480 assert typeOf(fptr) == F
481 return fptr(s)
482
483 res = interpret(h, [80, 5, 0])
484 assert res == 75
485 res = interpret(h, [80, 5, 1])
486 assert res == 85
487
464488
465489 def test_cast_instance_to_base_ptr():
466490 class A:
389389 res = self.interpret(f, [sys.maxint])
390390 assert res == 0
391391
392 def test_int_floordiv_nonnegargs(self):
392 def test_int_py_div_nonnegargs(self):
393393 def f(x, y):
394394 assert x >= 0
395395 assert y >= 0
397397 res = self.interpret(f, [1234567, 123])
398398 assert res == 1234567 // 123
399399
400 def test_int_mod_nonnegargs(self):
400 def test_int_py_mod_nonnegargs(self):
401401 def f(x, y):
402402 assert x >= 0
403403 assert y >= 0
20112011 e = py.test.raises(ValueError, self.interpret, f, [3])
20122012 assert str(e.value).startswith(r"exit case '\xff' not found")
20132013
2014 @py.test.mark.parametrize('limit', [3, 5])
2015 def test_conversion_table(self, limit):
2016 # with limit==3, check conversion from Char to Ptr(Func).
2017 # with limit>3, check conversion from Char to Char.
2018 def f1():
2019 return 111
2020 def f2():
2021 return 222
2022 def f3():
2023 return 333
2024 def g(n):
2025 if n & 1:
2026 return f1
2027 else:
2028 return f2
2029 def f(n):
2030 x = g(n) # can be f1 or f2
2031 if n > 10:
2032 x = f3 # now can be f1 or f2 or f3
2033 return x()
2034
2035 from rpython.config.translationoption import get_combined_translation_config
2036 self.config = get_combined_translation_config(translating=True)
2037 self.config.translation.withsmallfuncsets = limit
2038 assert self.interpret(f, [3]) == 111
2039 assert self.interpret(f, [4]) == 222
2040 assert self.interpret(f, [13]) == 333
2041 assert self.interpret(f, [14]) == 333
2042
2043
20142044 def test_smallfuncsets_basic():
20152045 from rpython.translator.translator import TranslationContext, graphof
20162046 from rpython.config.translationoption import get_combined_translation_config
219219 const = self.const
220220 def fn(i, mul):
221221 s = ["", "a", "aba"][i]
222 return s * mul
222 return s * mul + mul * s
223223 for i in xrange(3):
224224 for m in [0, 1, 4]:
225 res1 = fn(i, m)
225226 res = self.interpret(fn, [i, m])
226 assert self.ll_to_string(res) == fn(i, m)
227 assert self.ll_to_string(res) == res1
227228
228229 def test_is_none(self):
229230 const = self.const
157157
158158 @jit.elidable
159159 def offset2lineno(c, stopat):
160 # even position in lnotab denote byte increments, odd line increments.
161 # see dis.findlinestarts in the python std. library for more details
160162 tab = c.co_lnotab
161163 line = c.co_firstlineno
162164 addr = 0
11 from rpython.translator.backendopt import inline
22 from rpython.translator.backendopt.malloc import remove_mallocs
33 from rpython.translator.backendopt.constfold import constant_fold_graph
4 from rpython.translator.backendopt.constfold import replace_we_are_jitted
45 from rpython.translator.backendopt.stat import print_statistics
56 from rpython.translator.backendopt.merge_if_blocks import merge_if_blocks
67 from rpython.translator import simplify
3536 # inline_threshold, mallocs
3637 # merge_if_blocks, constfold, heap2stack
3738 # clever_malloc_removal, remove_asserts
39 # replace_we_are_jitted
3840
3941 config = translator.config.translation.backendopt.copy(as_default=True)
4042 config.set(**kwds)
4749 if config.print_statistics:
4850 print "before optimizations:"
4951 print_statistics(translator.graphs[0], translator, "per-graph.txt")
52
53 if config.replace_we_are_jitted:
54 for graph in graphs:
55 replace_we_are_jitted(graph)
5056
5157 if config.remove_asserts:
5258 constfold(config, graphs)
275275 rewire_links(splitblocks, graph)
276276 if not diffused and not splitblocks:
277277 break # finished
278
279 def replace_symbolic(graph, symbolic, value):
280 result = False
281 for block in graph.iterblocks():
282 for op in block.operations:
283 for i, arg in enumerate(op.args):
284 if isinstance(arg, Constant) and arg.value is symbolic:
285 op.args[i] = value
286 result = True
287 if block.exitswitch is symbolic:
288 block.exitswitch = value
289 result = True
290 return result
291
292 def replace_we_are_jitted(graph):
293 from rpython.rlib import jit
294 replacement = Constant(0)
295 replacement.concretetype = lltype.Signed
296 did_replacement = replace_symbolic(graph, jit._we_are_jitted, replacement)
297 if did_replacement:
298 constant_fold_graph(graph)
299 return did_replacement
3535 raise FinalizerError(msg)
3636 else:
3737 result = self.analyze_direct_call(graph)
38 if result is self.top_result():
39 log.red('old-style non-light finalizer: %r' % (graph,))
38 #if result is self.top_result():
39 # log.red('old-style non-light finalizer: %r' % (graph,))
4040 return result
4141
4242 def analyze_simple_operation(self, op, graphinfo):
288288 llinterp = LLInterpreter(t.rtyper)
289289 res = llinterp.eval_graph(later_graph, [10])
290290 assert res == 1
291
292 def test_replace_we_are_jitted(self):
293 from rpython.rlib import jit
294 def f():
295 if jit.we_are_jitted():
296 return 1
297 return 2 + jit.we_are_jitted()
298
299 t = self.translateopt(f, [])
300 graph = graphof(t, f)
301 # by default, replace_we_are_jitted is off
302 assert graph.startblock.operations[0].args[0].value is jit._we_are_jitted
303
304 t = self.translateopt(f, [], replace_we_are_jitted=True)
305 graph = graphof(t, f)
306 assert graph.startblock.exits[0].args[0].value == 2
66 from rpython.rtyper import rclass
77 from rpython.rlib import objectmodel
88 from rpython.translator.backendopt.constfold import constant_fold_graph
9 from rpython.translator.backendopt.constfold import replace_we_are_jitted
910 from rpython.conftest import option
1011
1112 def get_graph(fn, signature):
342343 merge_if_blocks.merge_if_blocks_once(graph)
343344 constant_fold_graph(graph)
344345 check_graph(graph, [], 66, t)
346
347 def test_replace_we_are_jitted():
348 from rpython.rlib import jit
349 def fn():
350 if jit.we_are_jitted():
351 return 1
352 return 2 + jit.we_are_jitted()
353 graph, t = get_graph(fn, [])
354 result = replace_we_are_jitted(graph)
355 assert result
356 checkgraph(graph)
357 # check shape of graph
358 assert len(graph.startblock.operations) == 0
359 assert graph.startblock.exitswitch is None
360 assert graph.startblock.exits[0].target.exits[0].args[0].value == 2
11 from rpython.translator.c.support import cdecl
22 from rpython.translator.c.support import llvalue_from_constant, gen_assignments
33 from rpython.translator.c.support import c_string_constant, barebonearray
4 from rpython.flowspace.model import Variable, Constant
4 from rpython.flowspace.model import Variable, Constant, mkentrymap
55 from rpython.rtyper.lltypesystem.lltype import (Ptr, Void, Bool, Signed, Unsigned,
66 SignedLongLong, Float, UnsignedLongLong, Char, UniChar, ContainerType,
77 Array, FixedSizeArray, ForwardReference, FuncType)
172172
173173 def cfunction_body(self):
174174 graph = self.graph
175 yield 'goto block0;' # to avoid a warning "this label is not used"
176
177 # generate the body of each block
175
176 # Locate blocks with a single predecessor, which can be written
177 # inline in place of a "goto":
178 entrymap = mkentrymap(graph)
179 self.inlinable_blocks = {
180 block for block in entrymap if len(entrymap[block]) == 1}
181
182 yield ''
183 for line in self.gen_goto(graph.startblock):
184 yield line
185
186 # Only blocks left are those that have more than one predecessor.
178187 for block in graph.iterblocks():
188 if block in self.inlinable_blocks:
189 continue
190 for line in self.gen_block(block):
191 yield line
192
193 def gen_block(self, block):
194 if 1: # (preserve indentation)
179195 myblocknum = self.blocknum[block]
180 yield ''
181 yield 'block%d:' % myblocknum
196 if block in self.inlinable_blocks:
197 # debug comment
198 yield '/* block%d: (inlined) */' % myblocknum
199 else:
200 yield 'block%d:' % myblocknum
182201 if block in self.innerloops:
183202 for line in self.gen_while_loop_hack(block):
184203 yield line
185 continue
204 return
186205 for i, op in enumerate(block.operations):
187206 for line in self.gen_op(op):
188207 yield line
193212 if self.exception_policy != "exc_helper":
194213 yield 'RPY_DEBUG_RETURN();'
195214 yield 'return %s;' % retval
196 continue
215 return
197216 elif block.exitswitch is None:
198217 # single-exit block
199218 assert len(block.exits) == 1
255274 assignments.append((a2typename, dest, src))
256275 for line in gen_assignments(assignments):
257276 yield line
258 label = 'block%d' % self.blocknum[link.target]
259 if link.target in self.innerloops:
260 loop = self.innerloops[link.target]
277 for line in self.gen_goto(link.target, link):
278 yield line
279
280 def gen_goto(self, target, link=None):
281 """Recursively expand block with inlining or goto.
282
283 Blocks that have only one predecessor are inlined directly, all others
284 are reached via goto.
285 """
286 label = 'block%d' % self.blocknum[target]
287 if target in self.innerloops:
288 loop = self.innerloops[target]
261289 if link is loop.links[-1]: # link that ends a loop
262290 label += '_back'
263 yield 'goto %s;' % label
291 if target in self.inlinable_blocks:
292 for line in self.gen_block(target):
293 yield line
294 else:
295 yield 'goto %s;' % label
264296
265297 def gen_op(self, op):
266298 macro = 'OP_%s' % op.opname.upper()
210210 # See module/thread/test/test_rthread.py
211211 compile_extra=['-DPYPY_USING_BOEHM_GC'],
212212 ))
213
214 gct = self.db.gctransformer
215 gct.finalizer_triggers = tuple(gct.finalizer_triggers) # stop changing
216 sourcelines = ['']
217 for trig in gct.finalizer_triggers:
218 sourcelines.append('RPY_EXTERN void %s(void);' % (
219 self.db.get(trig),))
220 sourcelines.append('')
221 sourcelines.append('void (*boehm_fq_trigger[])(void) = {')
222 for trig in gct.finalizer_triggers:
223 sourcelines.append('\t%s,' % (self.db.get(trig),))
224 sourcelines.append('\tNULL')
225 sourcelines.append('};')
226 sourcelines.append('struct boehm_fq_s *boehm_fq_queues[%d];' % (
227 len(gct.finalizer_triggers) or 1,))
228 sourcelines.append('')
229 eci = eci.merge(ExternalCompilationInfo(
230 separate_module_sources=['\n'.join(sourcelines)]))
213231
214232 return eci
215233
421421 mk.definition('PROFOPT', profopt)
422422
423423 rules = [
424 ('clean', '', 'rm -f $(OBJECTS) $(DEFAULT_TARGET) $(TARGET) $(GCMAPFILES) $(ASMFILES) *.gc?? ../module_cache/*.gc??'),
425 ('clean_noprof', '', 'rm -f $(OBJECTS) $(DEFAULT_TARGET) $(TARGET) $(GCMAPFILES) $(ASMFILES)'),
426424 ('debug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT" debug_target'),
427425 ('debug_exc', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DDO_LOG_EXC" debug_target'),
428426 ('debug_mem', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DPYPY_USE_TRIVIAL_MALLOC" debug_target'),
429427 ('llsafer', '', '$(MAKE) CFLAGS="-O2 -DRPY_LL_ASSERT" $(DEFAULT_TARGET)'),
430428 ('lldebug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DRPY_LL_ASSERT" debug_target'),
431 ('lldebug0','', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -O0 -DMAX_STACK_SIZE=8192000 -DRPY_ASSERT -DRPY_LL_ASSERT" debug_target'),
432429 ('profile', '', '$(MAKE) CFLAGS="-g -O1 -pg $(CFLAGS) -fno-omit-frame-pointer" LDFLAGS="-pg $(LDFLAGS)" $(DEFAULT_TARGET)'),
433430 ]
434431 if self.has_profopt():
442439 for rule in rules:
443440 mk.rule(*rule)
444441
442 if self.translator.platform.name == 'msvc':
443 mk.rule('lldebug0','', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -Od -DMAX_STACK_SIZE=8192000 -DRPY_ASSERT -DRPY_LL_ASSERT" debug_target'),
444 wildcards = '..\*.obj ..\*.pdb ..\*.lib ..\*.dll ..\*.manifest ..\*.exp *.pch'
445 cmd = r'del /s %s $(DEFAULT_TARGET) $(TARGET) $(GCMAPFILES) $(ASMFILES)' % wildcards
446 mk.rule('clean', '', cmd + ' *.gc?? ..\module_cache\*.gc??')
447 mk.rule('clean_noprof', '', cmd)
448 else:
449 mk.rule('lldebug0','', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -O0 -DMAX_STACK_SIZE=8192000 -DRPY_ASSERT -DRPY_LL_ASSERT" debug_target'),
450 mk.rule('clean', '', 'rm -f $(OBJECTS) $(DEFAULT_TARGET) $(TARGET) $(GCMAPFILES) $(ASMFILES) *.gc?? ../module_cache/*.gc??')
451 mk.rule('clean_noprof', '', 'rm -f $(OBJECTS) $(DEFAULT_TARGET) $(TARGET) $(GCMAPFILES) $(ASMFILES)')
452
445453 #XXX: this conditional part is not tested at all
446454 if self.config.translation.gcrootfinder == 'asmgcc':
447455 if self.translator.platform.name == 'msvc':
506514 else:
507515 mk.definition('DEBUGFLAGS', '-O1 -g')
508516 if self.translator.platform.name == 'msvc':
509 mk.rule('debug_target', '$(DEFAULT_TARGET)', 'rem')
517 mk.rule('debug_target', '$(DEFAULT_TARGET) $(WTARGET)', 'rem')
510518 else:
511519 mk.rule('debug_target', '$(DEFAULT_TARGET)', '#')
512520 mk.write()
252252 yield '\t' + cdecl(typename, fname) + ';'
253253 if not self.ARRAY._hints.get('nolength', False):
254254 yield '\tlong length;'
255 varlength = self.varlength
256 if varlength is not None:
257 varlength += self.ARRAY._hints.get('extra_item_after_alloc', 0)
255258 line = '%s;' % cdecl(self.itemtypename,
256 'items[%s]' % deflength(self.varlength))
259 'items[%s]' % deflength(varlength))
257260 if self.ARRAY.OF is Void: # strange
258261 line = '/* array of void */'
259262 if self.ARRAY._hints.get('nolength', False):
105105 #define PYPY_X86_CHECK_SSE2_DEFINED
106106 RPY_EXTERN void pypy_x86_check_sse2(void);
107107 #endif
108
109
110 #define RPy_YieldProcessor() asm("pause")
55 asm volatile("rdtsc" : "=a"(_rax), "=d"(_rdx)); \
66 val = (_rdx << 32) | _rax; \
77 } while (0)
8
9
10 #define RPy_YieldProcessor() asm("pause")
2626 # include "forwarddecl.h"
2727 # endif
2828
29 #if defined(MS_WINDOWS) && defined(RPY_SANDBOXED)
29 #if defined(MS_WINDOWS)
3030 # include <stdio.h>
3131 # include <fcntl.h>
3232 # include <io.h>
6262 char *errmsg;
6363 int i, exitcode;
6464
65 #if defined(MS_WINDOWS) && defined(RPY_SANDBOXED)
65 #if defined(MS_WINDOWS)
6666 _setmode(0, _O_BINARY);
6767 _setmode(1, _O_BINARY);
68 _setmode(2, _O_BINARY);
6869 #endif
6970
7071 #ifdef RPY_WITH_GIL
3333 #define OP_CAST_FLOAT_TO_UINT(x,r) r = (Unsigned)(x)
3434 #define OP_CAST_INT_TO_FLOAT(x,r) r = (double)(x)
3535 #define OP_CAST_UINT_TO_FLOAT(x,r) r = (double)(x)
36 #define OP_CAST_LONGLONG_TO_FLOAT(x,r) r = (double)(x)
37 #define OP_CAST_ULONGLONG_TO_FLOAT(x,r) r = (double)(x)
36 #define OP_CAST_LONGLONG_TO_FLOAT(x,r) r = rpy_cast_longlong_to_float(x)
37 #define OP_CAST_ULONGLONG_TO_FLOAT(x,r) r = rpy_cast_ulonglong_to_float(x)
3838 #define OP_CAST_BOOL_TO_FLOAT(x,r) r = (double)(x)
39
40 #ifdef _WIN32
41 /* The purpose of these two functions is to work around a MSVC bug.
42 The expression '(double)131146795334735160LL' will lead to bogus
43 rounding, but apparently everything is fine if we write instead
44 rpy_cast_longlong_to_float(131146795334735160LL). Tested with
45 MSVC 2008. Note that even if the two functions contain just
46 'return (double)x;' it seems to work on MSVC 2008, but I don't
47 trust that there are no other corner cases.
48 http://stackoverflow.com/questions/33829101/incorrect-double-to-long-conversion
49 */
50 static _inline double rpy_cast_longlong_to_float(long long x)
51 {
52 unsigned int lo = (unsigned int)x;
53 double result = lo;
54 result += ((int)(x >> 32)) * 4294967296.0;
55 return result;
56 }
57 static _inline double rpy_cast_ulonglong_to_float(unsigned long long x)
58 {
59 unsigned int lo = (unsigned int)x;
60 double result = lo;
61 result += ((unsigned int)(x >> 32)) * 4294967296.0;
62 return result;
63 }
64 #else
65 # define rpy_cast_longlong_to_float(x) ((double)(x))
66 # define rpy_cast_ulonglong_to_float(x) ((double)(x))
67 #endif
3968
4069 #ifdef HAVE_LONG_LONG
4170 #define OP_CAST_FLOAT_TO_LONGLONG(x,r) r = (long long)(x)
120120 #define OP_LLONG_LSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, PYPY_LONGLONG_BIT); \
121121 r = (long long)(((unsigned long long)(x)) << (y))
122122 #define OP_LLLONG_LSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, 128); \
123 r = (__int128)(((unsigned __int128)(x)) << (y))
123 r = (__int128_t)(((__uint128_t)(x)) << (y))
124124
125125 #define OP_UINT_LSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, PYPY_LONG_BIT); \
126126 r = (x) << (y)
156156 #define OP_CAST_UINT_TO_INT(x,r) r = (Signed)(x)
157157 #define OP_CAST_INT_TO_UINT(x,r) r = (Unsigned)(x)
158158 #define OP_CAST_INT_TO_LONGLONG(x,r) r = (long long)(x)
159 #define OP_CAST_INT_TO_LONGLONGLONG(x,r) r = (__int128)(x)
159 #define OP_CAST_INT_TO_LONGLONGLONG(x,r) r = (__int128_t)(x)
160160 #define OP_CAST_CHAR_TO_INT(x,r) r = (Signed)((unsigned char)(x))
161161 #define OP_CAST_INT_TO_CHAR(x,r) r = (char)(x)
162162 #define OP_CAST_PTR_TO_INT(x,r) r = (Signed)(x) /* XXX */
7272
7373 #ifdef PYPY_USING_BOEHM_GC
7474
75 struct boehm_fq_s {
76 void *obj;
77 struct boehm_fq_s *next;
78 };
79 RPY_EXTERN void (*boehm_fq_trigger[])(void);
80
7581 int boehm_gc_finalizer_lock = 0;
7682 void boehm_gc_finalizer_notifier(void)
7783 {
84 int i;
85
7886 boehm_gc_finalizer_lock++;
7987 while (GC_should_invoke_finalizers()) {
8088 if (boehm_gc_finalizer_lock > 1) {
8593 }
8694 GC_invoke_finalizers();
8795 }
96
97 i = 0;
98 while (boehm_fq_trigger[i])
99 boehm_fq_trigger[i++]();
100
88101 boehm_gc_finalizer_lock--;
89102 }
90103
98111 GC_finalizer_notifier = &boehm_gc_finalizer_notifier;
99112 GC_finalize_on_demand = 1;
100113 GC_set_warn_proc(mem_boehm_ignore);
114 }
115
116 void boehm_fq_callback(void *obj, void *rawfqueue)
117 {
118 struct boehm_fq_s **fqueue = rawfqueue;
119 struct boehm_fq_s *node = GC_malloc(sizeof(void *) * 2);
120 if (!node)
121 return; /* ouch, too bad */
122 node->obj = obj;
123 node->next = *fqueue;
124 *fqueue = node;
125 }
126
127 void *boehm_fq_next_dead(struct boehm_fq_s **fqueue)
128 {
129 struct boehm_fq_s *node = *fqueue;
130 if (node != NULL) {
131 *fqueue = node->next;
132 return node->obj;
133 }
134 else
135 return NULL;
101136 }
102137 #endif /* BOEHM GC */
103138
103103 RPY_EXTERN int boehm_gc_finalizer_lock;
104104 RPY_EXTERN void boehm_gc_startup_code(void);
105105 RPY_EXTERN void boehm_gc_finalizer_notifier(void);
106 struct boehm_fq_s;
107 RPY_EXTERN struct boehm_fq_s *boehm_fq_queues[];
108 RPY_EXTERN void (*boehm_fq_trigger[])(void);
109 RPY_EXTERN void boehm_fq_callback(void *, void *);
110 RPY_EXTERN void *boehm_fq_next_dead(struct boehm_fq_s **);
106111
107112 #define OP_GC__DISABLE_FINALIZERS(r) boehm_gc_finalizer_lock++
108113 #define OP_GC__ENABLE_FINALIZERS(r) (boehm_gc_finalizer_lock--, \
109114 boehm_gc_finalizer_notifier())
110115
111 #define OP_GC_FQ_REGISTER(tag, obj, r) /* ignored so far */
112 #define OP_GC_FQ_NEXT_DEAD(tag, r) (r = NULL)
116 #define OP_BOEHM_FQ_REGISTER(tagindex, obj, r) \
117 GC_REGISTER_FINALIZER(obj, boehm_fq_callback, \
118 boehm_fq_queues + tagindex, NULL, NULL)
119 #define OP_BOEHM_FQ_NEXT_DEAD(tagindex, r) \
120 r = boehm_fq_next_dead(boehm_fq_queues + tagindex)
113121
114122 #endif /* PYPY_USING_BOEHM_GC */
115123
1717 #define _LARGEFILE_SOURCE 1
1818 /* Define on NetBSD to activate all library features */
1919 #define _NETBSD_SOURCE 1
20 /* Define to activate features from IEEE Stds 1003.1-2001 */
20 /* Define to activate features from IEEE Stds 1003.1-2008 */
2121 #ifndef _POSIX_C_SOURCE
22 # define _POSIX_C_SOURCE 200112L
22 # define _POSIX_C_SOURCE 200809L
2323 #endif
2424 /* Define on FreeBSD to activate all library features */
2525 #define __BSD_VISIBLE 1
4343 */
4444 long rpy_fastgil = 0;
4545 static long rpy_waiting_threads = -42; /* GIL not initialized */
46 static volatile int rpy_early_poll_n = 0;
4647 static mutex1_t mutex_gil_stealer;
4748 static mutex2_t mutex_gil;
4849
6566 }
6667 }
6768
69 static void check_and_save_old_fastgil(long old_fastgil)
70 {
71 assert(RPY_FASTGIL_LOCKED(rpy_fastgil));
72
73 #ifdef PYPY_USE_ASMGCC
74 if (old_fastgil != 0) {
75 /* this case only occurs from the JIT compiler */
76 struct pypy_ASM_FRAMEDATA_HEAD0 *new =
77 (struct pypy_ASM_FRAMEDATA_HEAD0 *)old_fastgil;
78 struct pypy_ASM_FRAMEDATA_HEAD0 *root = &pypy_g_ASM_FRAMEDATA_HEAD;
79 struct pypy_ASM_FRAMEDATA_HEAD0 *next = root->as_next;
80 new->as_next = next;
81 new->as_prev = root;
82 root->as_next = new;
83 next->as_prev = new;
84 }
85 #else
86 assert(old_fastgil == 0);
87 #endif
88 }
89
90 #define RPY_GIL_POKE_MIN 40
91 #define RPY_GIL_POKE_MAX 400
92
6893 void RPyGilAcquireSlowPath(long old_fastgil)
6994 {
7095 /* Acquires the GIL. This assumes that we already did:
78103 }
79104 else {
80105 /* Otherwise, another thread is busy with the GIL. */
106 int n;
107 long old_waiting_threads;
81108
82109 if (rpy_waiting_threads < 0) {
83110 /* <arigo> I tried to have RPyGilAllocate() called from
97124 /* Register me as one of the threads that is actively waiting
98125 for the GIL. The number of such threads is found in
99126 rpy_waiting_threads. */
100 atomic_increment(&rpy_waiting_threads);
127 old_waiting_threads = atomic_increment(&rpy_waiting_threads);
128
129 /* Early polling: before entering the waiting queue, we check
130 a certain number of times if the GIL becomes free. The
131 motivation for this is issue #2341. Note that we do this
132 polling even if there are already other threads in the
133 queue, and one of thesee threads is the stealer. This is
134 because the stealer is likely sleeping right now. There
135 are use cases where the GIL will really be released very
136 soon after RPyGilAcquireSlowPath() is called, so it's worth
137 always doing this check.
138
139 To avoid falling into bad cases, we "randomize" the number
140 of iterations: we loop N times, where N is choosen between
141 RPY_GIL_POKE_MIN and RPY_GIL_POKE_MAX.
142 */
143 n = rpy_early_poll_n * 2 + 1;
144 while (n >= RPY_GIL_POKE_MAX)
145 n -= (RPY_GIL_POKE_MAX - RPY_GIL_POKE_MIN);
146 rpy_early_poll_n = n;
147 while (n >= 0) {
148 n--;
149 if (old_waiting_threads != rpy_waiting_threads) {
150 /* If the number changed, it is because another thread
151 entered or left this function. In that case, stop
152 this loop: if another thread left it means the GIL
153 has been acquired by that thread; if another thread
154 entered there is no point in running the present
155 loop twice. */
156 break;
157 }
158 RPy_YieldProcessor();
159 RPy_CompilerMemoryBarrier();
160
161 if (!RPY_FASTGIL_LOCKED(rpy_fastgil)) {
162 old_fastgil = pypy_lock_test_and_set(&rpy_fastgil, 1);
163 if (!RPY_FASTGIL_LOCKED(old_fastgil)) {
164 /* We got the gil before entering the waiting
165 queue. In case there are other threads waiting
166 for the GIL, wake up the stealer thread now and
167 go to the waiting queue anyway, for fairness.
168 This will fall through if there are no other
169 threads waiting.
170 */
171 check_and_save_old_fastgil(old_fastgil);
172 mutex2_unlock(&mutex_gil);
173 break;
174 }
175 }
176 }
101177
102178 /* Enter the waiting queue from the end. Assuming a roughly
103179 first-in-first-out order, this will nicely give the threads
108184
109185 /* We are now the stealer thread. Steals! */
110186 while (1) {
187 /* Busy-looping here. Try to look again if 'rpy_fastgil' is
188 released.
189 */
190 if (!RPY_FASTGIL_LOCKED(rpy_fastgil)) {
191 old_fastgil = pypy_lock_test_and_set(&rpy_fastgil, 1);
192 if (!RPY_FASTGIL_LOCKED(old_fastgil))
193 /* yes, got a non-held value! Now we hold it. */
194 break;
195 }
111196 /* Sleep for one interval of time. We may be woken up earlier
112197 if 'mutex_gil' is released.
113198 */
118203 old_fastgil = 0;
119204 break;
120205 }
121
122 /* Busy-looping here. Try to look again if 'rpy_fastgil' is
123 released.
124 */
125 if (!RPY_FASTGIL_LOCKED(rpy_fastgil)) {
126 old_fastgil = pypy_lock_test_and_set(&rpy_fastgil, 1);
127 if (!RPY_FASTGIL_LOCKED(old_fastgil))
128 /* yes, got a non-held value! Now we hold it. */
129 break;
130 }
131 /* Otherwise, loop back. */
206 /* Loop back. */
132207 }
133208 atomic_decrement(&rpy_waiting_threads);
134209 mutex2_loop_stop(&mutex_gil);
135210 mutex1_unlock(&mutex_gil_stealer);
136211 }
137 assert(RPY_FASTGIL_LOCKED(rpy_fastgil));
138
139 #ifdef PYPY_USE_ASMGCC
140 if (old_fastgil != 0) {
141 /* this case only occurs from the JIT compiler */
142 struct pypy_ASM_FRAMEDATA_HEAD0 *new =
143 (struct pypy_ASM_FRAMEDATA_HEAD0 *)old_fastgil;
144 struct pypy_ASM_FRAMEDATA_HEAD0 *root = &pypy_g_ASM_FRAMEDATA_HEAD;
145 struct pypy_ASM_FRAMEDATA_HEAD0 *next = root->as_next;
146 new->as_next = next;
147 new->as_prev = root;
148 root->as_next = new;
149 next->as_prev = new;
150 }
151 #else
152 assert(old_fastgil == 0);
153 #endif
212 check_and_save_old_fastgil(old_fastgil);
154213 }
155214
156215 long RPyGilYieldThread(void)
257257 //#define pypy_lock_test_and_set(ptr, value) see thread_nt.h
258258 #define atomic_increment(ptr) InterlockedIncrement(ptr)
259259 #define atomic_decrement(ptr) InterlockedDecrement(ptr)
260 #ifdef YieldProcessor
261 # define RPy_YieldProcessor() YieldProcessor()
262 #else
263 # define RPy_YieldProcessor() __asm { rep nop }
264 #endif
265 #define RPy_CompilerMemoryBarrier() _ReadWriteBarrier()
260266
261267 #include "src/thread_gil.c"
551551 }
552552
553553 //#define pypy_lock_test_and_set(ptr, value) see thread_pthread.h
554 #define atomic_increment(ptr) __sync_fetch_and_add(ptr, 1)
555 #define atomic_decrement(ptr) __sync_fetch_and_sub(ptr, 1)
554 #define atomic_increment(ptr) __sync_add_and_fetch(ptr, 1)
555 #define atomic_decrement(ptr) __sync_sub_and_fetch(ptr, 1)
556 #define RPy_CompilerMemoryBarrier() asm("":::"memory")
556557 #define HAVE_PTHREAD_ATFORK 1
557558
559 #include "src/asm.h" /* for RPy_YieldProcessor() */
560 #ifndef RPy_YieldProcessor
561 # define RPy_YieldProcessor() /* nothing */
562 #endif
563
558564 #include "src/thread_gil.c"
392392 assert res[3] == compute_hash(d)
393393 assert res[4] == compute_hash(("Hi", None, (7.5, 2, d)))
394394
395 def test_finalizer_queue_is_at_least_ignored(self):
395 def test_finalizer_queue(self):
396396 class A(object):
397 pass
397 def __init__(self, i):
398 self.i = i
399 class Glob:
400 triggered = 0
401 glob = Glob()
398402 class FQ(rgc.FinalizerQueue):
399403 Class = A
404 triggered = 0
400405 def finalizer_trigger(self):
401 debug.debug_print("hello!") # not called so far
406 glob.triggered += 1
402407 fq = FQ()
403408 #
404409 def fn():
405 fq.register_finalizer(A())
406 rgc.collect()
407 rgc.collect()
408 fq.next_dead()
410 for i in range(1000):
411 fq.register_finalizer(A(i))
412 rgc.collect()
413 rgc.collect()
414 if glob.triggered == 0:
415 print "not triggered!"
416 return 50
417 seen = {}
418 while True:
419 a = fq.next_dead()
420 if a is None:
421 break
422 assert a.i not in seen
423 seen[a.i] = True
424 if len(seen) < 500:
425 print "seen only %d!" % len(seen)
426 return 51
409427 return 42
410428
411429 f = self.getcompiled(fn)
00 import ctypes
1 import re
12 from collections import OrderedDict
23
34 import py
1213 from rpython.rtyper.lltypesystem.rstr import STR
1314 from rpython.tool.nullpath import NullPyPathLocal
1415 from rpython.translator.c import genc
16 from rpython.translator.backendopt.merge_if_blocks import merge_if_blocks
1517 from rpython.translator.interactive import Translation
1618 from rpython.translator.translator import TranslationContext, graphof
1719
603605 else:
604606 assert 0, "the call was not found in the C source"
605607 assert 'PYPY_INHIBIT_TAIL_CALL();' in lines[i+1]
608
609 def get_generated_c_source(fn, types):
610 """Return the generated C source for fn."""
611 t = Translation(fn, types, backend="c")
612 t.annotate()
613 merge_if_blocks(t.driver.translator.graphs[0])
614 c_filename_path = t.source_c()
615 return t.driver.cbuilder.c_source_filename.join('..',
616 'rpython_translator_c_test.c').read()
617
618 def test_generated_c_source_no_gotos():
619 # We want simple functions to have no indirection/goto.
620 # Instead, PyPy can inline blocks when they aren't reused.
621
622 def main(x):
623 return x + 1
624
625 c_src = get_generated_c_source(main, [int])
626 assert 'goto' not in c_src
627 assert not re.search(r'block\w*:(?! \(inlined\))', c_src)
0 import py
0 import py, random
11 from rpython.rtyper.lltypesystem.lltype import *
22 from rpython.rtyper.lltypesystem import rffi
33 from rpython.translator.c.test.test_genc import compile
253253 res1 = fn(1)
254254 res2 = fn(0)
255255 assert res1 == res2
256
257 def test_null_padding(self):
258 py.test.skip("we no longer pad our RPython strings with a final NUL")
259 from rpython.rtyper.lltypesystem import llmemory
260 from rpython.rtyper.lltypesystem import rstr
261 chars_offset = llmemory.FieldOffset(rstr.STR, 'chars') + \
262 llmemory.ArrayItemsOffset(rstr.STR.chars)
263 # sadly, there's no way of forcing this to fail if the strings
264 # are allocated in a region of memory such that they just
265 # happen to get a NUL byte anyway :/ (a debug build will
266 # always fail though)
267 def trailing_byte(s):
268 adr_s = llmemory.cast_ptr_to_adr(s)
269 return (adr_s + chars_offset).char[len(s)]
270 def f(x):
271 r = 0
272 for i in range(x):
273 r += ord(trailing_byte(' '*(100-x*x)))
274 return r
275 fn = self.getcompiled(f, [int])
276 res = fn(10)
277 assert res == 0
278256
279257 def test_cast_primitive(self):
280258 def f(x):
10221000 assert fn(r_longlong(1)) == True
10231001 assert fn(r_longlong(256)) == True
10241002 assert fn(r_longlong(2**32)) == True
1003
1004 def test_extra_item_after_alloc(self):
1005 from rpython.rlib import rgc
1006 from rpython.rtyper.lltypesystem import lltype
1007 from rpython.rtyper.lltypesystem import rstr
1008 # all STR objects should be allocated with enough space for one
1009 # extra char. Check this for prebuilt strings, and for dynamically
1010 # allocated ones with the default GC for tests. Use strings of 8,
1011 # 16 and 24 chars because if the extra char is missing, writing to it
1012 # is likely to cause corruption in nearby structures.
1013 sizes = [random.choice([8, 16, 24]) for i in range(100)]
1014 A = lltype.Struct('A', ('x', lltype.Signed))
1015 prebuilt = [(rstr.mallocstr(sz),
1016 lltype.malloc(A, flavor='raw', immortal=True))
1017 for sz in sizes]
1018 k = 0
1019 for i, (s, a) in enumerate(prebuilt):
1020 a.x = i
1021 for i in range(len(s.chars)):
1022 k += 1
1023 if k == 256:
1024 k = 1
1025 s.chars[i] = chr(k)
1026
1027 def check(lst):
1028 hashes = []
1029 for i, (s, a) in enumerate(lst):
1030 assert a.x == i
1031 rgc.ll_write_final_null_char(s)
1032 for i, (s, a) in enumerate(lst):
1033 assert a.x == i # check it was not overwritten
1034 def f():
1035 check(prebuilt)
1036 lst1 = []
1037 for i, sz in enumerate(sizes):
1038 s = rstr.mallocstr(sz)
1039 a = lltype.malloc(A, flavor='raw')
1040 a.x = i
1041 lst1.append((s, a))
1042 check(lst1)
1043 for _, a in lst1:
1044 lltype.free(a, flavor='raw')
1045 return 42
1046
1047 fn = self.getcompiled(f, [])
1048 assert fn() == 42
22 import os
33 import sys
44 import subprocess
5 import random
56
67 import py
78
14661467 def test_nursery_hash_base(self):
14671468 res = self.run('nursery_hash_base')
14681469 assert res >= 195
1470
1471 def define_extra_item_after_alloc(cls):
1472 from rpython.rtyper.lltypesystem import rstr
1473 # all STR objects should be allocated with enough space for
1474 # one extra char. Check this with our GCs. Use strings of 8,
1475 # 16 and 24 chars because if the extra char is missing,
1476 # writing to it is likely to cause corruption in nearby
1477 # structures.
1478 sizes = [random.choice([8, 16, 24]) for i in range(100)]
1479 A = lltype.Struct('A', ('x', lltype.Signed))
1480 prebuilt = [(rstr.mallocstr(sz),
1481 lltype.malloc(A, flavor='raw', immortal=True))
1482 for sz in sizes]
1483 k = 0
1484 for i, (s, a) in enumerate(prebuilt):
1485 a.x = i
1486 for i in range(len(s.chars)):
1487 k += 1
1488 if k == 256:
1489 k = 1
1490 s.chars[i] = chr(k)
1491
1492 def check(lst):
1493 hashes = []
1494 for i, (s, a) in enumerate(lst):
1495 assert a.x == i
1496 rgc.ll_write_final_null_char(s)
1497 for i, (s, a) in enumerate(lst):
1498 assert a.x == i # check it was not overwritten
1499 def fn():
1500 check(prebuilt)
1501 lst1 = []
1502 for i, sz in enumerate(sizes):
1503 s = rstr.mallocstr(sz)
1504 a = lltype.malloc(A, flavor='raw')
1505 a.x = i
1506 lst1.append((s, a))
1507 check(lst1)
1508 for _, a in lst1:
1509 lltype.free(a, flavor='raw')
1510 return 42
1511 return fn
1512
1513 def test_extra_item_after_alloc(self):
1514 res = self.run('extra_item_after_alloc')
1515 assert res == 42
14691516
14701517
14711518 class TestGenerationalGC(TestSemiSpaceGC):
1616 from rpython.tool.udir import udir
1717 from rpython.translator import cdir
1818 from rpython.conftest import option
19 from rpython.rlib.jit import JitDriver
1920
2021 def setup_module(module):
2122 if os.name == 'nt':
380380 """ Run all backend optimizations - lltype version
381381 """
382382 from rpython.translator.backendopt.all import backend_optimizations
383 backend_optimizations(self.translator)
383 backend_optimizations(self.translator, replace_we_are_jitted=True)
384384
385385
386386 STACKCHECKINSERTION = 'stackcheckinsertion_lltype'
0 import re
1
2 def extract_s390x_cpu_ids(lines):
3 """ NOT_RPYTHON """
4 ids = []
5
6 re_number = re.compile("processor (\d+):")
7 re_version = re.compile("version = ([0-9A-Fa-f]+)")
8 re_id = re.compile("identification = ([0-9A-Fa-f]+)")
9 re_machine = re.compile("machine = ([0-9A-Fa-f]+)")
10 for line in lines:
11 number = -1
12 version = None
13 ident = None
14 machine = 0
15
16 match = re_number.match(line)
17 if not match:
18 continue
19 number = int(match.group(1))
20
21 match = re_version.search(line)
22 if match:
23 version = match.group(1)
24
25 match = re_version.search(line)
26 if match:
27 version = match.group(1)
28
29 match = re_id.search(line)
30 if match:
31 ident = match.group(1)
32
33 match = re_machine.search(line)
34 if match:
35 machine = int(match.group(1), 16)
36
37 ids.append((number, version, ident, machine))
38
39 return ids
40
41
42 def s390x_cpu_revision():
43 """ NOT_RPYTHON """
44 # linux kernel does the same classification
45 # http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20131028/193311.html
46
47 with open("/proc/cpuinfo", "rb") as fd:
48 lines = fd.read().splitlines()
49 cpu_ids = extract_s390x_cpu_ids(lines)
50 machine = -1
51 for number, version, id, m in cpu_ids:
52 if machine != -1:
53 assert machine == m
54 machine = m
55
56 if machine == 0x2097 or machine == 0x2098:
57 return "z10"
58 if machine == 0x2817 or machine == 0x2818:
59 return "z196"
60 if machine == 0x2827 or machine == 0x2828:
61 return "zEC12"
62 if machine == 0x2964:
63 return "z13"
64
65 # well all others are unsupported!
66 return "unknown"
67
68 def update_cflags(cflags):
69 """ NOT_RPYTHON """
70 # force the right target arch for s390x
71 for cflag in cflags:
72 if cflag.startswith('-march='):
73 break
74 else:
75 # the default cpu architecture that is supported
76 # older versions are not supported
77 revision = s390x_cpu_revision()
78 if revision == 'z13':
79 # gcc does not recognize z13 as a compiler flag!
80 revision = 'zEC12'
81
82 assert revision != 'unknown'
83 cflags += ('-march='+revision,)
84 cflags += ('-m64','-mzarch')
85 return cflags
0 import py
1 import platform
2 from rpython.translator.platform.arch.s390x import (s390x_cpu_revision,
3 extract_s390x_cpu_ids)
4
5 if platform.machine() != 's390x':
6 py.test.skip("s390x tests only")
7
8 def test_cpuid_s390x():
9 revision = s390x_cpu_revision()
10 assert revision != 'unknown', 'the model you are running on might be too old'
11
12 def test_read_processor_info():
13 ids = extract_s390x_cpu_ids("""
14 processor 0: machine = 12345
15 processor 1: version = FF, identification = AF
16 """.splitlines())
17 assert ids == [(0, None, None, 0x12345),
18 (1, 'FF', 'AF', 0),
19 ]
20
21
2121 so_prefixes = ('lib', '')
2222
2323 if platform.machine() == 's390x':
24 # force the right target arch for s390x
25 cflags = ('-march=zEC12','-m64','-mzarch') + cflags
24 from rpython.translator.platform.arch import s390x
25 cflags = s390x.update_cflags(cflags)
2626
2727 def _args_for_shared(self, args):
2828 return ['-shared'] + args
529529 def do_ll_os__ll_os_unlink(self, vpathname):
530530 raise OSError(errno.EPERM, "write access denied")
531531
532 def do_ll_os__ll_os_mkdir(self, vpathname, mode=None):
533 raise OSError(errno.EPERM, "write access denied")
534
532535 def do_ll_os__ll_os_getuid(self):
533536 return UID
534537 do_ll_os__ll_os_geteuid = do_ll_os__ll_os_getuid
7777 dll = ctypes.CDLL(str(t.driver.c_entryp))
7878 f = dll.pypy_g_f
7979 assert f(2, 3) == 5
80
81 def test_check_that_driver_uses_replace_we_are_jitted():
82 from rpython.rlib import jit
83 def f():
84 if jit.we_are_jitted():
85 return 1
86 return 2 + jit.we_are_jitted()
87
88 t = Translation(f, [])
89 t.backendopt()
90 graph = t.driver.translator.graphs[0]
91 assert graph.startblock.exits[0].args[0].value == 2
5454 graph, _ = translate(f, [int, int], backend_optimize=False)
5555 assert len(graph.startblock.operations) == 1
5656 assert graph.startblock.operations[0].opname == 'direct_call'
57 assert 'int_floordiv_ovf_zer' in repr(
57 assert 'int_py_div_ovf_zer' in repr(
5858 graph.startblock.operations[0].args[0].value)
5959 assert len(graph.startblock.exits) == 3
6060 assert [link.target.operations for link in graph.startblock.exits[1:]] == \
7272 graph, _ = translate(f, [int, int], backend_optimize=False)
7373 assert len(graph.startblock.operations) == 1
7474 assert graph.startblock.operations[0].opname == 'direct_call'
75 assert 'int_floordiv_ovf_zer' in repr(
75 assert 'int_py_div_ovf_zer' in repr(
7676 graph.startblock.operations[0].args[0].value)
7777 assert len(graph.startblock.exits) == 3
7878 assert [link.target.operations for link in graph.startblock.exits[1:]] == \
6666 (4 * S + 2 * P) + # struct dicttable
6767 (S + 2 * 8192) + # indexes, length 8192, rffi.USHORT
6868 (S + (S + S) * 3840) + # entries, length 3840
69 (S + S + 5) * 3840) # 3840 strings with 5 chars each
69 (S + S + 6) * 3840) # 3840 strings with 5 chars each (+1 final)
7070 assert guess_size(func.builder.db, fixarrayvalnode, set()) == 100 * rffi.sizeof(lltype.Signed) + 1 * rffi.sizeof(lltype.Signed)
7171 assert guess_size(func.builder.db, dynarrayvalnode, set()) == 100 * rffi.sizeof(lltype.Signed) + 2 * rffi.sizeof(lltype.Signed) + 1 * rffi.sizeof(rffi.VOIDP)
7272