summaryrefslogtreecommitdiff
path: root/coverage/parser.py
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2009-12-20 11:03:33 -0500
committerNed Batchelder <ned@nedbatchelder.com>2009-12-20 11:03:33 -0500
commita81c9c2598e4beb00f64e0fb994561e9f7b66b01 (patch)
tree34e0356821fc246fe5bede7a340727efaa26f8e4 /coverage/parser.py
parent4d117fd6de4a9307d8033be5392984302b8c259d (diff)
downloadpython-coveragepy-a81c9c2598e4beb00f64e0fb994561e9f7b66b01.tar.gz
Jumps to jumps could make loops look like they go places they really don't, so start new chunks for every absolute jump. Fixes issue #39.
Diffstat (limited to 'coverage/parser.py')
-rw-r--r--coverage/parser.py15
1 files changed, 14 insertions, 1 deletions
diff --git a/coverage/parser.py b/coverage/parser.py
index cf46218..aea05f3 100644
--- a/coverage/parser.py
+++ b/coverage/parser.py
@@ -256,6 +256,11 @@ OPS_CHUNK_END = _opcode_set(
'BREAK_LOOP', 'CONTINUE_LOOP',
)
+# Opcodes that unconditionally begin a new code chunk. By starting new chunks
+# with unconditional jump instructions, we neatly deal with jumps to jumps
+# properly.
+OPS_CHUNK_BEGIN = _opcode_set('JUMP_ABSOLUTE', 'JUMP_FORWARD')
+
# Opcodes that push a block on the block stack.
OPS_PUSH_BLOCK = _opcode_set('SETUP_LOOP', 'SETUP_EXCEPT', 'SETUP_FINALLY')
@@ -399,12 +404,20 @@ class ByteParser(object):
ult = penult = None
for bc in ByteCodes(self.code.co_code):
- # Maybe have to start a new block
+ # Maybe have to start a new chunk
if bc.offset in bytes_lines_map:
+ # Start a new chunk for each source line number.
if chunk:
chunk.exits.add(bc.offset)
chunk = Chunk(bc.offset, bytes_lines_map[bc.offset])
chunks.append(chunk)
+ elif bc.op in OPS_CHUNK_BEGIN:
+ # Jumps deserve their own unnumbered chunk. This fixes
+ # problems with jumps to jumps getting confused.
+ if chunk:
+ chunk.exits.add(bc.offset)
+ chunk = Chunk(bc.offset)
+ chunks.append(chunk)
if not chunk:
chunk = Chunk(bc.offset)