PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/module/sys/vm.py

https://bitbucket.org/pypy/pypy/
Python | 261 lines | 260 code | 0 blank | 1 comment | 0 complexity | ba6150e4fd8a9e2b9e270e5d651f8427 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """
  2. Implementation of interpreter-level 'sys' routines.
  3. """
  4. from rpython.rlib import jit
  5. from rpython.rlib.runicode import MAXUNICODE
  6. from pypy.interpreter import gateway
  7. from pypy.interpreter.error import oefmt
  8. from pypy.interpreter.gateway import unwrap_spec
  9. # ____________________________________________________________
  10. @unwrap_spec(depth=int)
  11. def _getframe(space, depth=0):
  12. """Return a frame object from the call stack. If optional integer depth is
  13. given, return the frame object that many calls below the top of the stack.
  14. If that is deeper than the call stack, ValueError is raised. The default
  15. for depth is zero, returning the frame at the top of the call stack.
  16. This function should be used for internal and specialized
  17. purposes only."""
  18. if depth < 0:
  19. raise oefmt(space.w_ValueError, "frame index must not be negative")
  20. return getframe(space, depth)
  21. @jit.look_inside_iff(lambda space, depth: jit.isconstant(depth))
  22. def getframe(space, depth):
  23. ec = space.getexecutioncontext()
  24. f = ec.gettopframe_nohidden()
  25. while True:
  26. if f is None:
  27. raise oefmt(space.w_ValueError, "call stack is not deep enough")
  28. if depth == 0:
  29. f.mark_as_escaped()
  30. return space.wrap(f)
  31. depth -= 1
  32. f = ec.getnextframe_nohidden(f)
  33. @unwrap_spec(new_limit="c_int")
  34. def setrecursionlimit(space, new_limit):
  35. """setrecursionlimit() sets the maximum number of nested calls that
  36. can occur before a RuntimeError is raised. On PyPy the limit is
  37. approximative and checked at a lower level. The default 1000
  38. reserves 768KB of stack space, which should suffice (on Linux,
  39. depending on the compiler settings) for ~1400 calls. Setting the
  40. value to N reserves N/1000 times 768KB of stack space.
  41. """
  42. from rpython.rlib.rstack import _stack_set_length_fraction
  43. if new_limit <= 0:
  44. raise oefmt(space.w_ValueError, "recursion limit must be positive")
  45. space.sys.recursionlimit = new_limit
  46. _stack_set_length_fraction(new_limit * 0.001)
  47. def getrecursionlimit(space):
  48. """Return the last value set by setrecursionlimit().
  49. """
  50. return space.wrap(space.sys.recursionlimit)
  51. @unwrap_spec(flag=bool)
  52. def set_track_resources(space, flag):
  53. space.sys.track_resources = flag
  54. def get_track_resources(space):
  55. return space.wrap(space.sys.track_resources)
  56. @unwrap_spec(interval=int)
  57. def setcheckinterval(space, interval):
  58. """Tell the Python interpreter to check for asynchronous events every
  59. n instructions. This also affects how often thread switches occur."""
  60. space.actionflag.setcheckinterval(interval)
  61. def getcheckinterval(space):
  62. """Return the current check interval; see setcheckinterval()."""
  63. # xxx to make tests and possibly some obscure apps happy, if the
  64. # checkinterval is set to the minimum possible value (which is 1) we
  65. # return 0. The idea is that according to the CPython docs, <= 0
  66. # means "check every virtual instruction, maximizing responsiveness
  67. # as well as overhead".
  68. result = space.actionflag.getcheckinterval()
  69. if result <= 1:
  70. result = 0
  71. return space.wrap(result)
  72. def exc_info(space):
  73. """Return the (type, value, traceback) of the most recent exception
  74. caught by an except clause in the current stack frame or in an older stack
  75. frame."""
  76. return exc_info_with_tb(space) # indirection for the tests
  77. def exc_info_with_tb(space):
  78. operror = space.getexecutioncontext().sys_exc_info()
  79. if operror is None:
  80. return space.newtuple([space.w_None, space.w_None, space.w_None])
  81. else:
  82. return space.newtuple([operror.w_type, operror.get_w_value(space),
  83. space.wrap(operror.get_traceback())])
  84. def exc_info_without_tb(space, frame):
  85. operror = frame.last_exception
  86. return space.newtuple([operror.w_type, operror.get_w_value(space),
  87. space.w_None])
  88. def exc_info_direct(space, frame):
  89. from pypy.tool import stdlib_opcode
  90. # In order to make the JIT happy, we try to return (exc, val, None)
  91. # instead of (exc, val, tb). We can do that only if we recognize
  92. # the following pattern in the bytecode:
  93. # CALL_FUNCTION/CALL_METHOD <-- invoking me
  94. # LOAD_CONST 0, 1, -2 or -3
  95. # BINARY_SUBSCR
  96. # or:
  97. # CALL_FUNCTION/CALL_METHOD
  98. # LOAD_CONST <=2
  99. # SLICE_2
  100. # or:
  101. # CALL_FUNCTION/CALL_METHOD
  102. # LOAD_CONST any integer
  103. # LOAD_CONST <=2
  104. # SLICE_3
  105. need_all_three_args = True
  106. co = frame.getcode().co_code
  107. p = frame.last_instr
  108. if (ord(co[p]) == stdlib_opcode.CALL_FUNCTION or
  109. ord(co[p]) == stdlib_opcode.CALL_METHOD):
  110. if ord(co[p+3]) == stdlib_opcode.LOAD_CONST:
  111. lo = ord(co[p+4])
  112. hi = ord(co[p+5])
  113. w_constant = frame.getconstant_w((hi * 256) | lo)
  114. if space.isinstance_w(w_constant, space.w_int):
  115. constant = space.int_w(w_constant)
  116. if ord(co[p+6]) == stdlib_opcode.BINARY_SUBSCR:
  117. if -3 <= constant <= 1 and constant != -1:
  118. need_all_three_args = False
  119. elif ord(co[p+6]) == stdlib_opcode.SLICE+2:
  120. if constant <= 2:
  121. need_all_three_args = False
  122. elif (ord(co[p+6]) == stdlib_opcode.LOAD_CONST and
  123. ord(co[p+9]) == stdlib_opcode.SLICE+3):
  124. lo = ord(co[p+7])
  125. hi = ord(co[p+8])
  126. w_constant = frame.getconstant_w((hi * 256) | lo)
  127. if space.isinstance_w(w_constant, space.w_int):
  128. if space.int_w(w_constant) <= 2:
  129. need_all_three_args = False
  130. #
  131. if need_all_three_args or frame.last_exception is None or frame.hide():
  132. return exc_info_with_tb(space)
  133. else:
  134. return exc_info_without_tb(space, frame)
  135. def exc_clear(space):
  136. """Clear global information on the current exception. Subsequent calls
  137. to exc_info() will return (None,None,None) until another exception is
  138. raised and caught in the current thread or the execution stack returns to a
  139. frame where another exception is being handled."""
  140. space.getexecutioncontext().clear_sys_exc_info()
  141. def settrace(space, w_func):
  142. """Set the global debug tracing function. It will be called on each
  143. function call. See the debugger chapter in the library manual."""
  144. space.getexecutioncontext().settrace(w_func)
  145. def gettrace(space):
  146. """Return the global debug tracing function set with sys.settrace.
  147. See the debugger chapter in the library manual."""
  148. return space.getexecutioncontext().gettrace()
  149. def setprofile(space, w_func):
  150. """Set the profiling function. It will be called on each function call
  151. and return. See the profiler chapter in the library manual."""
  152. space.getexecutioncontext().setprofile(w_func)
  153. def getprofile(space):
  154. """Return the profiling function set with sys.setprofile.
  155. See the profiler chapter in the library manual."""
  156. w_func = space.getexecutioncontext().getprofile()
  157. if w_func is not None:
  158. return w_func
  159. else:
  160. return space.w_None
  161. def call_tracing(space, w_func, w_args):
  162. """Call func(*args), while tracing is enabled. The tracing state is
  163. saved, and restored afterwards. This is intended to be called from
  164. a debugger from a checkpoint, to recursively debug some other code."""
  165. return space.getexecutioncontext().call_tracing(w_func, w_args)
  166. app = gateway.applevel('''
  167. "NOT_RPYTHON"
  168. from _structseq import structseqtype, structseqfield
  169. class windows_version_info:
  170. __metaclass__ = structseqtype
  171. name = "sys.getwindowsversion"
  172. major = structseqfield(0, "Major version number")
  173. minor = structseqfield(1, "Minor version number")
  174. build = structseqfield(2, "Build number")
  175. platform = structseqfield(3, "Operating system platform")
  176. service_pack = structseqfield(4, "Latest Service Pack installed on the system")
  177. # Because the indices aren't consecutive, they aren't included when
  178. # unpacking and other such operations.
  179. service_pack_major = structseqfield(10, "Service Pack major version number")
  180. service_pack_minor = structseqfield(11, "Service Pack minor version number")
  181. suite_mask = structseqfield(12, "Bit mask identifying available product suites")
  182. product_type = structseqfield(13, "System product type")
  183. ''')
  184. def getwindowsversion(space):
  185. from rpython.rlib import rwin32
  186. info = rwin32.GetVersionEx()
  187. w_windows_version_info = app.wget(space, "windows_version_info")
  188. raw_version = space.newtuple([
  189. space.wrap(info[0]),
  190. space.wrap(info[1]),
  191. space.wrap(info[2]),
  192. space.wrap(info[3]),
  193. space.wrap(info[4]),
  194. space.wrap(info[5]),
  195. space.wrap(info[6]),
  196. space.wrap(info[7]),
  197. space.wrap(info[8]),
  198. ])
  199. return space.call_function(w_windows_version_info, raw_version)
  200. @jit.dont_look_inside
  201. def get_dllhandle(space):
  202. if not space.config.objspace.usemodules.cpyext:
  203. return space.wrap(0)
  204. return _get_dllhandle(space)
  205. def _get_dllhandle(space):
  206. # Retrieve cpyext api handle
  207. from pypy.module.cpyext.api import State
  208. handle = space.fromcache(State).get_pythonapi_handle()
  209. # It used to be a CDLL
  210. # from pypy.module._rawffi.interp_rawffi import W_CDLL
  211. # from rpython.rlib.clibffi import RawCDLL
  212. # cdll = RawCDLL(handle)
  213. # return space.wrap(W_CDLL(space, "python api", cdll))
  214. # Provide a cpython-compatible int
  215. from rpython.rtyper.lltypesystem import lltype, rffi
  216. return space.wrap(rffi.cast(lltype.Signed, handle))
  217. def getsizeof(space, w_object, w_default=None):
  218. """Not implemented on PyPy."""
  219. if w_default is None:
  220. raise oefmt(space.w_TypeError,
  221. "sys.getsizeof() not implemented on PyPy")
  222. return w_default