PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/jit/backend/llsupport/llmodel.py

https://bitbucket.org/pypy/pypy/
Python | 827 lines | 809 code | 12 blank | 6 comment | 15 complexity | cdfad2445eaa2303fa556a039f210214 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr
  2. from rpython.rtyper import rclass
  3. from rpython.rtyper.lltypesystem.lloperation import llop
  4. from rpython.rtyper.llinterp import LLInterpreter
  5. from rpython.rtyper.annlowlevel import llhelper, MixLevelHelperAnnotator
  6. from rpython.rtyper.llannotation import lltype_to_annotation
  7. from rpython.rlib.objectmodel import we_are_translated, specialize
  8. from rpython.jit.metainterp import history, compile
  9. from rpython.jit.metainterp.optimize import SpeculativeError
  10. from rpython.jit.codewriter import heaptracker, longlong
  11. from rpython.jit.backend.model import AbstractCPU
  12. from rpython.jit.backend.llsupport import symbolic, jitframe
  13. from rpython.jit.backend.llsupport.symbolic import WORD, unroll_basic_sizes
  14. from rpython.jit.backend.llsupport.descr import (
  15. get_size_descr, get_field_descr, get_array_descr,
  16. get_call_descr, get_interiorfield_descr,
  17. FieldDescr, ArrayDescr, CallDescr, InteriorFieldDescr,
  18. FLAG_POINTER, FLAG_FLOAT)
  19. from rpython.jit.backend.llsupport.memcpy import memset_fn
  20. from rpython.jit.backend.llsupport import asmmemmgr, codemap
  21. from rpython.rlib.unroll import unrolling_iterable
  22. class AbstractLLCPU(AbstractCPU):
  23. from rpython.jit.metainterp.typesystem import llhelper as ts
  24. HAS_CODEMAP = False
  25. done_with_this_frame_descr_int = None # overridden by pyjitpl.py
  26. done_with_this_frame_descr_float = None
  27. done_with_this_frame_descr_ref = None
  28. done_with_this_frame_descr_void = None
  29. exit_frame_with_exception_descr_ref = None
  30. # can an ISA instruction handle a factor to the offset?
  31. load_supported_factors = (1,)
  32. vector_extension = False
  33. vector_register_size = 0 # in bytes
  34. vector_horizontal_operations = False
  35. vector_pack_slots = False
  36. def __init__(self, rtyper, stats, opts, translate_support_code=False,
  37. gcdescr=None):
  38. assert type(opts) is not bool
  39. self.opts = opts
  40. from rpython.jit.backend.llsupport.gc import get_ll_description
  41. AbstractCPU.__init__(self)
  42. self.rtyper = rtyper
  43. self.stats = stats
  44. self.translate_support_code = translate_support_code
  45. if translate_support_code and rtyper is not None:
  46. translator = rtyper.annotator.translator
  47. self.remove_gctypeptr = translator.config.translation.gcremovetypeptr
  48. else:
  49. translator = None
  50. self.gc_ll_descr = get_ll_description(gcdescr, translator, rtyper)
  51. # support_guard_gc_type indicates if a gc type of an object can be read.
  52. # In some states (boehm or x86 untranslated) the type is not known just yet,
  53. # because there are cases where it is not guarded. The precise place where it's not
  54. # is while inlining short preamble.
  55. self.supports_guard_gc_type = self.gc_ll_descr.supports_guard_gc_type
  56. if translator and translator.config.translation.gcremovetypeptr:
  57. self.vtable_offset = None
  58. else:
  59. self.vtable_offset, _ = symbolic.get_field_token(rclass.OBJECT,
  60. 'typeptr',
  61. translate_support_code)
  62. self.subclassrange_min_offset, _ = symbolic.get_field_token(
  63. rclass.OBJECT_VTABLE, 'subclassrange_min', translate_support_code)
  64. if translate_support_code:
  65. self._setup_exception_handling_translated()
  66. else:
  67. self._setup_exception_handling_untranslated()
  68. self.asmmemmgr = asmmemmgr.AsmMemoryManager()
  69. if self.HAS_CODEMAP:
  70. self.codemap = codemap.CodemapStorage()
  71. self._setup_frame_realloc(translate_support_code)
  72. ad = self.gc_ll_descr.getframedescrs(self).arraydescr
  73. self.signedarraydescr = ad
  74. # the same as normal JITFRAME, however with an array of pointers
  75. self.refarraydescr = ArrayDescr(ad.basesize, ad.itemsize, ad.lendescr,
  76. FLAG_POINTER)
  77. if WORD == 4:
  78. self.floatarraydescr = ArrayDescr(ad.basesize, ad.itemsize * 2,
  79. ad.lendescr, FLAG_FLOAT)
  80. else:
  81. self.floatarraydescr = ArrayDescr(ad.basesize, ad.itemsize,
  82. ad.lendescr, FLAG_FLOAT)
  83. self.setup()
  84. self._debug_errno_container = lltype.malloc(
  85. rffi.CArray(lltype.Signed), 7, flavor='raw', zero=True,
  86. track_allocation=False)
  87. def getarraydescr_for_frame(self, type):
  88. if type == history.FLOAT:
  89. descr = self.floatarraydescr
  90. elif type == history.REF:
  91. descr = self.refarraydescr
  92. else:
  93. descr = self.signedarraydescr
  94. return descr
  95. def setup(self):
  96. pass
  97. def finish_once(self):
  98. if self.HAS_CODEMAP:
  99. self.codemap.finish_once()
  100. def compile_loop(self, inputargs, operations, looptoken, jd_id=0,
  101. unique_id=0, log=True, name='', logger=None):
  102. return self.assembler.assemble_loop(jd_id, unique_id, logger, name,
  103. inputargs, operations,
  104. looptoken, log)
  105. def stitch_bridge(self, faildescr, target):
  106. self.assembler.stitch_bridge(faildescr, target)
  107. def _setup_frame_realloc(self, translate_support_code):
  108. FUNC_TP = lltype.Ptr(lltype.FuncType([llmemory.GCREF, lltype.Signed],
  109. llmemory.GCREF))
  110. base_ofs = self.get_baseofs_of_frame_field()
  111. def realloc_frame(frame, size):
  112. try:
  113. if not we_are_translated():
  114. assert not self._exception_emulator[0]
  115. frame = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, frame)
  116. if size > frame.jf_frame_info.jfi_frame_depth:
  117. # update the frame_info size, which is for whatever reason
  118. # not up to date
  119. frame.jf_frame_info.update_frame_depth(base_ofs, size)
  120. new_frame = jitframe.JITFRAME.allocate(frame.jf_frame_info)
  121. frame.jf_forward = new_frame
  122. i = 0
  123. while i < len(frame.jf_frame):
  124. new_frame.jf_frame[i] = frame.jf_frame[i]
  125. frame.jf_frame[i] = 0
  126. i += 1
  127. new_frame.jf_savedata = frame.jf_savedata
  128. new_frame.jf_guard_exc = frame.jf_guard_exc
  129. # all other fields are empty
  130. llop.gc_writebarrier(lltype.Void, new_frame)
  131. return lltype.cast_opaque_ptr(llmemory.GCREF, new_frame)
  132. except Exception as e:
  133. print "Unhandled exception", e, "in realloc_frame"
  134. return lltype.nullptr(llmemory.GCREF.TO)
  135. def realloc_frame_crash(frame, size):
  136. print "frame", frame, "size", size
  137. return lltype.nullptr(llmemory.GCREF.TO)
  138. if not translate_support_code:
  139. fptr = llhelper(FUNC_TP, realloc_frame)
  140. else:
  141. FUNC = FUNC_TP.TO
  142. args_s = [lltype_to_annotation(ARG) for ARG in FUNC.ARGS]
  143. s_result = lltype_to_annotation(FUNC.RESULT)
  144. mixlevelann = MixLevelHelperAnnotator(self.rtyper)
  145. graph = mixlevelann.getgraph(realloc_frame, args_s, s_result)
  146. fptr = mixlevelann.graph2delayed(graph, FUNC)
  147. mixlevelann.finish()
  148. self.realloc_frame = heaptracker.adr2int(llmemory.cast_ptr_to_adr(fptr))
  149. if not translate_support_code:
  150. fptr = llhelper(FUNC_TP, realloc_frame_crash)
  151. else:
  152. FUNC = FUNC_TP.TO
  153. args_s = [lltype_to_annotation(ARG) for ARG in FUNC.ARGS]
  154. s_result = lltype_to_annotation(FUNC.RESULT)
  155. mixlevelann = MixLevelHelperAnnotator(self.rtyper)
  156. graph = mixlevelann.getgraph(realloc_frame_crash, args_s, s_result)
  157. fptr = mixlevelann.graph2delayed(graph, FUNC)
  158. mixlevelann.finish()
  159. self.realloc_frame_crash = heaptracker.adr2int(llmemory.cast_ptr_to_adr(fptr))
  160. def _setup_exception_handling_untranslated(self):
  161. # for running un-translated only, all exceptions occurring in the
  162. # llinterpreter are stored in '_exception_emulator', which is then
  163. # read back by the machine code reading at the address given by
  164. # pos_exception() and pos_exc_value().
  165. _exception_emulator = lltype.malloc(rffi.CArray(lltype.Signed), 2,
  166. zero=True, flavor='raw',
  167. immortal=True)
  168. self._exception_emulator = _exception_emulator
  169. def _store_exception(lle):
  170. self._last_exception = lle # keepalive
  171. tp_i = rffi.cast(lltype.Signed, lle.args[0])
  172. v_i = rffi.cast(lltype.Signed, lle.args[1])
  173. _exception_emulator[0] = tp_i
  174. _exception_emulator[1] = v_i
  175. self.debug_ll_interpreter = LLInterpreter(self.rtyper)
  176. self.debug_ll_interpreter._store_exception = _store_exception
  177. def pos_exception():
  178. return rffi.cast(lltype.Signed, _exception_emulator)
  179. def pos_exc_value():
  180. return (rffi.cast(lltype.Signed, _exception_emulator) +
  181. rffi.sizeof(lltype.Signed))
  182. self.pos_exception = pos_exception
  183. self.pos_exc_value = pos_exc_value
  184. self.insert_stack_check = lambda: (0, 0, 0)
  185. def _setup_exception_handling_translated(self):
  186. def pos_exception():
  187. addr = llop.get_exception_addr(llmemory.Address)
  188. return heaptracker.adr2int(addr)
  189. def pos_exc_value():
  190. addr = llop.get_exc_value_addr(llmemory.Address)
  191. return heaptracker.adr2int(addr)
  192. from rpython.rlib import rstack
  193. STACK_CHECK_SLOWPATH = lltype.Ptr(lltype.FuncType([lltype.Signed],
  194. lltype.Void))
  195. def insert_stack_check():
  196. endaddr = rstack._stack_get_end_adr()
  197. lengthaddr = rstack._stack_get_length_adr()
  198. f = llhelper(STACK_CHECK_SLOWPATH, rstack.stack_check_slowpath)
  199. slowpathaddr = rffi.cast(lltype.Signed, f)
  200. return endaddr, lengthaddr, slowpathaddr
  201. self.pos_exception = pos_exception
  202. self.pos_exc_value = pos_exc_value
  203. self.insert_stack_check = insert_stack_check
  204. def grab_exc_value(self, deadframe):
  205. deadframe = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, deadframe)
  206. return deadframe.jf_guard_exc
  207. def set_savedata_ref(self, deadframe, data):
  208. deadframe = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, deadframe)
  209. deadframe.jf_savedata = data
  210. def get_savedata_ref(self, deadframe):
  211. deadframe = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, deadframe)
  212. return deadframe.jf_savedata
  213. def free_loop_and_bridges(self, compiled_loop_token):
  214. AbstractCPU.free_loop_and_bridges(self, compiled_loop_token)
  215. # turn off all gcreftracers
  216. tracers = compiled_loop_token.asmmemmgr_gcreftracers
  217. if tracers is not None:
  218. compiled_loop_token.asmmemmgr_gcreftracers = None
  219. for tracer in tracers:
  220. self.gc_ll_descr.clear_gcref_tracer(tracer)
  221. # then free all blocks of code and raw data
  222. blocks = compiled_loop_token.asmmemmgr_blocks
  223. if blocks is not None:
  224. compiled_loop_token.asmmemmgr_blocks = None
  225. for rawstart, rawstop in blocks:
  226. self.gc_ll_descr.freeing_block(rawstart, rawstop)
  227. self.asmmemmgr.free(rawstart, rawstop)
  228. if self.HAS_CODEMAP:
  229. self.codemap.free_asm_block(rawstart, rawstop)
  230. def force(self, addr_of_force_token):
  231. frame = rffi.cast(jitframe.JITFRAMEPTR, addr_of_force_token)
  232. frame = frame.resolve()
  233. frame.jf_descr = frame.jf_force_descr
  234. return lltype.cast_opaque_ptr(llmemory.GCREF, frame)
  235. def make_execute_token(self, *ARGS):
  236. # The JIT backend must generate functions with the following
  237. # signature: it takes the jitframe and the threadlocal_addr
  238. # as arguments, and it returns the (possibly reallocated) jitframe.
  239. # The backend can optimize OS_THREADLOCALREF_GET calls to return a
  240. # field of this threadlocal_addr, but only if 'translate_support_code':
  241. # in untranslated tests, threadlocal_addr is a dummy container
  242. # for errno tests only.
  243. FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF, llmemory.Address],
  244. llmemory.GCREF))
  245. lst = [(i, history.getkind(ARG)[0]) for i, ARG in enumerate(ARGS)]
  246. kinds = unrolling_iterable(lst)
  247. def execute_token(executable_token, *args):
  248. clt = executable_token.compiled_loop_token
  249. assert len(args) == clt._debug_nbargs
  250. #
  251. addr = executable_token._ll_function_addr
  252. func = rffi.cast(FUNCPTR, addr)
  253. #llop.debug_print(lltype.Void, ">>>> Entering", addr)
  254. frame_info = clt.frame_info
  255. frame = self.gc_ll_descr.malloc_jitframe(frame_info)
  256. ll_frame = lltype.cast_opaque_ptr(llmemory.GCREF, frame)
  257. locs = executable_token.compiled_loop_token._ll_initial_locs
  258. prev_interpreter = None # help flow space
  259. if not self.translate_support_code:
  260. prev_interpreter = LLInterpreter.current_interpreter
  261. LLInterpreter.current_interpreter = self.debug_ll_interpreter
  262. try:
  263. for i, kind in kinds:
  264. arg = args[i]
  265. num = locs[i]
  266. if kind == history.INT:
  267. self.set_int_value(ll_frame, num, arg)
  268. elif kind == history.FLOAT:
  269. self.set_float_value(ll_frame, num, arg)
  270. else:
  271. assert kind == history.REF
  272. self.set_ref_value(ll_frame, num, arg)
  273. if self.translate_support_code:
  274. ll_threadlocal_addr = llop.threadlocalref_addr(
  275. llmemory.Address)
  276. else:
  277. ll_threadlocal_addr = rffi.cast(llmemory.Address,
  278. self._debug_errno_container)
  279. llop.gc_writebarrier(lltype.Void, ll_frame)
  280. ll_frame = func(ll_frame, ll_threadlocal_addr)
  281. finally:
  282. if not self.translate_support_code:
  283. LLInterpreter.current_interpreter = prev_interpreter
  284. #llop.debug_print(lltype.Void, "<<<< Back")
  285. return ll_frame
  286. return execute_token
  287. def setup_descrs(self):
  288. return self.gc_ll_descr.setup_descrs()
  289. # ------------------- helpers and descriptions --------------------
  290. @staticmethod
  291. def _cast_int_to_gcref(x):
  292. # dangerous! only use if you are sure no collection could occur
  293. # between reading the integer and casting it to a pointer
  294. return rffi.cast(llmemory.GCREF, x)
  295. @staticmethod
  296. def cast_gcref_to_int(x):
  297. return rffi.cast(lltype.Signed, x)
  298. @staticmethod
  299. def cast_int_to_adr(x):
  300. return rffi.cast(llmemory.Address, x)
  301. @staticmethod
  302. def cast_adr_to_int(x):
  303. return rffi.cast(lltype.Signed, x)
  304. @specialize.arg(2)
  305. def cast_int_to_ptr(self, x, TYPE):
  306. return rffi.cast(TYPE, x)
  307. def sizeof(self, S, vtable=lltype.nullptr(rclass.OBJECT_VTABLE)):
  308. return get_size_descr(self.gc_ll_descr, S, vtable)
  309. def fielddescrof(self, STRUCT, fieldname):
  310. return get_field_descr(self.gc_ll_descr, STRUCT, fieldname)
  311. def unpack_fielddescr(self, fielddescr):
  312. assert isinstance(fielddescr, FieldDescr)
  313. return fielddescr.offset
  314. unpack_fielddescr._always_inline_ = True
  315. def unpack_fielddescr_size(self, fielddescr):
  316. assert isinstance(fielddescr, FieldDescr)
  317. ofs = fielddescr.offset
  318. size = fielddescr.field_size
  319. sign = fielddescr.is_field_signed()
  320. return ofs, size, sign
  321. unpack_fielddescr_size._always_inline_ = True
  322. @specialize.memo()
  323. def arraydescrof(self, A):
  324. return get_array_descr(self.gc_ll_descr, A)
  325. def interiorfielddescrof(self, A, fieldname, arrayfieldname=None):
  326. return get_interiorfield_descr(self.gc_ll_descr, A, fieldname,
  327. arrayfieldname)
  328. def unpack_arraydescr(self, arraydescr):
  329. assert isinstance(arraydescr, ArrayDescr)
  330. return arraydescr.basesize
  331. unpack_arraydescr._always_inline_ = True
  332. def unpack_arraydescr_size(self, arraydescr):
  333. assert isinstance(arraydescr, ArrayDescr)
  334. ofs = arraydescr.basesize
  335. size = arraydescr.itemsize
  336. sign = arraydescr.is_item_signed()
  337. return ofs, size, sign
  338. unpack_arraydescr_size._always_inline_ = True
  339. def calldescrof(self, FUNC, ARGS, RESULT, extrainfo):
  340. return get_call_descr(self.gc_ll_descr, ARGS, RESULT, extrainfo)
  341. def calldescrof_dynamic(self, cif_description, extrainfo):
  342. from rpython.jit.backend.llsupport import ffisupport
  343. return ffisupport.get_call_descr_dynamic(self, cif_description,
  344. extrainfo)
  345. def _calldescr_dynamic_for_tests(self, atypes, rtype,
  346. abiname='FFI_DEFAULT_ABI'):
  347. from rpython.jit.backend.llsupport import ffisupport
  348. return ffisupport.calldescr_dynamic_for_tests(self, atypes, rtype,
  349. abiname)
  350. def get_latest_descr(self, deadframe):
  351. deadframe = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, deadframe)
  352. descr = deadframe.jf_descr
  353. res = history.AbstractDescr.show(self, descr)
  354. if not we_are_translated(): # tests only: for missing
  355. if res is None: # propagate_exception_descr
  356. raise MissingLatestDescrError
  357. assert isinstance(res, history.AbstractFailDescr)
  358. return res
  359. def _decode_pos(self, deadframe, index):
  360. descr = self.get_latest_descr(deadframe)
  361. return rffi.cast(lltype.Signed, descr.rd_locs[index]) * WORD
  362. @specialize.arg(2)
  363. def get_value_direct(self, deadframe, tp, index):
  364. if tp == 'i':
  365. return self.get_int_value_direct(deadframe, index * WORD)
  366. elif tp == 'r':
  367. return self.get_ref_value_direct(deadframe, index * WORD)
  368. elif tp == 'f':
  369. return self.get_float_value_direct(deadframe, index * WORD)
  370. else:
  371. assert False
  372. def get_int_value(self, deadframe, index):
  373. pos = self._decode_pos(deadframe, index)
  374. return self.get_int_value_direct(deadframe, pos)
  375. def get_int_value_direct(self, deadframe, pos):
  376. descr = self.gc_ll_descr.getframedescrs(self).arraydescr
  377. ofs = self.unpack_arraydescr(descr)
  378. return self.read_int_at_mem(deadframe, pos + ofs, WORD, 1)
  379. def get_ref_value(self, deadframe, index):
  380. pos = self._decode_pos(deadframe, index)
  381. return self.get_ref_value_direct(deadframe, pos)
  382. def get_ref_value_direct(self, deadframe, pos):
  383. descr = self.gc_ll_descr.getframedescrs(self).arraydescr
  384. ofs = self.unpack_arraydescr(descr)
  385. return self.read_ref_at_mem(deadframe, pos + ofs)
  386. def get_float_value(self, deadframe, index):
  387. pos = self._decode_pos(deadframe, index)
  388. return self.get_float_value_direct(deadframe, pos)
  389. def get_float_value_direct(self, deadframe, pos):
  390. descr = self.gc_ll_descr.getframedescrs(self).arraydescr
  391. ofs = self.unpack_arraydescr(descr)
  392. return self.read_float_at_mem(deadframe, pos + ofs)
  393. # ____________________ RAW PRIMITIVES ________________________
  394. @specialize.argtype(1)
  395. def read_int_at_mem(self, gcref, ofs, size, sign):
  396. for STYPE, UTYPE, itemsize in unroll_basic_sizes:
  397. if size == itemsize:
  398. if sign:
  399. val = llop.raw_load(STYPE, gcref, ofs)
  400. val = rffi.cast(lltype.Signed, val)
  401. else:
  402. val = llop.raw_load(UTYPE, gcref, ofs)
  403. val = rffi.cast(lltype.Signed, val)
  404. return val
  405. else:
  406. raise NotImplementedError("size = %d" % size)
  407. @specialize.argtype(1)
  408. def write_int_at_mem(self, gcref, ofs, size, newvalue):
  409. for TYPE, _, itemsize in unroll_basic_sizes:
  410. if size == itemsize:
  411. newvalue = rffi.cast(TYPE, newvalue)
  412. llop.raw_store(lltype.Void, gcref, ofs, newvalue)
  413. return
  414. else:
  415. raise NotImplementedError("size = %d" % size)
  416. @specialize.argtype(1)
  417. def read_ref_at_mem(self, gcref, ofs):
  418. return llop.raw_load(llmemory.GCREF, gcref, ofs)
  419. # non-@specialized: must only be called with llmemory.GCREF
  420. def write_ref_at_mem(self, gcref, ofs, newvalue):
  421. llop.raw_store(lltype.Void, gcref, ofs, newvalue)
  422. # the write barrier is implied above
  423. @specialize.argtype(1)
  424. def read_float_at_mem(self, gcref, ofs):
  425. return llop.raw_load(longlong.FLOATSTORAGE, gcref, ofs)
  426. @specialize.argtype(1)
  427. def write_float_at_mem(self, gcref, ofs, newvalue):
  428. llop.raw_store(lltype.Void, gcref, ofs, newvalue)
  429. # ____________________________________________________________
  430. def set_int_value(self, newframe, index, value):
  431. """ Note that we keep index multiplied by WORD here mostly
  432. for completeness with get_int_value and friends
  433. """
  434. descr = self.gc_ll_descr.getframedescrs(self).arraydescr
  435. ofs = self.unpack_arraydescr(descr)
  436. self.write_int_at_mem(newframe, ofs + index, WORD, value)
  437. def set_ref_value(self, newframe, index, value):
  438. descr = self.gc_ll_descr.getframedescrs(self).arraydescr
  439. ofs = self.unpack_arraydescr(descr)
  440. self.write_ref_at_mem(newframe, ofs + index, value)
  441. def set_float_value(self, newframe, index, value):
  442. descr = self.gc_ll_descr.getframedescrs(self).arraydescr
  443. ofs = self.unpack_arraydescr(descr)
  444. self.write_float_at_mem(newframe, ofs + index, value)
  445. @specialize.arg(1)
  446. def get_ofs_of_frame_field(self, name):
  447. descrs = self.gc_ll_descr.getframedescrs(self)
  448. ofs = self.unpack_fielddescr(getattr(descrs, name))
  449. return ofs
  450. def get_baseofs_of_frame_field(self):
  451. descrs = self.gc_ll_descr.getframedescrs(self)
  452. base_ofs = self.unpack_arraydescr(descrs.arraydescr)
  453. return base_ofs
  454. # ____________________________________________________________
  455. def check_is_object(self, gcptr):
  456. """Check if the given, non-null gcptr refers to an rclass.OBJECT
  457. or not at all (an unrelated GcStruct or a GcArray). Only usable
  458. in the llgraph backend, or after translation of a real backend."""
  459. assert self.supports_guard_gc_type
  460. return self.gc_ll_descr.check_is_object(gcptr)
  461. def get_actual_typeid(self, gcptr):
  462. """Fetch the actual typeid of the given gcptr, as an integer.
  463. Only usable in the llgraph backend, or after translation of a
  464. real backend."""
  465. assert self.supports_guard_gc_type
  466. return self.gc_ll_descr.get_actual_typeid(gcptr)
  467. def protect_speculative_field(self, gcptr, fielddescr):
  468. if not gcptr:
  469. raise SpeculativeError
  470. if self.supports_guard_gc_type:
  471. assert isinstance(fielddescr, FieldDescr)
  472. sizedescr = fielddescr.parent_descr
  473. if sizedescr.is_object():
  474. if (not self.check_is_object(gcptr) or
  475. not sizedescr.is_valid_class_for(gcptr)):
  476. raise SpeculativeError
  477. else:
  478. if self.get_actual_typeid(gcptr) != sizedescr.tid:
  479. raise SpeculativeError
  480. def protect_speculative_array(self, gcptr, arraydescr):
  481. if not gcptr:
  482. raise SpeculativeError
  483. if self.supports_guard_gc_type:
  484. assert isinstance(arraydescr, ArrayDescr)
  485. if self.get_actual_typeid(gcptr) != arraydescr.tid:
  486. raise SpeculativeError
  487. def protect_speculative_string(self, gcptr):
  488. self.protect_speculative_array(gcptr, self.gc_ll_descr.str_descr)
  489. def protect_speculative_unicode(self, gcptr):
  490. self.protect_speculative_array(gcptr, self.gc_ll_descr.unicode_descr)
  491. # ____________________________________________________________
  492. def bh_arraylen_gc(self, array, arraydescr):
  493. assert isinstance(arraydescr, ArrayDescr)
  494. ofs = arraydescr.lendescr.offset
  495. return self.read_int_at_mem(array, ofs, WORD, 1)
  496. @specialize.argtype(1)
  497. def bh_getarrayitem_gc_i(self, gcref, itemindex, arraydescr):
  498. ofs, size, sign = self.unpack_arraydescr_size(arraydescr)
  499. return self.read_int_at_mem(gcref, ofs + itemindex * size, size,
  500. sign)
  501. def bh_getarrayitem_gc_r(self, gcref, itemindex, arraydescr):
  502. ofs = self.unpack_arraydescr(arraydescr)
  503. return self.read_ref_at_mem(gcref, itemindex * WORD + ofs)
  504. @specialize.argtype(1)
  505. def bh_getarrayitem_gc_f(self, gcref, itemindex, arraydescr):
  506. ofs = self.unpack_arraydescr(arraydescr)
  507. fsize = rffi.sizeof(longlong.FLOATSTORAGE)
  508. return self.read_float_at_mem(gcref, itemindex * fsize + ofs)
  509. @specialize.argtype(1)
  510. def bh_setarrayitem_gc_i(self, gcref, itemindex, newvalue, arraydescr):
  511. ofs, size, sign = self.unpack_arraydescr_size(arraydescr)
  512. self.write_int_at_mem(gcref, ofs + itemindex * size, size, newvalue)
  513. def bh_setarrayitem_gc_r(self, gcref, itemindex, newvalue, arraydescr):
  514. ofs = self.unpack_arraydescr(arraydescr)
  515. self.write_ref_at_mem(gcref, itemindex * WORD + ofs, newvalue)
  516. @specialize.argtype(1)
  517. def bh_setarrayitem_gc_f(self, gcref, itemindex, newvalue, arraydescr):
  518. ofs = self.unpack_arraydescr(arraydescr)
  519. fsize = rffi.sizeof(longlong.FLOATSTORAGE)
  520. self.write_float_at_mem(gcref, ofs + itemindex * fsize, newvalue)
  521. bh_setarrayitem_raw_i = bh_setarrayitem_gc_i
  522. bh_setarrayitem_raw_f = bh_setarrayitem_gc_f
  523. bh_getarrayitem_raw_i = bh_getarrayitem_gc_i
  524. bh_getarrayitem_raw_f = bh_getarrayitem_gc_f
  525. def bh_getinteriorfield_gc_i(self, gcref, itemindex, descr):
  526. assert isinstance(descr, InteriorFieldDescr)
  527. ofs, size, _ = self.unpack_arraydescr_size(descr.arraydescr)
  528. fldofs, fldsize, sign = self.unpack_fielddescr_size(descr.fielddescr)
  529. ofs += itemindex * size + fldofs
  530. return self.read_int_at_mem(gcref, ofs, fldsize, sign)
  531. def bh_getinteriorfield_gc_r(self, gcref, itemindex, descr):
  532. assert isinstance(descr, InteriorFieldDescr)
  533. ofs, size, _ = self.unpack_arraydescr_size(descr.arraydescr)
  534. ofs += descr.fielddescr.offset
  535. fullofs = itemindex * size + ofs
  536. return self.read_ref_at_mem(gcref, fullofs)
  537. def bh_getinteriorfield_gc_f(self, gcref, itemindex, descr):
  538. assert isinstance(descr, InteriorFieldDescr)
  539. ofs, size, _ = self.unpack_arraydescr_size(descr.arraydescr)
  540. ofs += descr.fielddescr.offset
  541. fullofs = itemindex * size + ofs
  542. return self.read_float_at_mem(gcref, fullofs)
  543. def bh_setinteriorfield_gc_i(self, gcref, itemindex, newvalue, descr):
  544. assert isinstance(descr, InteriorFieldDescr)
  545. ofs, size, _ = self.unpack_arraydescr_size(descr.arraydescr)
  546. fldofs, fldsize, _ = self.unpack_fielddescr_size(descr.fielddescr)
  547. ofs += itemindex * size + fldofs
  548. self.write_int_at_mem(gcref, ofs, fldsize, newvalue)
  549. def bh_setinteriorfield_gc_r(self, gcref, itemindex, newvalue, descr):
  550. assert isinstance(descr, InteriorFieldDescr)
  551. ofs, size, _ = self.unpack_arraydescr_size(descr.arraydescr)
  552. ofs += itemindex * size + descr.fielddescr.offset
  553. self.write_ref_at_mem(gcref, ofs, newvalue)
  554. def bh_setinteriorfield_gc_f(self, gcref, itemindex, newvalue, descr):
  555. assert isinstance(descr, InteriorFieldDescr)
  556. ofs, size, _ = self.unpack_arraydescr_size(descr.arraydescr)
  557. ofs += itemindex * size + descr.fielddescr.offset
  558. self.write_float_at_mem(gcref, ofs, newvalue)
  559. def bh_strlen(self, string):
  560. s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
  561. return len(s.chars)
  562. def bh_unicodelen(self, string):
  563. u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
  564. return len(u.chars)
  565. def bh_strgetitem(self, string, index):
  566. s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
  567. return ord(s.chars[index])
  568. def bh_unicodegetitem(self, string, index):
  569. u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
  570. return ord(u.chars[index])
  571. @specialize.argtype(1)
  572. def bh_getfield_gc_i(self, struct, fielddescr):
  573. ofs, size, sign = self.unpack_fielddescr_size(fielddescr)
  574. if isinstance(lltype.typeOf(struct), lltype.Ptr):
  575. fielddescr.assert_correct_type(struct)
  576. return self.read_int_at_mem(struct, ofs, size, sign)
  577. @specialize.argtype(1)
  578. def bh_getfield_gc_r(self, struct, fielddescr):
  579. ofs = self.unpack_fielddescr(fielddescr)
  580. if isinstance(lltype.typeOf(struct), lltype.Ptr):
  581. fielddescr.assert_correct_type(struct)
  582. return self.read_ref_at_mem(struct, ofs)
  583. @specialize.argtype(1)
  584. def bh_getfield_gc_f(self, struct, fielddescr):
  585. ofs = self.unpack_fielddescr(fielddescr)
  586. if isinstance(lltype.typeOf(struct), lltype.Ptr):
  587. fielddescr.assert_correct_type(struct)
  588. return self.read_float_at_mem(struct, ofs)
  589. bh_getfield_raw_i = bh_getfield_gc_i
  590. bh_getfield_raw_r = bh_getfield_gc_r
  591. bh_getfield_raw_f = bh_getfield_gc_f
  592. @specialize.argtype(1)
  593. def bh_setfield_gc_i(self, struct, newvalue, fielddescr):
  594. ofs, size, _ = self.unpack_fielddescr_size(fielddescr)
  595. if isinstance(lltype.typeOf(struct), lltype.Ptr):
  596. fielddescr.assert_correct_type(struct)
  597. self.write_int_at_mem(struct, ofs, size, newvalue)
  598. def bh_setfield_gc_r(self, struct, newvalue, fielddescr):
  599. ofs = self.unpack_fielddescr(fielddescr)
  600. if isinstance(lltype.typeOf(struct), lltype.Ptr):
  601. fielddescr.assert_correct_type(struct)
  602. self.write_ref_at_mem(struct, ofs, newvalue)
  603. @specialize.argtype(1)
  604. def bh_setfield_gc_f(self, struct, newvalue, fielddescr):
  605. ofs = self.unpack_fielddescr(fielddescr)
  606. if isinstance(lltype.typeOf(struct), lltype.Ptr):
  607. fielddescr.assert_correct_type(struct)
  608. self.write_float_at_mem(struct, ofs, newvalue)
  609. bh_setfield_raw_i = bh_setfield_gc_i
  610. bh_setfield_raw_f = bh_setfield_gc_f
  611. def bh_raw_store_i(self, addr, offset, newvalue, descr):
  612. ofs, size, _ = self.unpack_arraydescr_size(descr)
  613. assert ofs == 0 # otherwise, 'descr' is not a raw length-less array
  614. self.write_int_at_mem(addr, offset, size, newvalue)
  615. def bh_raw_store_f(self, addr, offset, newvalue, descr):
  616. self.write_float_at_mem(addr, offset, newvalue)
  617. def bh_raw_load_i(self, addr, offset, descr):
  618. ofs, size, sign = self.unpack_arraydescr_size(descr)
  619. assert ofs == 0 # otherwise, 'descr' is not a raw length-less array
  620. return self.read_int_at_mem(addr, offset, size, sign)
  621. def bh_raw_load_f(self, addr, offset, descr):
  622. return self.read_float_at_mem(addr, offset)
  623. def bh_gc_load_indexed_i(self, addr, index, scale, base_ofs, bytes):
  624. offset = base_ofs + scale * index
  625. return self.read_int_at_mem(addr, offset, abs(bytes), bytes < 0)
  626. def bh_gc_load_indexed_f(self, addr, index, scale, base_ofs, bytes):
  627. # only for 'double'!
  628. assert bytes == rffi.sizeof(lltype.Float)
  629. offset = base_ofs + scale * index
  630. return self.read_float_at_mem(addr, offset)
  631. def bh_new(self, sizedescr):
  632. return self.gc_ll_descr.gc_malloc(sizedescr)
  633. def bh_new_with_vtable(self, sizedescr):
  634. res = self.gc_ll_descr.gc_malloc(sizedescr)
  635. if self.vtable_offset is not None:
  636. self.write_int_at_mem(res, self.vtable_offset, WORD, sizedescr.get_vtable())
  637. return res
  638. def bh_new_raw_buffer(self, size):
  639. return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
  640. def bh_classof(self, struct):
  641. struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct)
  642. result_adr = llmemory.cast_ptr_to_adr(struct.typeptr)
  643. return heaptracker.adr2int(result_adr)
  644. def bh_new_array(self, length, arraydescr):
  645. return self.gc_ll_descr.gc_malloc_array(length, arraydescr)
  646. bh_new_array_clear = bh_new_array
  647. def bh_newstr(self, length):
  648. return self.gc_ll_descr.gc_malloc_str(length)
  649. def bh_newunicode(self, length):
  650. return self.gc_ll_descr.gc_malloc_unicode(length)
  651. def bh_strsetitem(self, string, index, newvalue):
  652. s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
  653. s.chars[index] = chr(newvalue)
  654. def bh_unicodesetitem(self, string, index, newvalue):
  655. u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
  656. u.chars[index] = unichr(newvalue)
  657. def bh_copystrcontent(self, src, dst, srcstart, dststart, length):
  658. src = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), src)
  659. dst = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), dst)
  660. rstr.copy_string_contents(src, dst, srcstart, dststart, length)
  661. def bh_copyunicodecontent(self, src, dst, srcstart, dststart, length):
  662. src = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), src)
  663. dst = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), dst)
  664. rstr.copy_unicode_contents(src, dst, srcstart, dststart, length)
  665. def bh_call_i(self, func, args_i, args_r, args_f, calldescr):
  666. assert isinstance(calldescr, CallDescr)
  667. if not we_are_translated():
  668. calldescr.verify_types(args_i, args_r, args_f, history.INT + 'S')
  669. return calldescr.call_stub_i(func, args_i, args_r, args_f)
  670. def bh_call_r(self, func, args_i, args_r, args_f, calldescr):
  671. assert isinstance(calldescr, CallDescr)
  672. if not we_are_translated():
  673. calldescr.verify_types(args_i, args_r, args_f, history.REF)
  674. return calldescr.call_stub_r(func, args_i, args_r, args_f)
  675. def bh_call_f(self, func, args_i, args_r, args_f, calldescr):
  676. assert isinstance(calldescr, CallDescr)
  677. if not we_are_translated():
  678. calldescr.verify_types(args_i, args_r, args_f, history.FLOAT + 'L')
  679. return calldescr.call_stub_f(func, args_i, args_r, args_f)
  680. def bh_call_v(self, func, args_i, args_r, args_f, calldescr):
  681. assert isinstance(calldescr, CallDescr)
  682. if not we_are_translated():
  683. calldescr.verify_types(args_i, args_r, args_f, history.VOID)
  684. # the 'i' return value is ignored (and nonsense anyway)
  685. calldescr.call_stub_i(func, args_i, args_r, args_f)
  686. class MissingLatestDescrError(Exception):
  687. """For propagate_exception_descr in untranslated tests."""
  688. final_descr_rd_locs = [rffi.cast(rffi.USHORT, 0)]
  689. history.BasicFinalDescr.rd_locs = final_descr_rd_locs
  690. compile._DoneWithThisFrameDescr.rd_locs = final_descr_rd_locs