summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/compiler/pyassem.py41
-rw-r--r--Lib/compiler/pycodegen.py8
-rw-r--r--Tools/compiler/compiler/pyassem.py41
-rw-r--r--Tools/compiler/compiler/pycodegen.py8
4 files changed, 64 insertions, 34 deletions
diff --git a/Lib/compiler/pyassem.py b/Lib/compiler/pyassem.py
index c8d9e90..74ea562 100644
--- a/Lib/compiler/pyassem.py
+++ b/Lib/compiler/pyassem.py
@@ -419,21 +419,32 @@ class LineAddrTable:
# compute deltas
addr = self.codeOffset - self.lastoff
line = lineno - self.lastline
- while addr > 0 or line > 0:
- # write the values in 1-byte chunks that sum
- # to desired value
- trunc_addr = addr
- trunc_line = line
- if trunc_addr > 255:
- trunc_addr = 255
- if trunc_line > 255:
- trunc_line = 255
- self.lnotab.append(trunc_addr)
- self.lnotab.append(trunc_line)
- addr = addr - trunc_addr
- line = line - trunc_line
- self.lastline = lineno
- self.lastoff = self.codeOffset
+ # Python assumes that lineno always increases with
+ # increasing bytecode address (lnotab is unsigned char).
+ # Depending on when SET_LINENO instructions are emitted
+ # this is not always true. Consider the code:
+ # a = (1,
+ # b)
+ # In the bytecode stream, the assignment to "a" occurs
+ # after the loading of "b". This works with the C Python
+ # compiler because it only generates a SET_LINENO instruction
+ # for the assignment.
+ if line > 0:
+ while addr > 0 or line > 0:
+ # write the values in 1-byte chunks that sum
+ # to desired value
+ trunc_addr = addr
+ trunc_line = line
+ if trunc_addr > 255:
+ trunc_addr = 255
+ if trunc_line > 255:
+ trunc_line = 255
+ self.lnotab.append(trunc_addr)
+ self.lnotab.append(trunc_line)
+ addr = addr - trunc_addr
+ line = line - trunc_line
+ self.lastline = lineno
+ self.lastoff = self.codeOffset
def getCode(self):
return string.join(self.code, '')
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py
index a4c9e5b..2a1b308 100644
--- a/Lib/compiler/pycodegen.py
+++ b/Lib/compiler/pycodegen.py
@@ -70,6 +70,7 @@ class CodeGenerator:
self.loops = misc.Stack()
self.curStack = 0
self.maxStack = 0
+ self.last_lineno = None
self._setupGraphDelegation()
def _setupGraphDelegation(self):
@@ -107,7 +108,8 @@ class CodeGenerator:
self.emit(prefix + '_GLOBAL', name)
def set_lineno(self, node):
- """Emit SET_LINENO if node has lineno attribute
+ """Emit SET_LINENO if node has lineno attribute and it is
+ different than the last lineno emitted.
Returns true if SET_LINENO was emitted.
@@ -117,8 +119,9 @@ class CodeGenerator:
then, this method works around missing line numbers.
"""
lineno = getattr(node, 'lineno', None)
- if lineno is not None:
+ if lineno is not None and lineno != self.last_lineno:
self.emit('SET_LINENO', lineno)
+ self.last_lineno = lineno
return 1
return 0
@@ -414,6 +417,7 @@ class CodeGenerator:
pass
def visitName(self, node):
+ self.set_lineno(node)
self.loadName(node.name)
def visitPass(self, node):
diff --git a/Tools/compiler/compiler/pyassem.py b/Tools/compiler/compiler/pyassem.py
index c8d9e90..74ea562 100644
--- a/Tools/compiler/compiler/pyassem.py
+++ b/Tools/compiler/compiler/pyassem.py
@@ -419,21 +419,32 @@ class LineAddrTable:
# compute deltas
addr = self.codeOffset - self.lastoff
line = lineno - self.lastline
- while addr > 0 or line > 0:
- # write the values in 1-byte chunks that sum
- # to desired value
- trunc_addr = addr
- trunc_line = line
- if trunc_addr > 255:
- trunc_addr = 255
- if trunc_line > 255:
- trunc_line = 255
- self.lnotab.append(trunc_addr)
- self.lnotab.append(trunc_line)
- addr = addr - trunc_addr
- line = line - trunc_line
- self.lastline = lineno
- self.lastoff = self.codeOffset
+ # Python assumes that lineno always increases with
+ # increasing bytecode address (lnotab is unsigned char).
+ # Depending on when SET_LINENO instructions are emitted
+ # this is not always true. Consider the code:
+ # a = (1,
+ # b)
+ # In the bytecode stream, the assignment to "a" occurs
+ # after the loading of "b". This works with the C Python
+ # compiler because it only generates a SET_LINENO instruction
+ # for the assignment.
+ if line > 0:
+ while addr > 0 or line > 0:
+ # write the values in 1-byte chunks that sum
+ # to desired value
+ trunc_addr = addr
+ trunc_line = line
+ if trunc_addr > 255:
+ trunc_addr = 255
+ if trunc_line > 255:
+ trunc_line = 255
+ self.lnotab.append(trunc_addr)
+ self.lnotab.append(trunc_line)
+ addr = addr - trunc_addr
+ line = line - trunc_line
+ self.lastline = lineno
+ self.lastoff = self.codeOffset
def getCode(self):
return string.join(self.code, '')
diff --git a/Tools/compiler/compiler/pycodegen.py b/Tools/compiler/compiler/pycodegen.py
index a4c9e5b..2a1b308 100644
--- a/Tools/compiler/compiler/pycodegen.py
+++ b/Tools/compiler/compiler/pycodegen.py
@@ -70,6 +70,7 @@ class CodeGenerator:
self.loops = misc.Stack()
self.curStack = 0
self.maxStack = 0
+ self.last_lineno = None
self._setupGraphDelegation()
def _setupGraphDelegation(self):
@@ -107,7 +108,8 @@ class CodeGenerator:
self.emit(prefix + '_GLOBAL', name)
def set_lineno(self, node):
- """Emit SET_LINENO if node has lineno attribute
+ """Emit SET_LINENO if node has lineno attribute and it is
+ different than the last lineno emitted.
Returns true if SET_LINENO was emitted.
@@ -117,8 +119,9 @@ class CodeGenerator:
then, this method works around missing line numbers.
"""
lineno = getattr(node, 'lineno', None)
- if lineno is not None:
+ if lineno is not None and lineno != self.last_lineno:
self.emit('SET_LINENO', lineno)
+ self.last_lineno = lineno
return 1
return 0
@@ -414,6 +417,7 @@ class CodeGenerator:
pass
def visitName(self, node):
+ self.set_lineno(node)
self.loadName(node.name)
def visitPass(self, node):