PageRenderTime 53ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/flowspace/flowcontext.py

https://bitbucket.org/pypy/pypy/
Python | 1358 lines | 1329 code | 15 blank | 14 comment | 5 complexity | 68e349a553d290520a0cd201994ae5f5 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """Implements the core parts of flow graph creation.
  2. """
  3. import sys
  4. import collections
  5. import types
  6. import __builtin__
  7. from rpython.tool.error import source_lines
  8. from rpython.rlib import rstackovf
  9. from rpython.flowspace.argument import CallSpec
  10. from rpython.flowspace.model import (Constant, Variable, Block, Link,
  11. c_last_exception, const, FSException)
  12. from rpython.flowspace.framestate import FrameState
  13. from rpython.flowspace.specialcase import (rpython_print_item,
  14. rpython_print_newline)
  15. from rpython.flowspace.operation import op
  16. from rpython.flowspace.bytecode import BytecodeCorruption
  17. w_None = const(None)
  18. class FlowingError(Exception):
  19. """ Signals invalid RPython in the function being analysed"""
  20. ctx = None
  21. def __str__(self):
  22. msg = ["\n"]
  23. msg += map(str, self.args)
  24. msg += [""]
  25. msg += source_lines(self.ctx.graph, None, offset=self.ctx.last_offset)
  26. return "\n".join(msg)
  27. class StopFlowing(Exception):
  28. pass
  29. class SpamBlock(Block):
  30. def __init__(self, framestate):
  31. Block.__init__(self, framestate.getvariables())
  32. self.framestate = framestate
  33. self.dead = False
  34. def make_recorder(self):
  35. return BlockRecorder(self)
  36. class EggBlock(Block):
  37. def __init__(self, inputargs, prevblock, booloutcome):
  38. Block.__init__(self, inputargs)
  39. self.prevblock = prevblock
  40. self.booloutcome = booloutcome
  41. @property
  42. def ancestor(self):
  43. parent = self.prevblock
  44. while isinstance(parent, EggBlock):
  45. parent = parent.prevblock
  46. return parent
  47. @property
  48. def dead(self):
  49. return self.ancestor.dead
  50. @property
  51. def framestate(self):
  52. return self.ancestor.framestate
  53. def make_recorder(self):
  54. recorder = BlockRecorder(self)
  55. curr = self
  56. while isinstance(curr, EggBlock):
  57. prev = curr.prevblock
  58. recorder = Replayer(prev, curr.booloutcome, recorder)
  59. curr = prev
  60. return recorder
  61. def extravars(self, last_exception=None, last_exc_value=None):
  62. self.last_exception = last_exception
  63. def fixeggblocks(graph):
  64. for block in graph.iterblocks():
  65. if isinstance(block, SpamBlock):
  66. del block.framestate # memory saver
  67. # ____________________________________________________________
  68. class Recorder(object):
  69. def append(self, operation):
  70. raise NotImplementedError
  71. def guessbool(self, ctx, w_condition):
  72. raise AssertionError("cannot guessbool(%s)" % (w_condition,))
  73. class BlockRecorder(Recorder):
  74. # Records all generated operations into a block.
  75. def __init__(self, block):
  76. self.crnt_block = block
  77. # Final frame state after the operations in the block
  78. # If this is set, no new space op may be recorded.
  79. self.final_state = None
  80. def append(self, operation):
  81. self.crnt_block.operations.append(operation)
  82. def guessbool(self, ctx, w_condition):
  83. block = self.crnt_block
  84. links = []
  85. for case in [False, True]:
  86. egg = EggBlock([], block, case)
  87. ctx.pendingblocks.append(egg)
  88. link = Link([], egg, case)
  89. links.append(link)
  90. block.exitswitch = w_condition
  91. block.closeblock(*links)
  92. # forked the graph. Note that False comes before True by default
  93. # in the exits tuple so that (just in case we need it) we
  94. # actually have block.exits[False] = elseLink and
  95. # block.exits[True] = ifLink.
  96. raise StopFlowing
  97. def guessexception(self, ctx, *cases):
  98. block = self.crnt_block
  99. links = []
  100. for case in [None] + list(cases):
  101. if case is not None:
  102. if case is Exception:
  103. last_exc = Variable('last_exception')
  104. else:
  105. last_exc = Constant(case)
  106. last_exc_value = Variable('last_exc_value')
  107. vars = [last_exc, last_exc_value]
  108. vars2 = [Variable(), Variable()]
  109. else:
  110. vars = []
  111. vars2 = []
  112. egg = EggBlock(vars2, block, case)
  113. ctx.pendingblocks.append(egg)
  114. link = Link(vars, egg, case)
  115. if case is not None:
  116. link.extravars(last_exception=last_exc, last_exc_value=last_exc_value)
  117. egg.extravars(last_exception=last_exc)
  118. links.append(link)
  119. block.exitswitch = c_last_exception
  120. block.closeblock(*links)
  121. raise StopFlowing
  122. class Replayer(Recorder):
  123. def __init__(self, block, booloutcome, nextreplayer):
  124. self.crnt_block = block
  125. self.listtoreplay = block.operations
  126. self.booloutcome = booloutcome
  127. self.nextreplayer = nextreplayer
  128. self.index = 0
  129. def append(self, operation):
  130. operation.result = self.listtoreplay[self.index].result
  131. assert operation == self.listtoreplay[self.index], (
  132. '\n'.join(["Not generating the same operation sequence:"] +
  133. [str(s) for s in self.listtoreplay[:self.index]] +
  134. [" ---> | while repeating we see here"] +
  135. [" | %s" % operation] +
  136. [str(s) for s in self.listtoreplay[self.index:]]))
  137. self.index += 1
  138. def guessbool(self, ctx, w_condition):
  139. assert self.index == len(self.listtoreplay)
  140. ctx.recorder = self.nextreplayer
  141. return self.booloutcome
  142. def guessexception(self, ctx, *classes):
  143. assert self.index == len(self.listtoreplay)
  144. ctx.recorder = self.nextreplayer
  145. outcome = self.booloutcome
  146. if outcome is not None:
  147. egg = self.nextreplayer.crnt_block
  148. w_exc_cls, w_exc_value = egg.inputargs[-2:]
  149. if isinstance(egg.last_exception, Constant):
  150. w_exc_cls = egg.last_exception
  151. assert not isinstance(w_exc_cls.value, list)
  152. raise RaiseImplicit(FSException(w_exc_cls, w_exc_value))
  153. # ____________________________________________________________
  154. _unary_ops = [
  155. ('UNARY_POSITIVE', op.pos),
  156. ('UNARY_NEGATIVE', op.neg),
  157. ('UNARY_CONVERT', op.repr),
  158. ('UNARY_INVERT', op.invert),
  159. ]
  160. def unaryoperation(OPCODE, operation):
  161. def UNARY_OP(self, *ignored):
  162. w_1 = self.popvalue()
  163. w_result = operation(w_1).eval(self)
  164. self.pushvalue(w_result)
  165. UNARY_OP.func_name = OPCODE
  166. return UNARY_OP
  167. _binary_ops = [
  168. ('BINARY_MULTIPLY', op.mul),
  169. ('BINARY_TRUE_DIVIDE', op.truediv),
  170. ('BINARY_FLOOR_DIVIDE', op.floordiv),
  171. ('BINARY_DIVIDE', op.div),
  172. ('BINARY_MODULO', op.mod),
  173. ('BINARY_ADD', op.add),
  174. ('BINARY_SUBTRACT', op.sub),
  175. ('BINARY_SUBSCR', op.getitem),
  176. ('BINARY_LSHIFT', op.lshift),
  177. ('BINARY_RSHIFT', op.rshift),
  178. ('BINARY_AND', op.and_),
  179. ('BINARY_XOR', op.xor),
  180. ('BINARY_OR', op.or_),
  181. ('INPLACE_MULTIPLY', op.inplace_mul),
  182. ('INPLACE_TRUE_DIVIDE', op.inplace_truediv),
  183. ('INPLACE_FLOOR_DIVIDE', op.inplace_floordiv),
  184. ('INPLACE_DIVIDE', op.inplace_div),
  185. ('INPLACE_MODULO', op.inplace_mod),
  186. ('INPLACE_ADD', op.inplace_add),
  187. ('INPLACE_SUBTRACT', op.inplace_sub),
  188. ('INPLACE_LSHIFT', op.inplace_lshift),
  189. ('INPLACE_RSHIFT', op.inplace_rshift),
  190. ('INPLACE_AND', op.inplace_and),
  191. ('INPLACE_XOR', op.inplace_xor),
  192. ('INPLACE_OR', op.inplace_or),
  193. ]
  194. def binaryoperation(OPCODE, operation):
  195. """NOT_RPYTHON"""
  196. def BINARY_OP(self, _):
  197. w_2 = self.popvalue()
  198. w_1 = self.popvalue()
  199. w_result = operation(w_1, w_2).eval(self)
  200. self.pushvalue(w_result)
  201. BINARY_OP.func_name = OPCODE
  202. return BINARY_OP
  203. _unsupported_ops = [
  204. ('BINARY_POWER', "a ** b"),
  205. ('BUILD_CLASS', 'defining classes inside functions'),
  206. ('EXEC_STMT', 'exec statement'),
  207. ('STOP_CODE', '???'),
  208. ('STORE_NAME', 'modifying globals'),
  209. ('INPLACE_POWER', 'a **= b'),
  210. ('LOAD_LOCALS', 'locals()'),
  211. ('IMPORT_STAR', 'import *'),
  212. ('MISSING_OPCODE', '???'),
  213. ('DELETE_GLOBAL', 'modifying globals'),
  214. ('DELETE_NAME', 'modifying globals'),
  215. ('DELETE_ATTR', 'deleting attributes'),
  216. ]
  217. def unsupportedoperation(OPCODE, msg):
  218. def UNSUPPORTED(self, *ignored):
  219. raise FlowingError("%s is not RPython" % (msg,))
  220. UNSUPPORTED.func_name = OPCODE
  221. return UNSUPPORTED
  222. compare_method = [
  223. "cmp_lt", # "<"
  224. "cmp_le", # "<="
  225. "cmp_eq", # "=="
  226. "cmp_ne", # "!="
  227. "cmp_gt", # ">"
  228. "cmp_ge", # ">="
  229. "cmp_in",
  230. "cmp_not_in",
  231. "cmp_is",
  232. "cmp_is_not",
  233. "cmp_exc_match",
  234. ]
  235. class FlowContext(object):
  236. def __init__(self, graph, code):
  237. self.graph = graph
  238. func = graph.func
  239. self.pycode = code
  240. self.w_globals = Constant(func.func_globals)
  241. self.blockstack = []
  242. self.init_closure(func.func_closure)
  243. self.f_lineno = code.co_firstlineno
  244. self.last_offset = 0
  245. self.init_locals_stack(code)
  246. self.joinpoints = {}
  247. def init_closure(self, closure):
  248. if closure is None:
  249. self.closure = []
  250. else:
  251. self.closure = list(closure)
  252. assert len(self.closure) == len(self.pycode.co_freevars)
  253. def init_locals_stack(self, code):
  254. """
  255. Initialize the locals and the stack.
  256. The locals are ordered according to self.pycode.signature.
  257. """
  258. self.nlocals = code.co_nlocals
  259. self.locals_w = [None] * code.co_nlocals
  260. self.stack = []
  261. @property
  262. def stackdepth(self):
  263. return len(self.stack)
  264. def pushvalue(self, w_object):
  265. self.stack.append(w_object)
  266. def popvalue(self):
  267. return self.stack.pop()
  268. def peekvalue(self, index_from_top=0):
  269. # NOTE: top of the stack is peekvalue(0).
  270. index = ~index_from_top
  271. return self.stack[index]
  272. def settopvalue(self, w_object, index_from_top=0):
  273. index = ~index_from_top
  274. self.stack[index] = w_object
  275. def popvalues(self, n):
  276. if n == 0:
  277. return []
  278. values_w = self.stack[-n:]
  279. del self.stack[-n:]
  280. return values_w
  281. def dropvaluesuntil(self, finaldepth):
  282. del self.stack[finaldepth:]
  283. def getstate(self, next_offset):
  284. return FrameState(self.locals_w[:], self.stack[:],
  285. self.last_exception, self.blockstack[:], next_offset)
  286. def setstate(self, state):
  287. """ Reset the context to the given frame state. """
  288. self.locals_w = state.locals_w[:]
  289. self.stack = state.stack[:]
  290. self.last_exception = state.last_exception
  291. self.blockstack = state.blocklist[:]
  292. self._normalize_raise_signals()
  293. def _normalize_raise_signals(self):
  294. st = self.stack
  295. for i in range(len(st)):
  296. if isinstance(st[i], RaiseImplicit):
  297. st[i] = Raise(st[i].w_exc)
  298. def guessbool(self, w_condition):
  299. if isinstance(w_condition, Constant):
  300. return w_condition.value
  301. return self.recorder.guessbool(self, w_condition)
  302. def maybe_merge(self):
  303. recorder = self.recorder
  304. if getattr(recorder, 'final_state', None) is not None:
  305. self.mergeblock(recorder.crnt_block, recorder.final_state)
  306. raise StopFlowing
  307. def record(self, spaceop):
  308. spaceop.offset = self.last_offset
  309. self.recorder.append(spaceop)
  310. def do_op(self, op):
  311. self.maybe_merge()
  312. self.record(op)
  313. self.guessexception(op.canraise)
  314. return op.result
  315. def guessexception(self, exceptions):
  316. """
  317. Catch possible exceptions implicitly.
  318. """
  319. if not exceptions:
  320. return
  321. # Implicit exceptions are ignored unless they are caught explicitly
  322. if self.has_exc_handler():
  323. self.recorder.guessexception(self, *exceptions)
  324. def has_exc_handler(self):
  325. return any(isinstance(block, (ExceptBlock, FinallyBlock))
  326. for block in self.blockstack)
  327. def build_flow(self):
  328. graph = self.graph
  329. self.pendingblocks = collections.deque([graph.startblock])
  330. while self.pendingblocks:
  331. block = self.pendingblocks.popleft()
  332. if not block.dead:
  333. self.record_block(block)
  334. def record_block(self, block):
  335. self.setstate(block.framestate)
  336. next_offset = block.framestate.next_offset
  337. self.recorder = block.make_recorder()
  338. try:
  339. while True:
  340. next_offset = self.handle_bytecode(next_offset)
  341. self.recorder.final_state = self.getstate(next_offset)
  342. except StopFlowing:
  343. pass
  344. except FlowingError as exc:
  345. if exc.ctx is None:
  346. exc.ctx = self
  347. raise
  348. self.recorder = None
  349. def mergeblock(self, currentblock, currentstate):
  350. next_offset = currentstate.next_offset
  351. # can 'currentstate' be merged with one of the blocks that
  352. # already exist for this bytecode position?
  353. candidates = self.joinpoints.setdefault(next_offset, [])
  354. for block in candidates:
  355. newstate = block.framestate.union(currentstate)
  356. if newstate is not None:
  357. break
  358. else:
  359. newblock = self.make_next_block(currentblock, currentstate)
  360. candidates.insert(0, newblock)
  361. return
  362. if newstate.matches(block.framestate):
  363. outputargs = currentstate.getoutputargs(newstate)
  364. currentblock.closeblock(Link(outputargs, block))
  365. return
  366. newblock = SpamBlock(newstate)
  367. varnames = self.pycode.co_varnames
  368. for name, w_value in zip(varnames, newstate.locals_w):
  369. if isinstance(w_value, Variable):
  370. w_value.rename(name)
  371. # unconditionally link the current block to the newblock
  372. outputargs = currentstate.getoutputargs(newstate)
  373. link = Link(outputargs, newblock)
  374. currentblock.closeblock(link)
  375. # to simplify the graph, we patch the old block to point
  376. # directly at the new block which is its generalization
  377. block.dead = True
  378. block.operations = ()
  379. block.exitswitch = None
  380. outputargs = block.framestate.getoutputargs(newstate)
  381. block.recloseblock(Link(outputargs, newblock))
  382. candidates.remove(block)
  383. candidates.insert(0, newblock)
  384. self.pendingblocks.append(newblock)
  385. def make_next_block(self, block, state):
  386. newstate = state.copy()
  387. newblock = SpamBlock(newstate)
  388. # unconditionally link the current block to the newblock
  389. outputargs = state.getoutputargs(newstate)
  390. link = Link(outputargs, newblock)
  391. block.closeblock(link)
  392. self.pendingblocks.append(newblock)
  393. return newblock
  394. # hack for unrolling iterables, don't use this
  395. def replace_in_stack(self, oldvalue, newvalue):
  396. w_new = Constant(newvalue)
  397. stack_items_w = self.stack
  398. for i in range(self.stackdepth - 1, - 1, -1):
  399. w_v = stack_items_w[i]
  400. if isinstance(w_v, Constant):
  401. if w_v.value is oldvalue:
  402. # replace the topmost item of the stack that is equal
  403. # to 'oldvalue' with 'newvalue'.
  404. stack_items_w[i] = w_new
  405. break
  406. def handle_bytecode(self, next_offset):
  407. self.last_offset = next_offset
  408. next_offset, methodname, oparg = self.pycode.read(next_offset)
  409. try:
  410. offset = getattr(self, methodname)(oparg)
  411. return offset if offset is not None else next_offset
  412. except FlowSignal as signal:
  413. return self.unroll(signal)
  414. def unroll(self, signal):
  415. while self.blockstack:
  416. block = self.blockstack.pop()
  417. if isinstance(signal, block.handles):
  418. return block.handle(self, signal)
  419. block.cleanupstack(self)
  420. return signal.nomoreblocks(self)
  421. def getlocalvarname(self, index):
  422. return self.pycode.co_varnames[index]
  423. def getconstant_w(self, index):
  424. return const(self.pycode.consts[index])
  425. def getname_u(self, index):
  426. return self.pycode.names[index]
  427. def getname_w(self, index):
  428. return Constant(self.pycode.names[index])
  429. def appcall(self, func, *args_w):
  430. """Call an app-level RPython function directly"""
  431. w_func = const(func)
  432. return self.do_op(op.simple_call(w_func, *args_w))
  433. def BAD_OPCODE(self, _):
  434. raise FlowingError("This operation is not RPython")
  435. def BREAK_LOOP(self, oparg):
  436. raise Break
  437. def CONTINUE_LOOP(self, startofloop):
  438. raise Continue(startofloop)
  439. def not_(self, w_obj):
  440. w_bool = op.bool(w_obj).eval(self)
  441. return const(not self.guessbool(w_bool))
  442. def UNARY_NOT(self, _):
  443. w_obj = self.popvalue()
  444. self.pushvalue(self.not_(w_obj))
  445. def cmp_lt(self, w_1, w_2):
  446. return op.lt(w_1, w_2).eval(self)
  447. def cmp_le(self, w_1, w_2):
  448. return op.le(w_1, w_2).eval(self)
  449. def cmp_eq(self, w_1, w_2):
  450. return op.eq(w_1, w_2).eval(self)
  451. def cmp_ne(self, w_1, w_2):
  452. return op.ne(w_1, w_2).eval(self)
  453. def cmp_gt(self, w_1, w_2):
  454. return op.gt(w_1, w_2).eval(self)
  455. def cmp_ge(self, w_1, w_2):
  456. return op.ge(w_1, w_2).eval(self)
  457. def cmp_in(self, w_1, w_2):
  458. return op.contains(w_2, w_1).eval(self)
  459. def cmp_not_in(self, w_1, w_2):
  460. return self.not_(self.cmp_in(w_1, w_2))
  461. def cmp_is(self, w_1, w_2):
  462. return op.is_(w_1, w_2).eval(self)
  463. def cmp_is_not(self, w_1, w_2):
  464. return self.not_(op.is_(w_1, w_2).eval(self))
  465. def exception_match(self, w_exc_type, w_check_class):
  466. """Checks if the given exception type matches 'w_check_class'."""
  467. if not isinstance(w_check_class, Constant):
  468. raise FlowingError("Non-constant except guard.")
  469. check_class = w_check_class.value
  470. if check_class in (NotImplementedError, AssertionError):
  471. raise FlowingError(
  472. "Catching %s is not valid in RPython" % check_class.__name__)
  473. if not isinstance(check_class, tuple):
  474. # the simple case
  475. return self.guessbool(op.issubtype(w_exc_type, w_check_class).eval(self))
  476. # special case for StackOverflow (see rlib/rstackovf.py)
  477. if check_class == rstackovf.StackOverflow:
  478. w_real_class = const(rstackovf._StackOverflow)
  479. return self.guessbool(op.issubtype(w_exc_type, w_real_class).eval(self))
  480. # checking a tuple of classes
  481. for klass in w_check_class.value:
  482. if self.exception_match(w_exc_type, const(klass)):
  483. return True
  484. return False
  485. def cmp_exc_match(self, w_1, w_2):
  486. return const(self.exception_match(w_1, w_2))
  487. def COMPARE_OP(self, testnum):
  488. w_2 = self.popvalue()
  489. w_1 = self.popvalue()
  490. w_result = getattr(self, compare_method[testnum])(w_1, w_2)
  491. self.pushvalue(w_result)
  492. def exc_from_raise(self, w_arg1, w_arg2):
  493. """
  494. Create a wrapped exception from the arguments of a raise statement.
  495. Returns an FSException object whose w_value is an instance of w_type.
  496. """
  497. w_is_type = op.isinstance(w_arg1, const(type)).eval(self)
  498. if self.guessbool(w_is_type):
  499. # this is for all cases of the form (Class, something)
  500. if self.guessbool(op.is_(w_arg2, w_None).eval(self)):
  501. # raise Type: we assume we have to instantiate Type
  502. w_value = op.simple_call(w_arg1).eval(self)
  503. else:
  504. w_valuetype = op.type(w_arg2).eval(self)
  505. if self.guessbool(op.issubtype(w_valuetype, w_arg1).eval(self)):
  506. # raise Type, Instance: let etype be the exact type of value
  507. w_value = w_arg2
  508. else:
  509. # raise Type, X: assume X is the constructor argument
  510. w_value = op.simple_call(w_arg1, w_arg2).eval(self)
  511. else:
  512. # the only case left here is (inst, None), from a 'raise inst'.
  513. if not self.guessbool(op.is_(w_arg2, const(None)).eval(self)):
  514. exc = TypeError("instance exception may not have a "
  515. "separate value")
  516. raise Raise(const(exc))
  517. w_value = w_arg1
  518. w_type = op.type(w_value).eval(self)
  519. return FSException(w_type, w_value)
  520. def RAISE_VARARGS(self, nbargs):
  521. if nbargs == 0:
  522. if self.last_exception is not None:
  523. w_exc = self.last_exception
  524. else:
  525. w_exc = const(TypeError(
  526. "raise: no active exception to re-raise"))
  527. raise Raise(w_exc)
  528. if nbargs >= 3:
  529. self.popvalue()
  530. if nbargs >= 2:
  531. w_value = self.popvalue()
  532. w_type = self.popvalue()
  533. operror = self.exc_from_raise(w_type, w_value)
  534. else:
  535. w_type = self.popvalue()
  536. operror = self.exc_from_raise(w_type, w_None)
  537. raise Raise(operror)
  538. def import_name(self, name, glob=None, loc=None, frm=None, level=-1):
  539. try:
  540. mod = __import__(name, glob, loc, frm, level)
  541. except ImportError as e:
  542. raise Raise(const(e))
  543. return const(mod)
  544. def IMPORT_NAME(self, nameindex):
  545. modulename = self.getname_u(nameindex)
  546. glob = self.w_globals.value
  547. fromlist = self.popvalue().value
  548. level = self.popvalue().value
  549. w_obj = self.import_name(modulename, glob, None, fromlist, level)
  550. self.pushvalue(w_obj)
  551. def import_from(self, w_module, w_name):
  552. assert isinstance(w_module, Constant)
  553. assert isinstance(w_name, Constant)
  554. try:
  555. return op.getattr(w_module, w_name).eval(self)
  556. except FlowingError:
  557. exc = ImportError("cannot import name '%s'" % w_name.value)
  558. raise Raise(const(exc))
  559. def IMPORT_FROM(self, nameindex):
  560. w_name = self.getname_w(nameindex)
  561. w_module = self.peekvalue()
  562. self.pushvalue(self.import_from(w_module, w_name))
  563. def RETURN_VALUE(self, oparg):
  564. w_returnvalue = self.popvalue()
  565. raise Return(w_returnvalue)
  566. def END_FINALLY(self, oparg):
  567. # unlike CPython, there are two statically distinct cases: the
  568. # END_FINALLY might be closing an 'except' block or a 'finally'
  569. # block. In the first case, the stack contains three items:
  570. # [exception type we are now handling]
  571. # [exception value we are now handling]
  572. # [Raise]
  573. # In the case of a finally: block, the stack contains only one
  574. # item (unlike CPython which can have 1, 2 or 3 items):
  575. # [subclass of FlowSignal]
  576. w_top = self.popvalue()
  577. if w_top == w_None:
  578. # finally: block with no unroller active
  579. return
  580. elif isinstance(w_top, FlowSignal):
  581. # case of a finally: block
  582. raise w_top
  583. else:
  584. # case of an except: block. We popped the exception type
  585. self.popvalue() # Now we pop the exception value
  586. signal = self.popvalue()
  587. raise signal
  588. def POP_BLOCK(self, oparg):
  589. block = self.blockstack.pop()
  590. block.cleanupstack(self) # the block knows how to clean up the value stack
  591. def JUMP_ABSOLUTE(self, jumpto):
  592. return jumpto
  593. def YIELD_VALUE(self, _):
  594. assert self.pycode.is_generator
  595. w_result = self.popvalue()
  596. op.yield_(w_result).eval(self)
  597. # XXX yield expressions not supported. This will blow up if the value
  598. # isn't popped straightaway.
  599. self.pushvalue(None)
  600. PRINT_EXPR = BAD_OPCODE
  601. PRINT_ITEM_TO = BAD_OPCODE
  602. PRINT_NEWLINE_TO = BAD_OPCODE
  603. def PRINT_ITEM(self, oparg):
  604. w_item = self.popvalue()
  605. w_s = op.str(w_item).eval(self)
  606. self.appcall(rpython_print_item, w_s)
  607. def PRINT_NEWLINE(self, oparg):
  608. self.appcall(rpython_print_newline)
  609. def JUMP_FORWARD(self, target):
  610. return target
  611. def JUMP_IF_FALSE(self, target):
  612. # Python <= 2.6 only
  613. w_cond = self.peekvalue()
  614. if not self.guessbool(op.bool(w_cond).eval(self)):
  615. return target
  616. def JUMP_IF_TRUE(self, target):
  617. # Python <= 2.6 only
  618. w_cond = self.peekvalue()
  619. if self.guessbool(op.bool(w_cond).eval(self)):
  620. return target
  621. def POP_JUMP_IF_FALSE(self, target):
  622. w_value = self.popvalue()
  623. if not self.guessbool(op.bool(w_value).eval(self)):
  624. return target
  625. def POP_JUMP_IF_TRUE(self, target):
  626. w_value = self.popvalue()
  627. if self.guessbool(op.bool(w_value).eval(self)):
  628. return target
  629. def JUMP_IF_FALSE_OR_POP(self, target):
  630. w_value = self.peekvalue()
  631. if not self.guessbool(op.bool(w_value).eval(self)):
  632. return target
  633. self.popvalue()
  634. def JUMP_IF_TRUE_OR_POP(self, target):
  635. w_value = self.peekvalue()
  636. if self.guessbool(op.bool(w_value).eval(self)):
  637. return target
  638. return target
  639. self.popvalue()
  640. def JUMP_IF_NOT_DEBUG(self, target):
  641. pass
  642. def GET_ITER(self, oparg):
  643. w_iterable = self.popvalue()
  644. w_iterator = op.iter(w_iterable).eval(self)
  645. self.pushvalue(w_iterator)
  646. def FOR_ITER(self, target):
  647. w_iterator = self.peekvalue()
  648. self.blockstack.append(IterBlock(self, target))
  649. w_nextitem = op.next(w_iterator).eval(self)
  650. self.blockstack.pop()
  651. self.pushvalue(w_nextitem)
  652. def SETUP_LOOP(self, target):
  653. block = LoopBlock(self, target)
  654. self.blockstack.append(block)
  655. def SETUP_EXCEPT(self, target):
  656. block = ExceptBlock(self, target)
  657. self.blockstack.append(block)
  658. def SETUP_FINALLY(self, target):
  659. block = FinallyBlock(self, target)
  660. self.blockstack.append(block)
  661. def SETUP_WITH(self, target):
  662. # A simpler version than the 'real' 2.7 one:
  663. # directly call manager.__enter__(), don't use special lookup functions
  664. # which don't make sense on the RPython type system.
  665. w_manager = self.peekvalue()
  666. w_exit = op.getattr(w_manager, const("__exit__")).eval(self)
  667. self.settopvalue(w_exit)
  668. w_enter = op.getattr(w_manager, const('__enter__')).eval(self)
  669. w_result = op.simple_call(w_enter).eval(self)
  670. block = WithBlock(self, target)
  671. self.blockstack.append(block)
  672. self.pushvalue(w_result)
  673. def WITH_CLEANUP(self, oparg):
  674. # Note: RPython context managers receive None in lieu of tracebacks
  675. # and cannot suppress the exception.
  676. unroller = self.popvalue()
  677. w_exitfunc = self.popvalue()
  678. self.pushvalue(unroller)
  679. if isinstance(unroller, Raise):
  680. w_exc = unroller.w_exc
  681. # The annotator won't allow to merge exception types with None.
  682. # Replace it with the exception value...
  683. op.simple_call(w_exitfunc, w_exc.w_value, w_exc.w_value, w_None
  684. ).eval(self)
  685. else:
  686. op.simple_call(w_exitfunc, w_None, w_None, w_None).eval(self)
  687. def LOAD_FAST(self, varindex):
  688. w_value = self.locals_w[varindex]
  689. if w_value is None:
  690. raise FlowingError("Local variable referenced before assignment")
  691. self.pushvalue(w_value)
  692. def LOAD_CONST(self, constindex):
  693. w_const = self.getconstant_w(constindex)
  694. self.pushvalue(w_const)
  695. def find_global(self, w_globals, varname):
  696. try:
  697. value = w_globals.value[varname]
  698. except KeyError:
  699. # not in the globals, now look in the built-ins
  700. try:
  701. value = getattr(__builtin__, varname)
  702. except AttributeError:
  703. raise FlowingError("global name '%s' is not defined" % varname)
  704. return const(value)
  705. def LOAD_GLOBAL(self, nameindex):
  706. w_result = self.find_global(self.w_globals, self.getname_u(nameindex))
  707. self.pushvalue(w_result)
  708. LOAD_NAME = LOAD_GLOBAL
  709. def LOAD_ATTR(self, nameindex):
  710. "obj.attributename"
  711. w_obj = self.popvalue()
  712. w_attributename = self.getname_w(nameindex)
  713. w_value = op.getattr(w_obj, w_attributename).eval(self)
  714. self.pushvalue(w_value)
  715. LOOKUP_METHOD = LOAD_ATTR
  716. def LOAD_DEREF(self, varindex):
  717. cell = self.closure[varindex]
  718. try:
  719. content = cell.cell_contents
  720. except ValueError:
  721. name = self.pycode.co_freevars[varindex]
  722. raise FlowingError("Undefined closure variable '%s'" % name)
  723. self.pushvalue(const(content))
  724. def STORE_FAST(self, varindex):
  725. w_newvalue = self.popvalue()
  726. assert w_newvalue is not None
  727. self.locals_w[varindex] = w_newvalue
  728. if isinstance(w_newvalue, Variable):
  729. w_newvalue.rename(self.getlocalvarname(varindex))
  730. def STORE_GLOBAL(self, nameindex):
  731. varname = self.getname_u(nameindex)
  732. raise FlowingError(
  733. "Attempting to modify global variable %r." % (varname))
  734. def POP_TOP(self, oparg):
  735. self.popvalue()
  736. def ROT_TWO(self, oparg):
  737. w_1 = self.popvalue()
  738. w_2 = self.popvalue()
  739. self.pushvalue(w_1)
  740. self.pushvalue(w_2)
  741. def ROT_THREE(self, oparg):
  742. w_1 = self.popvalue()
  743. w_2 = self.popvalue()
  744. w_3 = self.popvalue()
  745. self.pushvalue(w_1)
  746. self.pushvalue(w_3)
  747. self.pushvalue(w_2)
  748. def ROT_FOUR(self, oparg):
  749. w_1 = self.popvalue()
  750. w_2 = self.popvalue()
  751. w_3 = self.popvalue()
  752. w_4 = self.popvalue()
  753. self.pushvalue(w_1)
  754. self.pushvalue(w_4)
  755. self.pushvalue(w_3)
  756. self.pushvalue(w_2)
  757. def DUP_TOP(self, oparg):
  758. w_1 = self.peekvalue()
  759. self.pushvalue(w_1)
  760. def DUP_TOPX(self, itemcount):
  761. delta = itemcount - 1
  762. while True:
  763. itemcount -= 1
  764. if itemcount < 0:
  765. break
  766. w_value = self.peekvalue(delta)
  767. self.pushvalue(w_value)
  768. for OPCODE, op in _unary_ops:
  769. locals()[OPCODE] = unaryoperation(OPCODE, op)
  770. for OPCODE, op in _binary_ops:
  771. locals()[OPCODE] = binaryoperation(OPCODE, op)
  772. for OPCODE, op in _unsupported_ops:
  773. locals()[OPCODE] = unsupportedoperation(OPCODE, op)
  774. def BUILD_LIST_FROM_ARG(self, _):
  775. # This opcode was added with pypy-1.8. Here is a simpler
  776. # version, enough for annotation.
  777. last_val = self.popvalue()
  778. self.pushvalue(op.newlist().eval(self))
  779. self.pushvalue(last_val)
  780. def call_function(self, oparg, w_star=None, w_starstar=None):
  781. if w_starstar is not None:
  782. raise FlowingError("Dict-unpacking is not RPython")
  783. n_arguments = oparg & 0xff
  784. n_keywords = (oparg >> 8) & 0xff
  785. keywords = {}
  786. for _ in range(n_keywords):
  787. w_value = self.popvalue()
  788. w_key = self.popvalue()
  789. key = w_key.value
  790. keywords[key] = w_value
  791. arguments = self.popvalues(n_arguments)
  792. args = CallSpec(arguments, keywords, w_star)
  793. w_function = self.popvalue()
  794. if args.keywords or isinstance(args.w_stararg, Variable):
  795. shape, args_w = args.flatten()
  796. hlop = op.call_args(w_function, Constant(shape), *args_w)
  797. else:
  798. hlop = op.simple_call(w_function, *args.as_list())
  799. self.pushvalue(hlop.eval(self))
  800. def CALL_FUNCTION(self, oparg):
  801. self.call_function(oparg)
  802. CALL_METHOD = CALL_FUNCTION
  803. def CALL_FUNCTION_VAR(self, oparg):
  804. w_varargs = self.popvalue()
  805. self.call_function(oparg, w_varargs)
  806. def CALL_FUNCTION_KW(self, oparg):
  807. w_varkw = self.popvalue()
  808. self.call_function(oparg, None, w_varkw)
  809. def CALL_FUNCTION_VAR_KW(self, oparg):
  810. w_varkw = self.popvalue()
  811. w_varargs = self.popvalue()
  812. self.call_function(oparg, w_varargs, w_varkw)
  813. def newfunction(self, w_code, defaults_w):
  814. if not all(isinstance(value, Constant) for value in defaults_w):
  815. raise FlowingError("Dynamically created function must"
  816. " have constant default values.")
  817. code = w_code.value
  818. globals = self.w_globals.value
  819. defaults = tuple([default.value for default in defaults_w])
  820. fn = types.FunctionType(code, globals, code.co_name, defaults)
  821. return Constant(fn)
  822. def MAKE_FUNCTION(self, numdefaults):
  823. w_codeobj = self.popvalue()
  824. defaults = self.popvalues(numdefaults)
  825. fn = self.newfunction(w_codeobj, defaults)
  826. self.pushvalue(fn)
  827. def STORE_ATTR(self, nameindex):
  828. "obj.attributename = newvalue"
  829. w_attributename = self.getname_w(nameindex)
  830. w_obj = self.popvalue()
  831. w_newvalue = self.popvalue()
  832. op.setattr(w_obj, w_attributename, w_newvalue).eval(self)
  833. def unpack_sequence(self, w_iterable, expected_length):
  834. w_len = op.len(w_iterable).eval(self)
  835. w_correct = op.eq(w_len, const(expected_length)).eval(self)
  836. if not self.guessbool(op.bool(w_correct).eval(self)):
  837. w_exc = self.exc_from_raise(const(ValueError), const(None))
  838. raise Raise(w_exc)
  839. return [op.getitem(w_iterable, const(i)).eval(self)
  840. for i in range(expected_length)]
  841. def UNPACK_SEQUENCE(self, itemcount):
  842. w_iterable = self.popvalue()
  843. items = self.unpack_sequence(w_iterable, itemcount)
  844. for w_item in reversed(items):
  845. self.pushvalue(w_item)
  846. def slice(self, w_start, w_end):
  847. w_obj = self.popvalue()
  848. w_result = op.getslice(w_obj, w_start, w_end).eval(self)
  849. self.pushvalue(w_result)
  850. def SLICE_0(self, oparg):
  851. self.slice(w_None, w_None)
  852. def SLICE_1(self, oparg):
  853. w_start = self.popvalue()
  854. self.slice(w_start, w_None)
  855. def SLICE_2(self, oparg):
  856. w_end = self.popvalue()
  857. self.slice(w_None, w_end)
  858. def SLICE_3(self, oparg):
  859. w_end = self.popvalue()
  860. w_start = self.popvalue()
  861. self.slice(w_start, w_end)
  862. def storeslice(self, w_start, w_end):
  863. w_obj = self.popvalue()
  864. w_newvalue = self.popvalue()
  865. op.setslice(w_obj, w_start, w_end, w_newvalue).eval(self)
  866. def STORE_SLICE_0(self, oparg):
  867. self.storeslice(w_None, w_None)
  868. def STORE_SLICE_1(self, oparg):
  869. w_start = self.popvalue()
  870. self.storeslice(w_start, w_None)
  871. def STORE_SLICE_2(self, oparg):
  872. w_end = self.popvalue()
  873. self.storeslice(w_None, w_end)
  874. def STORE_SLICE_3(self, oparg):
  875. w_end = self.popvalue()
  876. w_start = self.popvalue()
  877. self.storeslice(w_start, w_end)
  878. def deleteslice(self, w_start, w_end):
  879. w_obj = self.popvalue()
  880. op.delslice(w_obj, w_start, w_end).eval(self)
  881. def DELETE_SLICE_0(self, oparg):
  882. self.deleteslice(w_None, w_None)
  883. def DELETE_SLICE_1(self, oparg):
  884. w_start = self.popvalue()
  885. self.deleteslice(w_start, w_None)
  886. def DELETE_SLICE_2(self, oparg):
  887. w_end = self.popvalue()
  888. self.deleteslice(w_None, w_end)
  889. def DELETE_SLICE_3(self, oparg):
  890. w_end = self.popvalue()
  891. w_start = self.popvalue()
  892. self.deleteslice(w_start, w_end)
  893. def LIST_APPEND(self, oparg):
  894. w_value = self.popvalue()
  895. if sys.version_info < (2, 7):
  896. w_list = self.popvalue()
  897. else:
  898. w_list = self.peekvalue(oparg - 1)
  899. w_append_meth = op.getattr(w_list, const('append')).eval(self)
  900. op.simple_call(w_append_meth, w_value).eval(self)
  901. def DELETE_FAST(self, varindex):
  902. if self.locals_w[varindex] is None:
  903. varname = self.getlocalvarname(varindex)
  904. message = "local variable '%s' referenced before assignment"
  905. raise UnboundLocalError(message, varname)
  906. self.locals_w[varindex] = None
  907. def STORE_MAP(self, oparg):
  908. w_key = self.popvalue()
  909. w_value = self.popvalue()
  910. w_dict = self.peekvalue()
  911. op.setitem(w_dict, w_key, w_value).eval(self)
  912. def STORE_SUBSCR(self, oparg):
  913. "obj[subscr] = newvalue"
  914. w_subscr = self.popvalue()
  915. w_obj = self.popvalue()
  916. w_newvalue = self.popvalue()
  917. op.setitem(w_obj, w_subscr, w_newvalue).eval(self)
  918. def BUILD_SLICE(self, numargs):
  919. if numargs == 3:
  920. w_step = self.popvalue()
  921. elif numargs == 2:
  922. w_step = w_None
  923. else:
  924. raise BytecodeCorruption
  925. w_end = self.popvalue()
  926. w_start = self.popvalue()
  927. w_slice = op.newslice(w_start, w_end, w_step).eval(self)
  928. self.pushvalue(w_slice)
  929. def DELETE_SUBSCR(self, oparg):
  930. "del obj[subscr]"
  931. w_subscr = self.popvalue()
  932. w_obj = self.popvalue()
  933. op.delitem(w_obj, w_subscr).eval(self)
  934. def BUILD_TUPLE(self, itemcount):
  935. items = self.popvalues(itemcount)
  936. w_tuple = op.newtuple(*items).eval(self)
  937. self.pushvalue(w_tuple)
  938. def BUILD_LIST(self, itemcount):
  939. items = self.popvalues(itemcount)
  940. w_list = op.newlist(*items).eval(self)
  941. self.pushvalue(w_list)
  942. def BUILD_MAP(self, itemcount):
  943. w_dict = op.newdict().eval(self)
  944. self.pushvalue(w_dict)
  945. def NOP(self, *args):
  946. pass
  947. # XXX Unimplemented 2.7 opcodes ----------------
  948. # Set literals, set comprehensions
  949. def BUILD_SET(self, oparg):
  950. raise NotImplementedError("BUILD_SET")
  951. def SET_ADD(self, oparg):
  952. raise NotImplementedError("SET_ADD")
  953. # Dict comprehensions
  954. def MAP_ADD(self, oparg):
  955. raise NotImplementedError("MAP_ADD")
  956. # Closures
  957. STORE_DEREF = BAD_OPCODE
  958. LOAD_CLOSURE = BAD_OPCODE
  959. MAKE_CLOSURE = BAD_OPCODE
  960. ### Frame blocks ###
  961. class FlowSignal(Exception):
  962. """Abstract base class for translator-level objects that instruct the
  963. interpreter to change the control flow and the block stack.
  964. The concrete subclasses correspond to the various values WHY_XXX
  965. values of the why_code enumeration in ceval.c:
  966. WHY_NOT, OK, not this one :-)
  967. WHY_EXCEPTION, Raise
  968. WHY_RERAISE, implemented differently, see Reraise
  969. WHY_RETURN, Return
  970. WHY_BREAK, Break
  971. WHY_CONTINUE, Continue
  972. WHY_YIELD not needed
  973. """
  974. def nomoreblocks(self, ctx):
  975. raise BytecodeCorruption("misplaced bytecode - should not return")
  976. def __eq__(self, other):
  977. return type(other) is type(self) and other.args == self.args
  978. class Return(FlowSignal):
  979. """Signals a 'return' statement.
  980. Argument is the wrapped object to return.
  981. """
  982. def __init__(self, w_value):
  983. self.w_value = w_value
  984. def nomoreblocks(self, ctx):
  985. w_result = self.w_value
  986. link = Link([w_result], ctx.graph.returnblock)
  987. ctx.recorder.crnt_block.closeblock(link)
  988. raise StopFlowing
  989. @property
  990. def args(self):
  991. return [self.w_value]
  992. @staticmethod
  993. def rebuild(w_value):
  994. return Return(w_value)
  995. class Raise(FlowSignal):
  996. """Signals an application-level exception
  997. (i.e. an OperationException)."""
  998. def __init__(self, w_exc):
  999. self.w_exc = w_exc
  1000. def nomoreblocks(self, ctx):
  1001. w_exc = self.w_exc
  1002. if w_exc.w_type == const(ImportError):
  1003. msg = 'ImportError is raised in RPython: %s' % (
  1004. getattr(w_exc.w_value, 'value', '<not a constant message>'),)
  1005. raise ImportError(msg)
  1006. link = Link([w_exc.w_type, w_exc.w_value], ctx.graph.exceptblock)
  1007. ctx.recorder.crnt_block.closeblock(link)
  1008. raise StopFlowing
  1009. @property
  1010. def args(self):
  1011. return [self.w_exc.w_type, self.w_exc.w_value]
  1012. @classmethod
  1013. def rebuild(cls, w_type, w_value):
  1014. return cls(FSException(w_type, w_value))
  1015. class RaiseImplicit(Raise):
  1016. """Signals an exception raised implicitly"""
  1017. def nomoreblocks(self, ctx):
  1018. w_exc = self.w_exc
  1019. if isinstance(w_exc.w_type, Constant):
  1020. exc_cls = w_exc.w_type.value
  1021. else:
  1022. exc_cls = Exception
  1023. msg = "implicit %s shouldn't occur" % exc_cls.__name__
  1024. w_type = Constant(AssertionError)
  1025. w_value = Constant(AssertionError(msg))
  1026. link = Link([w_type, w_value], ctx.graph.exceptblock)
  1027. ctx.recorder.crnt_block.closeblock(link)
  1028. raise StopFlowing
  1029. class Break(FlowSignal):
  1030. """Signals a 'break' statement."""
  1031. @property
  1032. def args(self):
  1033. return []
  1034. @staticmethod
  1035. def rebuild():
  1036. return Break.singleton
  1037. Break.singleton = Break()
  1038. class Continue(FlowSignal):
  1039. """Signals a 'continue' statement.
  1040. Argument is the bytecode position of the beginning of the loop."""
  1041. def __init__(self, jump_to):
  1042. self.jump_to = jump_to
  1043. @property
  1044. def args(self):
  1045. return [const(self.jump_to)]
  1046. @staticmethod
  1047. def rebuild(w_jump_to):
  1048. return Continue(w_jump_to.value)
  1049. class FrameBlock(object):
  1050. """Abstract base class for frame blocks from the blockstack,
  1051. used by the SETUP_XXX and POP_BLOCK opcodes."""
  1052. def __init__(self, ctx, handlerposition):
  1053. self.handlerposition = handlerposition
  1054. self.stackdepth = ctx.stackdepth
  1055. def __eq__(self, other):
  1056. return (self.__class__ is other.__class__ and
  1057. self.handlerposition == other.handlerposition and
  1058. self.stackdepth == other.stackdepth)
  1059. def __ne__(self, other):
  1060. return not (self == other)
  1061. def __hash__(self):
  1062. return hash((self.handlerposition, self.stackdepth))
  1063. def cleanupstack(self, ctx):
  1064. ctx.dropvaluesuntil(self.stackdepth)
  1065. def handle(self, ctx, unroller):
  1066. raise NotImplementedError
  1067. class LoopBlock(FrameBlock):
  1068. """A loop block. Stores the end-of-loop pointer in case of 'break'."""
  1069. handles = (Break, Continue)
  1070. def handle(self, ctx, unroller):
  1071. if isinstance(unroller, Continue):
  1072. # re-push the loop block without cleaning up the value stack,
  1073. # and jump to the beginning of the loop, stored in the
  1074. # exception's argument
  1075. ctx.blockstack.append(self)
  1076. return unroller.jump_to
  1077. else:
  1078. # jump to the end of the loop
  1079. self.cleanupstack(ctx)
  1080. return self.handlerposition
  1081. class ExceptBlock(FrameBlock):
  1082. """An try:except: block. Stores the position of the exception handler."""
  1083. handles = Raise
  1084. def handle(self, ctx, unroller):
  1085. # push the exception to the value stack for inspection by the
  1086. # exception handler (the code after the except:)
  1087. self.cleanupstack(ctx)
  1088. assert isinstance(unroller, Raise)
  1089. w_exc = unroller.w_exc
  1090. # the stack setup is slightly different than in CPython:
  1091. # instead of the traceback, we store the unroller object,
  1092. # wrapped.
  1093. ctx.pushvalue(unroller)
  1094. ctx.pushvalue(w_exc.w_value)
  1095. ctx.pushvalue(w_exc.w_type)
  1096. ctx.last_exception = w_exc
  1097. return self.handlerposition # jump to the handler
  1098. class IterBlock(ExceptBlock):
  1099. """A pseudo-block to catch the StopIteration inside FOR_ITER"""
  1100. def handle(self, ctx, unroller):
  1101. w_exc = unroller.w_exc
  1102. if ctx.exception_match(w_exc.w_type, const(StopIteration)):
  1103. ctx.popvalue()
  1104. return self.handlerposition
  1105. else:
  1106. return ctx.unroll(unroller)
  1107. class FinallyBlock(FrameBlock):
  1108. """A try:finally: block. Stores the position of the exception handler."""
  1109. handles = FlowSignal
  1110. def handle(self, ctx, unroller):
  1111. # any abnormal reason for unrolling a finally: triggers the end of
  1112. # the block unrolling and the entering the finally: handler.
  1113. self.cleanupstack(ctx)
  1114. ctx.pushvalue(unroller)
  1115. return self.handlerposition # jump to the handler
  1116. class WithBlock(FinallyBlock):
  1117. def handle(self, ctx, unroller):
  1118. return FinallyBlock.handle(self, ctx, unroller)