[Jython-checkins] jython: Updated CPython bytecode (.pyc-files) support to bytecode-version 2.7

stefan.richthofer jython-checkins at python.org
Fri Nov 25 11:27:16 EST 2016


https://hg.python.org/jython/rev/bf9d77e286ac
changeset:   7972:bf9d77e286ac
user:        Stefan Richthofer <stefan.richthofer at gmx.de>
date:        Fri Nov 25 17:26:29 2016 +0100
summary:
  Updated CPython bytecode (.pyc-files) support to bytecode-version 2.7 (compliant with magic number 62211). Fixes #2533 and prepares for #527524. pycimport.py now checks for the right magic number; previously it just attempted to run incompatible bytecode, potentially yielding undefined behavior.

files:
  Lib/pycimport.py                       |   12 +
  NEWS                                   |    2 +
  src/org/python/compiler/ClassFile.java |   45 +-
  src/org/python/core/Opcode.java        |  290 +++---
  src/org/python/core/PyBytecode.java    |  492 +++++++-----
  5 files changed, 472 insertions(+), 369 deletions(-)


diff --git a/Lib/pycimport.py b/Lib/pycimport.py
--- a/Lib/pycimport.py
+++ b/Lib/pycimport.py
@@ -5,6 +5,9 @@
 
 __debugging__ = False
 
+# Todo: This should be stored in a central place.
+supported_magic = 62211 # CPython 2.7
+
 def __readPycHeader(file):
     def read():
         return ord(file.read(1))
@@ -26,6 +29,7 @@
     def __init__(self, path):
         if __debugging__: print "Importer invoked"
         self.__path = path
+
     def find_module(self, fullname, path=None):
         if __debugging__:
             print "Importer.find_module(fullname=%s, path=%s)" % (
@@ -42,6 +46,9 @@
             except:
                 return None # abort! not a valid pyc-file
             f.close()
+            # Todo: This check should also be in Unmarshaller
+            if magic != supported_magic:
+                return None # bytecode version mismatch
             if os.path.exists(pyfile):
                 pytime = os.stat(pyfile).st_mtime
                 if pytime > mtime:
@@ -49,12 +56,16 @@
             return self
         else:
             return None # abort! pyc-file does not exist
+
     def load_module(self, fullname):
         path = fullname.split('.')
         path[-1] += '.pyc'
         filename = os.path.join(self.__path, *path)
         f = open(filename, 'rb')
         magic, mtime = __readPycHeader(f)
+        if magic != supported_magic:
+            if __debugging__: print "Unsupported bytecode version:", fullname
+            return None
         #code = Unmarshaller(f, magic=magic).load()
         code = Unmarshaller(f).load()
         if __debugging__: print "Successfully loaded:", fullname
@@ -63,6 +74,7 @@
 class __MetaImporter(object):
     def __init__(self):
         self.__importers = {}
+
     def find_module(self, fullname, path):
         if __debugging__: print "MetaImporter.find_module(%s, %s)" % (
             repr(fullname), repr(path))
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@
 
 Jython 2.7.1rc1
   Bugs fixed
+    - [ 2533 ] Opcode.java is outdated -> breaks PyBytecode.interpret
     - [ 2502 ] Missing OpenFlags enum entry makes Jython clash with JRuby dependency
     - [ 2446 ] Support SNI for SSL/TLS client sockets
     - [ 2455 ] Java classes in packages with __init__.py not found
@@ -35,6 +36,7 @@
     - [ 1767 ] Rich comparisons
 
   New Features
+    - Support for CPython bytecode (.pyc-files) was updated to Python 2.7 bytecode (from 2.5).
     - Buffer API changes allow java.nio.ByteBuffer to provide the storage when a PyBuffer
       is exported. This is to support CPython extensions via JyNI, but has other uses too
       (including access to direct memory buffers from Python). There is no change at the
diff --git a/src/org/python/compiler/ClassFile.java b/src/org/python/compiler/ClassFile.java
--- a/src/org/python/compiler/ClassFile.java
+++ b/src/org/python/compiler/ClassFile.java
@@ -42,19 +42,18 @@
         }
         return new String(c);
     }
-    
 
     public static void visitAnnotations(AnnotationVisitor av, Map<String, Object> fields) {
         for (Entry<String, Object>field: fields.entrySet()) {
             visitAnnotation(av, field.getKey(), field.getValue());
         }
     }
-    
+
     // See org.objectweb.asm.AnnotationVisitor for details
     // TODO Support annotation annotations and annotation array annotations
     public static void visitAnnotation(AnnotationVisitor av, String fieldName, Object fieldValue) {
         Class<?> fieldValueClass = fieldValue.getClass();
-        
+
         if (fieldValue instanceof Class) {
             av.visit(fieldName, Type.getType((Class<?>)fieldValue));
         } else if (fieldValueClass.isEnum()) {
@@ -79,13 +78,14 @@
     public ClassFile(String name, String superclass, int access) {
         this(name, superclass, access, org.python.core.imp.NO_MTIME);
     }
+
     public ClassFile(String name, String superclass, int access, long mtime) {
         this.name = fixName(name);
         this.superclass = fixName(superclass);
         this.interfaces = new String[0];
         this.access = access;
         this.mtime = mtime;
-        
+
         cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
         methodVisitors = Collections.synchronizedList(new ArrayList<MethodVisitor>());
         fieldVisitors = Collections.synchronizedList(new ArrayList<FieldVisitor>());
@@ -96,7 +96,9 @@
         sfilename = name;
     }
 
-    public void addInterface(String name) throws IOException {
+    public void addInterface(String name)
+        throws IOException
+    {
         String[] new_interfaces = new String[interfaces.length+1];
         System.arraycopy(interfaces, 0, new_interfaces, 0, interfaces.length);
         new_interfaces[interfaces.length] = name;
@@ -111,15 +113,16 @@
         methodVisitors.add(pmv);
         return pmv;
     }
+
     public Code addMethod(String name, String type, int access, String[] exceptions)
-            throws IOException
-        {
-            MethodVisitor mv = cw.visitMethod(access, name, type, null, exceptions);
-            Code pmv = new Code(mv, type, access);
-            methodVisitors.add(pmv);
-            return pmv;
-        }
-    
+        throws IOException
+    {
+        MethodVisitor mv = cw.visitMethod(access, name, type, null, exceptions);
+        Code pmv = new Code(mv, type, access);
+        methodVisitors.add(pmv);
+        return pmv;
+    }
+
     public Code addMethod(String name, String type, int access, String[] exceptions,
             AnnotationDescr[]methodAnnotationDescrs, AnnotationDescr[][] parameterAnnotationDescrs)
         throws IOException
@@ -134,7 +137,7 @@
             }
             av.visitEnd();
         }
-        
+
         // parameter annotations
         for (int i = 0; i < parameterAnnotationDescrs.length; i++) {
             for (AnnotationDescr ad: parameterAnnotationDescrs[i]) {
@@ -145,12 +148,12 @@
                 av.visitEnd();
             }
         }
-        
+
         Code pmv = new Code(mv, type, access);
         methodVisitors.add(pmv);
         return pmv;
     }
-    
+
     public void addClassAnnotation(AnnotationDescr annotationDescr) {
         AnnotationVisitor av = cw.visitAnnotation(annotationDescr.getName(), true);
         if (annotationDescr.hasFields()) {
@@ -158,7 +161,7 @@
         }
         annotationVisitors.add(av);
     }
-    
+
     public void addField(String name, String type, int access)
         throws IOException
     {
@@ -190,7 +193,7 @@
             fv.visitEnd();
         }
     }
-    
+
     public void endMethods()
         throws IOException
     {
@@ -204,10 +207,12 @@
     public void endClassAnnotations() {
         for (AnnotationVisitor av: annotationVisitors) {
             av.visitEnd();
-        } 
+        }
     }
 
-    public void write(OutputStream stream) throws IOException {
+    public void write(OutputStream stream)
+        throws IOException
+    {
         cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, this.name, null, this.superclass, interfaces);
         AnnotationVisitor av = cw.visitAnnotation("Lorg/python/compiler/APIVersion;", true);
         // XXX: should imp.java really house this value or should imp.java point into
diff --git a/src/org/python/core/Opcode.java b/src/org/python/core/Opcode.java
--- a/src/org/python/core/Opcode.java
+++ b/src/org/python/core/Opcode.java
@@ -1,172 +1,174 @@
 package org.python.core;
 
-// derived from CPython 2.5.2 Include/opcode.h
+// derived from CPython 2.7.12 Include/opcode.h
 
-public class Opcode {
+public interface Opcode {
 
-    public static final int POP_TOP = 1;
-    public static final int ROT_TWO = 2;
-    public static final int ROT_THREE = 3;
-    public static final int DUP_TOP = 4;
-    public static final int ROT_FOUR = 5;
-    public static final int NOP = 9;
-    public static final int UNARY_POSITIVE = 10;
-    public static final int UNARY_NEGATIVE = 11;
-    public static final int UNARY_NOT = 12;
-    public static final int UNARY_CONVERT = 13;
-    public static final int UNARY_INVERT = 15;
-    public static final int LIST_APPEND = 18;
-    public static final int BINARY_POWER = 19;
-    public static final int BINARY_MULTIPLY = 20;
-    public static final int BINARY_DIVIDE = 21;
-    public static final int BINARY_MODULO = 22;
-    public static final int BINARY_ADD = 23;
-    public static final int BINARY_SUBTRACT = 24;
-    public static final int BINARY_SUBSCR = 25;
-    public static final int BINARY_FLOOR_DIVIDE = 26;
-    public static final int BINARY_TRUE_DIVIDE = 27;
-    public static final int INPLACE_FLOOR_DIVIDE = 28;
-    public static final int INPLACE_TRUE_DIVIDE = 29;
-    public static final int SLICE = 30;
+    /* Instruction opcodes for compiled code */
+
+    public static final int STOP_CODE            =   0;
+    public static final int POP_TOP              =   1;
+    public static final int ROT_TWO              =   2;
+    public static final int ROT_THREE            =   3;
+    public static final int DUP_TOP              =   4;
+    public static final int ROT_FOUR             =   5;
+    public static final int NOP                  =   9;
+
+    public static final int UNARY_POSITIVE       =  10;
+    public static final int UNARY_NEGATIVE       =  11;
+    public static final int UNARY_NOT            =  12;
+    public static final int UNARY_CONVERT        =  13;
+    public static final int UNARY_INVERT         =  15;
+
+    public static final int BINARY_POWER         =  19;
+    public static final int BINARY_MULTIPLY      =  20;
+    public static final int BINARY_DIVIDE        =  21;
+    public static final int BINARY_MODULO        =  22;
+    public static final int BINARY_ADD           =  23;
+    public static final int BINARY_SUBTRACT      =  24;
+    public static final int BINARY_SUBSCR        =  25;
+    public static final int BINARY_FLOOR_DIVIDE  =  26;
+    public static final int BINARY_TRUE_DIVIDE   =  27;
+
+    public static final int INPLACE_FLOOR_DIVIDE =  28;
+    public static final int INPLACE_TRUE_DIVIDE  =  29;
+
+    public static final int SLICE                =  30;
     /* Also uses 31-33 */
-    public static final int STORE_SLICE = 40;
+    public static final int SLICE_1              =  31;
+    public static final int SLICE_2              =  32;
+    public static final int SLICE_3              =  33;
+
+    public static final int STORE_SLICE          =  40;
     /* Also uses 41-43 */
-    public static final int DELETE_SLICE = 50;
+    public static final int STORE_SLICE_1        =  41;
+    public static final int STORE_SLICE_2        =  42;
+    public static final int STORE_SLICE_3        =  43;
+
+    public static final int DELETE_SLICE         =  50;
     /* Also uses 51-53 */
-    public static final int INPLACE_ADD = 55;
-    public static final int INPLACE_SUBTRACT = 56;
-    public static final int INPLACE_MULTIPLY = 57;
-    public static final int INPLACE_DIVIDE = 58;
-    public static final int INPLACE_MODULO = 59;
-    public static final int STORE_SUBSCR = 60;
-    public static final int DELETE_SUBSCR = 61;
-    public static final int BINARY_LSHIFT = 62;
-    public static final int BINARY_RSHIFT = 63;
-    public static final int BINARY_AND = 64;
-    public static final int BINARY_XOR = 65;
-    public static final int BINARY_OR = 66;
-    public static final int INPLACE_POWER = 67;
-    public static final int GET_ITER = 68;
-    public static final int PRINT_EXPR = 70;
-    public static final int PRINT_ITEM = 71;
-    public static final int PRINT_NEWLINE = 72;
-    public static final int PRINT_ITEM_TO = 73;
-    public static final int PRINT_NEWLINE_TO = 74;
-    public static final int INPLACE_LSHIFT = 75;
-    public static final int INPLACE_RSHIFT = 76;
-    public static final int INPLACE_AND = 77;
-    public static final int INPLACE_XOR = 78;
-    public static final int INPLACE_OR = 79;
-    public static final int BREAK_LOOP = 80;
-    public static final int WITH_CLEANUP = 81;
-    public static final int LOAD_LOCALS = 82;
-    public static final int RETURN_VALUE = 83;
-    public static final int IMPORT_STAR = 84;
-    public static final int EXEC_STMT = 85;
-    public static final int YIELD_VALUE = 86;
-    public static final int POP_BLOCK = 87;
-    public static final int END_FINALLY = 88;
-    public static final int BUILD_CLASS = 89;
-    public static final int HAVE_ARGUMENT = 90;	/* Opcodes from here have an argument: */
+    public static final int DELETE_SLICE_1       =  51;
+    public static final int DELETE_SLICE_2       =  52;
+    public static final int DELETE_SLICE_3       =  53;
 
-    public static final int STORE_NAME = 90;	/* Index in name list */
+    public static final int STORE_MAP            =  54;
+    public static final int INPLACE_ADD          =  55;
+    public static final int INPLACE_SUBTRACT     =  56;
+    public static final int INPLACE_MULTIPLY     =  57;
+    public static final int INPLACE_DIVIDE       =  58;
+    public static final int INPLACE_MODULO       =  59;
+    public static final int STORE_SUBSCR         =  60;
+    public static final int DELETE_SUBSCR        =  61;
 
-    public static final int DELETE_NAME = 91;	/* "" */
+    public static final int BINARY_LSHIFT        =  62;
+    public static final int BINARY_RSHIFT        =  63;
+    public static final int BINARY_AND           =  64;
+    public static final int BINARY_XOR           =  65;
+    public static final int BINARY_OR            =  66;
+    public static final int INPLACE_POWER        =  67;
+    public static final int GET_ITER             =  68;
 
-    public static final int UNPACK_SEQUENCE = 92;	/* Number of sequence items */
+    public static final int PRINT_EXPR           =  70;
+    public static final int PRINT_ITEM           =  71;
+    public static final int PRINT_NEWLINE        =  72;
+    public static final int PRINT_ITEM_TO        =  73;
+    public static final int PRINT_NEWLINE_TO     =  74;
+    public static final int INPLACE_LSHIFT       =  75;
+    public static final int INPLACE_RSHIFT       =  76;
+    public static final int INPLACE_AND          =  77;
+    public static final int INPLACE_XOR          =  78;
+    public static final int INPLACE_OR           =  79;
+    public static final int BREAK_LOOP           =  80;
+    public static final int WITH_CLEANUP         =  81;
+    public static final int LOAD_LOCALS          =  82;
+    public static final int RETURN_VALUE         =  83;
+    public static final int IMPORT_STAR          =  84;
+    public static final int EXEC_STMT            =  85;
+    public static final int YIELD_VALUE          =  86;
+    public static final int POP_BLOCK            =  87;
+    public static final int END_FINALLY          =  88;
+    public static final int BUILD_CLASS          =  89;
 
-    public static final int FOR_ITER = 93;
-    public static final int STORE_ATTR = 95;	/* Index in name list */
+    public static final int HAVE_ARGUMENT        =  90; /* Opcodes from here have an argument: */
 
-    public static final int DELETE_ATTR = 96;	/* "" */
+    public static final int STORE_NAME           =  90; /* Index in name list */
+    public static final int DELETE_NAME          =  91; /* "" */
+    public static final int UNPACK_SEQUENCE      =  92; /* Number of sequence items */
+    public static final int FOR_ITER             =  93;
+    public static final int LIST_APPEND          =  94;
 
-    public static final int STORE_GLOBAL = 97;	/* "" */
+    public static final int STORE_ATTR           =  95; /* Index in name list */
+    public static final int DELETE_ATTR          =  96; /* "" */
+    public static final int STORE_GLOBAL         =  97; /* "" */
+    public static final int DELETE_GLOBAL        =  98; /* "" */
+    public static final int DUP_TOPX             =  99; /* number of items to duplicate */
+    public static final int LOAD_CONST           = 100; /* Index in const list */
+    public static final int LOAD_NAME            = 101; /* Index in name list */
+    public static final int BUILD_TUPLE          = 102; /* Number of tuple items */
+    public static final int BUILD_LIST           = 103; /* Number of list items */
+    public static final int BUILD_SET            = 104; /* Number of set items */
+    public static final int BUILD_MAP            = 105; /* Always zero for now */
+    public static final int LOAD_ATTR            = 106; /* Index in name list */
+    public static final int COMPARE_OP           = 107; /* Comparison operator */
+    public static final int IMPORT_NAME          = 108; /* Index in name list */
+    public static final int IMPORT_FROM          = 109; /* Index in name list */
+    
+    public static final int JUMP_FORWARD         = 110; /* Number of bytes to skip */
+    public static final int JUMP_IF_FALSE_OR_POP = 111; /* Target byte offset from beginning of code */
+    public static final int JUMP_IF_TRUE_OR_POP  = 112; /* "" */
+    public static final int JUMP_ABSOLUTE        = 113; /* "" */
+    public static final int POP_JUMP_IF_FALSE    = 114; /* "" */
+    public static final int POP_JUMP_IF_TRUE     = 115; /* "" */
 
-    public static final int DELETE_GLOBAL = 98;	/* "" */
+    public static final int LOAD_GLOBAL          = 116; /* Index in name list */
 
-    public static final int DUP_TOPX = 99;	/* number of items to duplicate */
+    public static final int CONTINUE_LOOP        = 119; /* Start of loop (absolute) */
+    public static final int SETUP_LOOP           = 120; /* Target address (relative) */
+    public static final int SETUP_EXCEPT         = 121; /* "" */
+    public static final int SETUP_FINALLY        = 122; /* "" */
 
-    public static final int LOAD_CONST = 100;	/* Index in const list */
+    public static final int LOAD_FAST            = 124; /* Local variable number */
+    public static final int STORE_FAST           = 125; /* Local variable number */
+    public static final int DELETE_FAST          = 126; /* Local variable number */
 
-    public static final int LOAD_NAME = 101;	/* Index in name list */
+    public static final int RAISE_VARARGS        = 130; /* Number of raise arguments (1, 2 or 3) */
+    /* CALL_FUNCTION_XXX opcodes defined below depend on this definition */
+    public static final int CALL_FUNCTION        = 131; /* #args + (#kwargs<<8) */
+    public static final int MAKE_FUNCTION        = 132; /* #defaults */
+    public static final int BUILD_SLICE          = 133; /* Number of items */
 
-    public static final int BUILD_TUPLE = 102;	/* Number of tuple items */
-
-    public static final int BUILD_LIST = 103;	/* Number of list items */
-
-    public static final int BUILD_MAP = 104;	/* Always zero for now */
-
-    public static final int LOAD_ATTR = 105;	/* Index in name list */
-
-    public static final int COMPARE_OP = 106;	/* Comparison operator */
-
-    public static final int IMPORT_NAME = 107;	/* Index in name list */
-
-    public static final int IMPORT_FROM = 108;	/* Index in name list */
-
-    public static final int JUMP_FORWARD = 110;	/* Number of bytes to skip */
-
-    public static final int JUMP_IF_FALSE = 111;	/* "" */
-
-    public static final int JUMP_IF_TRUE = 112;	/* "" */
-
-    public static final int JUMP_ABSOLUTE = 113;	/* Target byte offset from beginning of code */
-
-    public static final int LOAD_GLOBAL = 116;	/* Index in name list */
-
-    public static final int CONTINUE_LOOP = 119;	/* Start of loop (absolute) */
-
-    public static final int SETUP_LOOP = 120;	/* Target address (absolute) */
-
-    public static final int SETUP_EXCEPT = 121;	/* "" */
-
-    public static final int SETUP_FINALLY = 122;	/* "" */
-
-    public static final int LOAD_FAST = 124;	/* Local variable number */
-
-    public static final int STORE_FAST = 125;	/* Local variable number */
-
-    public static final int DELETE_FAST = 126;	/* Local variable number */
-
-    public static final int RAISE_VARARGS = 130;	/* Number of raise arguments (1, 2 or 3) */
-    /* CALL_FUNCTION_XXX opcodes defined below depend on this definition */
-
-    public static final int CALL_FUNCTION = 131;	/* #args + (#kwargs<<8) */
-
-    public static final int MAKE_FUNCTION = 132;	/* #defaults */
-
-    public static final int BUILD_SLICE = 133;	/* Number of items */
-
-    public static final int MAKE_CLOSURE = 134;     /* #free vars */
-
-    public static final int LOAD_CLOSURE = 135;     /* Load free variable from closure */
-
-    public static final int LOAD_DEREF = 136;     /* Load and dereference from closure cell */
-
-    public static final int STORE_DEREF = 137;     /* Store into cell */
+    public static final int MAKE_CLOSURE         = 134; /* #free vars */
+    public static final int LOAD_CLOSURE         = 135; /* Load free variable from closure */
+    public static final int LOAD_DEREF           = 136; /* Load and dereference from closure cell */
+    public static final int STORE_DEREF          = 137; /* Store into cell */
 
     /* The next 3 opcodes must be contiguous and satisfy
-    (CALL_FUNCTION_VAR - CALL_FUNCTION) & 3 == 1  */
-    public static final int CALL_FUNCTION_VAR = 140;	/* #args + (#kwargs<<8) */
+       (CALL_FUNCTION_VAR - CALL_FUNCTION) & 3 == 1  */
+    public static final int CALL_FUNCTION_VAR    = 140; /* #args + (#kwargs<<8) */
+    public static final int CALL_FUNCTION_KW     = 141; /* #args + (#kwargs<<8) */
+    public static final int CALL_FUNCTION_VAR_KW = 142; /* #args + (#kwargs<<8) */
 
-    public static final int CALL_FUNCTION_KW = 141;	/* #args + (#kwargs<<8) */
-
-    public static final int CALL_FUNCTION_VAR_KW = 142;	/* #args + (#kwargs<<8) */
+    public static final int SETUP_WITH           = 143;
 
     /* Support for opargs more than 16 bits long */
-    public static final int EXTENDED_ARG = 143;
+    public static final int EXTENDED_ARG         = 145;
+
+    public static final int SET_ADD              = 146;
+    public static final int MAP_ADD              = 147;
+
 
     // comparison opcodes (on the oparg), just put in this class too
-    public static final int PyCmp_LT = 0;
-    public static final int PyCmp_LE = 1;
-    public static final int PyCmp_EQ = 2;
-    public static final int PyCmp_NE = 3;
-    public static final int PyCmp_GT = 4;
-    public static final int PyCmp_GE = 5;
-    public static final int PyCmp_IN = 6;
-    public static final int PyCmp_NOT_IN = 7;
-    public static final int PyCmp_IS = 8;
-    public static final int PyCmp_IS_NOT = 9;
+    public static final int PyCmp_LT        =  0;
+    public static final int PyCmp_LE        =  1;
+    public static final int PyCmp_EQ        =  2;
+    public static final int PyCmp_NE        =  3;
+    public static final int PyCmp_GT        =  4;
+    public static final int PyCmp_GE        =  5;
+    public static final int PyCmp_IN        =  6;
+    public static final int PyCmp_NOT_IN    =  7;
+    public static final int PyCmp_IS        =  8;
+    public static final int PyCmp_IS_NOT    =  9;
     public static final int PyCmp_EXC_MATCH = 10;
+    public static final int PyCmp_BAD       = 11;
 
 }
diff --git a/src/org/python/core/PyBytecode.java b/src/org/python/core/PyBytecode.java
--- a/src/org/python/core/PyBytecode.java
+++ b/src/org/python/core/PyBytecode.java
@@ -3,14 +3,17 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import static org.python.core.Opcode.*;
 
 public class PyBytecode extends PyBaseCode implements Traverseproc {
 
     // for debugging
+    public static boolean defaultDebug = false;
+    private static boolean debug;
+    private static PyObject dis, opname;
+
     private int count = 0; // total number of opcodes run so far in this code obj
     private int maxCount = -1; // if -1, no cap on number of opcodes than can be run
-    public static boolean defaultDebug = false;
-    private static PyObject dis;
 
     private static synchronized PyObject get_dis() {
         if (dis == null) {
@@ -18,7 +21,6 @@
         }
         return dis;
     }
-    private static PyObject opname;
 
     private static synchronized PyObject get_opname() {
         if (opname == null) {
@@ -26,7 +28,6 @@
         }
         return opname;
     }
-    private boolean debug;
 
     public static void _allDebug(boolean setting) {
         defaultDebug = setting;
@@ -37,8 +38,8 @@
         this.maxCount = maxCount;
         return Py.None;
     }
+    // end debugging
 
-    // end debugging
     public final static int CO_MAXBLOCKS = 20; // same as in CPython
     public final byte[] co_code; // widened to char to avoid signed byte issues
     public final PyObject[] co_consts;
@@ -57,7 +58,6 @@
                 null, null);
     }
 
-
     // XXX - intern names HERE instead of in marshal
     public PyBytecode(int argcount, int nlocals, int stacksize, int flags,
             String codestring, PyObject[] constants, String[] names, String varnames[],
@@ -90,6 +90,7 @@
         co_code = getBytes(codestring);
         co_lnotab = getBytes(lnotab);
     }
+
     private static final String[] __members__ = {
         "co_name", "co_argcount",
         "co_varnames", "co_filename", "co_firstlineno",
@@ -169,7 +170,6 @@
     }
 
     enum Why {
-
         NOT,       /* No error */
         EXCEPTION, /* Exception occurred */
         RERAISE,   /* Exception re-raised by 'finally' */
@@ -183,7 +183,6 @@
     // to enable why's to be stored on a PyStack
     @Untraversable
     private static class PyStackWhy extends PyObject {
-
         Why why;
 
         PyStackWhy(Why why) {
@@ -197,7 +196,6 @@
     }
 
     private static class PyStackException extends PyObject implements Traverseproc {
-
         PyException exception;
 
         PyStackException(PyException exception) {
@@ -227,10 +225,9 @@
             return "[]";
         }
         StringBuilder buf = new StringBuilder("[");
-        int len = f.f_lineno;
-        for (int i = 0; i < len; i++) {
+        for (int i = 0; i < f.f_exits.length; i++) {
             buf.append(f.f_exits[i].toString());
-            if (i < len - 1) {
+            if (i < f.f_exits.length - 1) {
                 buf.append(", ");
             }
         }
@@ -241,9 +238,9 @@
     private void print_debug(int count, int next_instr, int line, int opcode, int oparg, PyStack stack, PyFrame f) {
         if (debug) {
             System.err.println(co_name + " " + line + ":" +
-                    count + "," + f.f_lasti + "> " +
+                    count + "," + f.f_lasti + "> " + opcode+" "+
                     get_opname().__getitem__(Py.newInteger(opcode)) +
-                    (opcode >= Opcode.HAVE_ARGUMENT ? " " + oparg : "") +
+                    (opcode >= HAVE_ARGUMENT ? " " + oparg : "") +
                     ", stack: " + stack.toString() +
                     ", blocks: " + stringify_blocks(f));
         }
@@ -287,7 +284,6 @@
         // XXX - optimization opportunities
         // 1. consider detaching the setting/getting of frame fields to improve performance, instead do this
         // in a shadow version of the frame that we copy back to on entry/exit and downcalls
-
         if (debug) {
             System.err.println(co_name + ":" + f.f_lasti + "/" + co_code.length +
                     ", cells:" + Arrays.toString(co_cellvars) + ", free:" + Arrays.toString(co_freevars));
@@ -345,7 +341,7 @@
                 }
 
                 opcode = getUnsigned(co_code, next_instr);
-                if (opcode >= Opcode.HAVE_ARGUMENT) {
+                if (opcode >= HAVE_ARGUMENT) {
                     next_instr += 2;
                     oparg = (getUnsigned(co_code, next_instr) << 8) + getUnsigned(co_code, next_instr - 1);
                 }
@@ -356,42 +352,42 @@
                 f.f_lasti = next_instr;
 
                 switch (opcode) {
-                    case Opcode.NOP:
+                    case NOP:
                         break;
 
-                    case Opcode.LOAD_FAST:
+                    case LOAD_FAST:
                         stack.push(f.getlocal(oparg));
                         break;
 
-                    case Opcode.LOAD_CONST:
+                    case LOAD_CONST:
                         stack.push(co_consts[oparg]);
                         break;
 
-                    case Opcode.STORE_FAST:
+                    case STORE_FAST:
                         f.setlocal(oparg, stack.pop());
                         break;
 
-                    case Opcode.POP_TOP:
+                    case POP_TOP:
                         stack.pop();
                         break;
 
-                    case Opcode.ROT_TWO:
+                    case ROT_TWO:
                         stack.rot2();
                         break;
 
-                    case Opcode.ROT_THREE:
+                    case ROT_THREE:
                         stack.rot3();
                         break;
 
-                    case Opcode.ROT_FOUR:
+                    case ROT_FOUR:
                         stack.rot4();
                         break;
 
-                    case Opcode.DUP_TOP:
+                    case DUP_TOP:
                         stack.dup();
                         break;
 
-                    case Opcode.DUP_TOPX: {
+                    case DUP_TOPX: {
                         if (oparg == 2 || oparg == 3) {
                             stack.dup(oparg);
                         } else {
@@ -401,41 +397,41 @@
                         break;
                     }
 
-                    case Opcode.UNARY_POSITIVE:
+                    case UNARY_POSITIVE:
                         stack.push(stack.pop().__pos__());
                         break;
 
-                    case Opcode.UNARY_NEGATIVE:
+                    case UNARY_NEGATIVE:
                         stack.push(stack.pop().__neg__());
                         break;
 
-                    case Opcode.UNARY_NOT:
+                    case UNARY_NOT:
                         stack.push(stack.pop().__not__());
                         break;
 
-                    case Opcode.UNARY_CONVERT:
+                    case UNARY_CONVERT:
                         stack.push(stack.pop().__repr__());
                         break;
 
-                    case Opcode.UNARY_INVERT:
+                    case UNARY_INVERT:
                         stack.push(stack.pop().__invert__());
                         break;
 
-                    case Opcode.BINARY_POWER: {
+                    case BINARY_POWER: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._pow(b));
                         break;
                     }
 
-                    case Opcode.BINARY_MULTIPLY: {
+                    case BINARY_MULTIPLY: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._mul(b));
                         break;
                     }
 
-                    case Opcode.BINARY_DIVIDE: {
+                    case BINARY_DIVIDE: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
 
@@ -447,63 +443,63 @@
                         break;
                     }
 
-                    case Opcode.BINARY_TRUE_DIVIDE: {
+                    case BINARY_TRUE_DIVIDE: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._truediv(b));
                         break;
                     }
 
-                    case Opcode.BINARY_FLOOR_DIVIDE: {
+                    case BINARY_FLOOR_DIVIDE: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._floordiv(b));
                         break;
                     }
 
-                    case Opcode.BINARY_MODULO: {
+                    case BINARY_MODULO: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._mod(b));
                         break;
                     }
 
-                    case Opcode.BINARY_ADD: {
+                    case BINARY_ADD: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._add(b));
                         break;
                     }
 
-                    case Opcode.BINARY_SUBTRACT: {
+                    case BINARY_SUBTRACT: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._sub(b));
                         break;
                     }
 
-                    case Opcode.BINARY_SUBSCR: {
+                    case BINARY_SUBSCR: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a.__getitem__(b));
                         break;
                     }
 
-                    case Opcode.BINARY_LSHIFT: {
+                    case BINARY_LSHIFT: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._lshift(b));
                         break;
                     }
 
-                    case Opcode.BINARY_RSHIFT: {
+                    case BINARY_RSHIFT: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._rshift(b));
                         break;
                     }
 
-                    case Opcode.BINARY_AND: {
+                    case BINARY_AND: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._and(b));
@@ -511,42 +507,49 @@
                     }
 
 
-                    case Opcode.BINARY_XOR: {
+                    case BINARY_XOR: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._xor(b));
                         break;
                     }
 
-                    case Opcode.BINARY_OR: {
+                    case BINARY_OR: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._or(b));
                         break;
                     }
 
-                    case Opcode.LIST_APPEND: {
+                    case LIST_APPEND: {
                         PyObject b = stack.pop();
-                        PyList a = (PyList) (stack.pop());
+                        PyList a = (PyList) stack.top(oparg);
                         a.append(b);
                         break;
                     }
 
-                    case Opcode.INPLACE_POWER: {
+                    case SET_ADD: {
+                        PyObject b = stack.pop();
+                        PySet a = (PySet) stack.top(oparg);
+                        a.add(b);
+                        break;
+                    }
+
+                    case INPLACE_POWER: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._ipow(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_MULTIPLY: {
+                    case INPLACE_MULTIPLY: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._imul(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_DIVIDE: {
+                    case INPLACE_DIVIDE: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         if (!co_flags.isFlagSet(CodeFlag.CO_FUTURE_DIVISION)) {
@@ -557,111 +560,111 @@
                         break;
                     }
 
-                    case Opcode.INPLACE_TRUE_DIVIDE: {
+                    case INPLACE_TRUE_DIVIDE: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._itruediv(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_FLOOR_DIVIDE: {
+                    case INPLACE_FLOOR_DIVIDE: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._ifloordiv(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_MODULO: {
+                    case INPLACE_MODULO: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._imod(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_ADD: {
+                    case INPLACE_ADD: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._iadd(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_SUBTRACT: {
+                    case INPLACE_SUBTRACT: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._isub(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_LSHIFT: {
+                    case INPLACE_LSHIFT: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._ilshift(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_RSHIFT: {
+                    case INPLACE_RSHIFT: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._irshift(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_AND: {
+                    case INPLACE_AND: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._iand(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_XOR: {
+                    case INPLACE_XOR: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._ixor(b));
                         break;
                     }
 
-                    case Opcode.INPLACE_OR: {
+                    case INPLACE_OR: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
                         stack.push(a._ior(b));
                         break;
                     }
 
-                    case Opcode.SLICE + 0:
-                    case Opcode.SLICE + 1:
-                    case Opcode.SLICE + 2:
-                    case Opcode.SLICE + 3: {
-                        PyObject stop = (((opcode - Opcode.SLICE) & 2) != 0) ? stack.pop() : null;
-                        PyObject start = (((opcode - Opcode.SLICE) & 1) != 0) ? stack.pop() : null;
+                    case SLICE:
+                    case SLICE_1:
+                    case SLICE_2:
+                    case SLICE_3: {
+                        PyObject stop = (((opcode - SLICE) & 2) != 0) ? stack.pop() : null;
+                        PyObject start = (((opcode - SLICE) & 1) != 0) ? stack.pop() : null;
                         PyObject obj = stack.pop();
                         stack.push(obj.__getslice__(start, stop));
                         break;
                     }
 
-                    case Opcode.STORE_SLICE + 0:
-                    case Opcode.STORE_SLICE + 1:
-                    case Opcode.STORE_SLICE + 2:
-                    case Opcode.STORE_SLICE + 3: {
-                        PyObject stop = (((opcode - Opcode.STORE_SLICE) & 2) != 0) ? stack.pop() : null;
-                        PyObject start = (((opcode - Opcode.STORE_SLICE) & 1) != 0) ? stack.pop() : null;
+                    case STORE_SLICE:
+                    case STORE_SLICE_1:
+                    case STORE_SLICE_2:
+                    case STORE_SLICE_3: {
+                        PyObject stop = (((opcode - STORE_SLICE) & 2) != 0) ? stack.pop() : null;
+                        PyObject start = (((opcode - STORE_SLICE) & 1) != 0) ? stack.pop() : null;
                         PyObject obj = stack.pop();
                         PyObject value = stack.pop();
                         obj.__setslice__(start, stop, value);
                         break;
                     }
 
-                    case Opcode.DELETE_SLICE + 0:
-                    case Opcode.DELETE_SLICE + 1:
-                    case Opcode.DELETE_SLICE + 2:
-                    case Opcode.DELETE_SLICE + 3: {
-                        PyObject stop = (((opcode - Opcode.DELETE_SLICE) & 2) != 0) ? stack.pop() : null;
-                        PyObject start = (((opcode - Opcode.DELETE_SLICE) & 1) != 0) ? stack.pop() : null;
+                    case DELETE_SLICE:
+                    case DELETE_SLICE_1:
+                    case DELETE_SLICE_2:
+                    case DELETE_SLICE_3: {
+                        PyObject stop = (((opcode - DELETE_SLICE) & 2) != 0) ? stack.pop() : null;
+                        PyObject start = (((opcode - DELETE_SLICE) & 1) != 0) ? stack.pop() : null;
                         PyObject obj = stack.pop();
                         obj.__delslice__(start, stop);
                         break;
                     }
 
-                    case Opcode.STORE_SUBSCR: {
+                    case STORE_SUBSCR: {
                         PyObject key = stack.pop();
                         PyObject obj = stack.pop();
                         PyObject value = stack.pop();
@@ -669,34 +672,34 @@
                         break;
                     }
 
-                    case Opcode.DELETE_SUBSCR: {
+                    case DELETE_SUBSCR: {
                         PyObject key = stack.pop();
                         PyObject obj = stack.pop();
                         obj.__delitem__(key);
                         break;
                     }
 
-                    case Opcode.PRINT_EXPR:
+                    case PRINT_EXPR:
                         PySystemState.displayhook(stack.pop());
                         break;
 
-                    case Opcode.PRINT_ITEM_TO:
+                    case PRINT_ITEM_TO:
                         Py.printComma(stack.pop(), stack.pop());
                         break;
 
-                    case Opcode.PRINT_ITEM:
+                    case PRINT_ITEM:
                         Py.printComma(stack.pop());
                         break;
 
-                    case Opcode.PRINT_NEWLINE_TO:
+                    case PRINT_NEWLINE_TO:
                         Py.printlnv(stack.pop());
                         break;
 
-                    case Opcode.PRINT_NEWLINE:
+                    case PRINT_NEWLINE:
                         Py.println();
                         break;
 
-                    case Opcode.RAISE_VARARGS:
+                    case RAISE_VARARGS:
 
                         switch (oparg) {
                             case 3: {
@@ -720,29 +723,31 @@
                                 throw Py.SystemError("bad RAISE_VARARGS oparg");
                         }
 
-                    case Opcode.LOAD_LOCALS:
+                    case LOAD_LOCALS:
                         stack.push(f.f_locals);
                         break;
 
-                    case Opcode.RETURN_VALUE:
+                    case RETURN_VALUE:
                         retval = stack.pop();
                         why = Why.RETURN;
                         break;
 
-                    case Opcode.YIELD_VALUE:
+                    case YIELD_VALUE:
                         retval = stack.pop();
+                        // Note: CPython calls f->f_stacktop = stack_pointer; here
                         why = Why.YIELD;
                         break;
 
-                    case Opcode.EXEC_STMT: {
+                    case EXEC_STMT: {
                         PyObject locals = stack.pop();
                         PyObject globals = stack.pop();
                         PyObject code = stack.pop();
+                        //Todo: Better make it possible to use PyFrame f here:
                         Py.exec(code, globals == Py.None ? null : globals, locals == Py.None ? null : locals);
                         break;
                     }
 
-                    case Opcode.POP_BLOCK: {
+                    case POP_BLOCK: {
                         PyTryBlock b = popBlock(f);
                         while (stack.size() > b.b_level) {
                             stack.pop();
@@ -750,7 +755,8 @@
                         break;
                     }
 
-                    case Opcode.END_FINALLY: {
+                    case END_FINALLY: {
+                        // Todo: Review this regarding Python 2.7-update
                         PyObject v = stack.pop();
                         if (v instanceof PyStackWhy) {
                             why = ((PyStackWhy) v).why;
@@ -759,10 +765,16 @@
                                 retval = stack.pop();
                             }
                         } else if (v instanceof PyStackException) {
+                            stack.top -= 2; // to pop value, traceback
                             ts.exception = ((PyStackException) v).exception;
                             why = Why.RERAISE;
-
                         } else if (v instanceof PyString) {
+                            // This shouldn't happen, because Jython always pushes
+                            // exception type as PyException-object.
+                            // Todo: Test, if it can be removed.
+                            PyObject value = stack.pop();
+                            PyObject traceback = stack.pop();
+                            ts.exception = new PyException(v, value, (PyTraceback) traceback);
                             why = Why.RERAISE;
                         } else if (v != Py.None) {
                             throw Py.SystemError("'finally' pops bad exception");
@@ -770,7 +782,7 @@
                         break;
                     }
 
-                    case Opcode.BUILD_CLASS: {
+                    case BUILD_CLASS: {
                         PyObject methods = stack.pop();
                         PyObject bases[] = ((PySequenceList) (stack.pop())).getArray();
                         String name = stack.pop().toString();
@@ -778,50 +790,51 @@
                         break;
                     }
 
-                    case Opcode.STORE_NAME:
+                    case STORE_NAME:
                         f.setlocal(co_names[oparg], stack.pop());
                         break;
 
-                    case Opcode.DELETE_NAME:
+                    case DELETE_NAME:
                         f.dellocal(co_names[oparg]);
                         break;
 
-                    case Opcode.UNPACK_SEQUENCE:
+                    case UNPACK_SEQUENCE:
                         unpack_iterable(oparg, stack);
                         break;
 
-                    case Opcode.STORE_ATTR: {
+                    case STORE_ATTR: {
                         PyObject obj = stack.pop();
                         PyObject v = stack.pop();
                         obj.__setattr__(co_names[oparg], v);
                         break;
                     }
 
-                    case Opcode.DELETE_ATTR:
+                    case DELETE_ATTR:
                         stack.pop().__delattr__(co_names[oparg]);
                         break;
 
-                    case Opcode.STORE_GLOBAL:
+                    case STORE_GLOBAL:
                         f.setglobal(co_names[oparg], stack.pop());
                         break;
 
-                    case Opcode.DELETE_GLOBAL:
+                    case DELETE_GLOBAL:
                         f.delglobal(co_names[oparg]);
                         break;
 
-                    case Opcode.LOAD_NAME:
+                    case LOAD_NAME:
                         stack.push(f.getname(co_names[oparg]));
                         break;
 
-                    case Opcode.LOAD_GLOBAL:
+                    case LOAD_GLOBAL:
                         stack.push(f.getglobal(co_names[oparg]));
                         break;
 
-                    case Opcode.DELETE_FAST:
+                    case DELETE_FAST:
                         f.dellocal(oparg);
                         break;
 
-                    case Opcode.LOAD_CLOSURE: {
+                    case LOAD_CLOSURE: {
+                        // Todo: Review this regarding Python 2.7-update
                         PyCell cell = (PyCell) (f.getclosure(oparg));
                         if (cell.ob_ref == null) {
                             String name;
@@ -854,7 +867,8 @@
                         break;
                     }
 
-                    case Opcode.LOAD_DEREF: {
+                    case LOAD_DEREF: {
+                        // Todo: Review this regarding Python 2.7-update
                         // common code from LOAD_CLOSURE
                         PyCell cell = (PyCell) (f.getclosure(oparg));
                         if (cell.ob_ref == null) {
@@ -888,65 +902,85 @@
                         break;
                     }
 
-                    case Opcode.STORE_DEREF:
+                    case STORE_DEREF:
                         f.setderef(oparg, stack.pop());
                         break;
 
-                    case Opcode.BUILD_TUPLE:
+                    case BUILD_TUPLE:
                         stack.push(new PyTuple(stack.popN(oparg)));
                         break;
 
-                    case Opcode.BUILD_LIST:
+                    case BUILD_LIST:
                         stack.push(new PyList(stack.popN(oparg)));
                         break;
 
-                    case Opcode.BUILD_MAP:
-                        stack.push(new PyDictionary());
+                    case BUILD_SET:
+                        stack.push(new PySet(stack.popN(oparg)));
                         break;
 
-                    case Opcode.LOAD_ATTR: {
+                    case BUILD_MAP:
+                        // oparg contains initial capacity:
+                        stack.push(new PyDictionary(PyDictionary.TYPE, oparg));
+                        break;
+
+                    case STORE_MAP: {
+                        PyObject key = stack.pop();
+                        PyObject val = stack.pop();
+                        stack.top().__setitem__(key, val);
+                        break;
+                    }
+
+                    case MAP_ADD: {
+                        PyObject key = stack.pop();
+                        PyObject val = stack.pop();
+                        stack.top(oparg).__setitem__(key, val);
+                        break;
+                    }
+
+                    case LOAD_ATTR: {
                         String name = co_names[oparg];
                         stack.push(stack.pop().__getattr__(name));
                         break;
                     }
 
-                    case Opcode.COMPARE_OP: {
+                    case COMPARE_OP: {
                         PyObject b = stack.pop();
                         PyObject a = stack.pop();
 
                         switch (oparg) {
 
-                            case Opcode.PyCmp_LT:
+                            case PyCmp_LT:
                                 stack.push(a._lt(b));
                                 break;
-                            case Opcode.PyCmp_LE:
+                            case PyCmp_LE:
                                 stack.push(a._le(b));
                                 break;
-                            case Opcode.PyCmp_EQ:
+                            case PyCmp_EQ:
                                 stack.push(a._eq(b));
                                 break;
-                            case Opcode.PyCmp_NE:
+                            case PyCmp_NE:
                                 stack.push(a._ne(b));
                                 break;
-                            case Opcode.PyCmp_GT:
+                            case PyCmp_GT:
                                 stack.push(a._gt(b));
                                 break;
-                            case Opcode.PyCmp_GE:
+                            case PyCmp_GE:
                                 stack.push(a._ge(b));
                                 break;
-                            case Opcode.PyCmp_IN:
+                            case PyCmp_IN:
                                 stack.push(a._in(b));
                                 break;
-                            case Opcode.PyCmp_NOT_IN:
+                            case PyCmp_NOT_IN:
                                 stack.push(a._notin(b));
                                 break;
-                            case Opcode.PyCmp_IS:
+                            case PyCmp_IS:
                                 stack.push(a._is(b));
                                 break;
-                            case Opcode.PyCmp_IS_NOT:
+                            case PyCmp_IS_NOT:
                                 stack.push(a._isnot(b));
                                 break;
-                            case Opcode.PyCmp_EXC_MATCH:
+                            case PyCmp_EXC_MATCH:
+                                // Todo: Review this regarding Python 2.7-update
                                 if (a instanceof PyStackException) {
                                     PyException pye = ((PyStackException) a).exception;
                                     stack.push(Py.newBoolean(pye.match(b)));
@@ -959,7 +993,8 @@
                         break;
                     }
 
-                    case Opcode.IMPORT_NAME: {
+                    case IMPORT_NAME: {
+                        // Todo: Review this regarding Python 2.7-update
                         PyObject __import__ = f.f_builtins.__finditem__("__import__");
                         if (__import__ == null) {
                             throw Py.ImportError("__import__ not found");
@@ -976,13 +1011,14 @@
                         break;
                     }
 
-                    case Opcode.IMPORT_STAR: {
+                    case IMPORT_STAR: {
+                        // Todo: Review this regarding Python 2.7-update
                         PyObject module = stack.pop();
                         imp.importAll(module, f);
                         break;
                     }
 
-                    case Opcode.IMPORT_FROM:
+                    case IMPORT_FROM:
                         String name = co_names[oparg];
                         try {
                             stack.push(stack.top().__getattr__(name));
@@ -996,27 +1032,43 @@
                         }
                         break;
 
-                    case Opcode.JUMP_FORWARD:
+                    case JUMP_FORWARD:
                         next_instr += oparg;
                         break;
 
-                    case Opcode.JUMP_IF_FALSE:
-                        if (!stack.top().__nonzero__()) {
-                            next_instr += oparg;
+                    case POP_JUMP_IF_FALSE:
+                        if (!stack.pop().__nonzero__()) {
+                            next_instr = oparg;
                         }
                         break;
 
-                    case Opcode.JUMP_IF_TRUE:
-                        if (stack.top().__nonzero__()) {
-                            next_instr += oparg;
+                    case POP_JUMP_IF_TRUE:
+                        if (stack.pop().__nonzero__()) {
+                            next_instr = oparg;
                         }
                         break;
 
-                    case Opcode.JUMP_ABSOLUTE:
+                    case JUMP_IF_FALSE_OR_POP:
+                        if (stack.top().__nonzero__()) {
+                            --stack.top;
+                        } else {
+                            next_instr = oparg;
+                        }
+                        break;
+
+                    case JUMP_IF_TRUE_OR_POP:
+                        if (!stack.top().__nonzero__()) {
+                            --stack.top;
+                        } else {
+                            next_instr = oparg;
+                        }
+                        break;
+
+                    case JUMP_ABSOLUTE:
                         next_instr = oparg;
                         break;
 
-                    case Opcode.GET_ITER: {
+                    case GET_ITER: {
                         PyObject it = stack.top().__iter__();
                         if (it != null) {
                             stack.set_top(it);
@@ -1024,7 +1076,7 @@
                         break;
                     }
 
-                    case Opcode.FOR_ITER: {
+                    case FOR_ITER: {
                         PyObject it = stack.pop();
                         try {
                             PyObject x = it.__iternext__();
@@ -1042,52 +1094,95 @@
                         break;
                     }
 
-                    case Opcode.BREAK_LOOP:
+                    case BREAK_LOOP:
                         why = Why.BREAK;
                         break;
 
-                    case Opcode.CONTINUE_LOOP:
+                    case CONTINUE_LOOP:
                         retval = Py.newInteger(oparg);
                         if (retval.__nonzero__()) {
                             why = Why.CONTINUE;
                         }
                         break;
 
-                    case Opcode.SETUP_LOOP:
-                    case Opcode.SETUP_EXCEPT:
-                    case Opcode.SETUP_FINALLY:
+                    case SETUP_LOOP:
+                    case SETUP_EXCEPT:
+                    case SETUP_FINALLY:
                         pushBlock(f, new PyTryBlock(opcode, next_instr + oparg, stack.size()));
                         break;
 
-                    case Opcode.WITH_CLEANUP: {
-                        /*
-                        TOP is the context.__exit__ bound method.
-                        Below that are 1-3 values indicating how/why
-                        we entered the finally clause:
-                        - SECOND = None
-                        - (SECOND, THIRD) = (WHY_{RETURN,CONTINUE}), retval
-                        - SECOND = WHY_*; no retval below it
-                        - (SECOND, THIRD, FOURTH) = exc_info()
+                    case SETUP_WITH: {
+                        PyObject w = stack.top();
+                        PyObject exit = w.__getattr__("__exit__");
+                        if (exit == null) {
+                            break;
+                        }
+                        stack.set_top(exit);
+                        PyObject enter = w.__getattr__("__enter__");
+                        if (enter == null) {
+                            break;
+                        }
+                        w = enter.__call__();
+                        if (w == null) {
+                            break;
+                        }
+                        /* Setup a finally block (SETUP_WITH as a block is
+                        equivalent to SETUP_FINALLY except it normalizes
+                        the exception) before pushing the result of
+                        __enter__ on the stack. */
+                        pushBlock(f, new PyTryBlock(opcode, next_instr + oparg, stack.size()));
+                        stack.push(w);
+                        break;
+                    }
+
+                    case WITH_CLEANUP: {
+                     /* At the top of the stack are 1-3 values indicating
+                        how/why we entered the finally clause:
+                        - TOP = None
+                        - (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval
+                        - TOP = WHY_*; no retval below it
+                        - (TOP, SECOND, THIRD) = exc_info()
+                        Below them is EXIT, the context.__exit__ bound method.
                         In the last case, we must call
-                        TOP(SECOND, THIRD, FOURTH)
+                          EXIT(TOP, SECOND, THIRD)
                         otherwise we must call
-                        TOP(None, None, None)
+                          EXIT(None, None, None)
+
+                        In all cases, we remove EXIT from the stack, leaving
+                        the rest in the same order.
 
                         In addition, if the stack represents an exception,
-                         *and* the function call returns a 'true' value, we
+                        *and* the function call returns a 'true' value, we
                         "zap" this information, to prevent END_FINALLY from
                         re-raising the exception.  (But non-local gotos
                         should still be resumed.)
-                         */
-                        PyObject exit = stack.top();
-                        PyObject u = stack.top(2);
-                        PyObject v;
-                        PyObject w;
-                        if (u == Py.None || u instanceof PyStackWhy) {
+                     */    
+                        PyObject exit;
+                        PyObject u = stack.pop(), v, w;
+                        if (u == Py.None) {
+                            exit = stack.top();
+                            stack.set_top(u);
+                            v = w = Py.None;
+                        } else if (u instanceof PyStackWhy) {
+                            switch (((PyStackWhy) u).why) {
+                            case RETURN:
+                            case CONTINUE:
+                                exit = stack.top(2);
+                                stack.set_top(2, stack.top());
+                                stack.set_top(u);
+                                break;
+                            default:
+                                exit = stack.top();
+                                stack.set_top(u);
+                            }
                             u = v = w = Py.None;
                         } else {
-                            v = stack.top(3);
-                            w = stack.top(4);
+                            v = stack.top();
+                            w = stack.top(2);
+                            exit = stack.top(3);
+                            stack.set_top(u);
+                            stack.set_top(2, v);
+                            stack.set_top(3, w);
                         }
                         PyObject x = null;
                         if (u instanceof PyStackException) {
@@ -1098,15 +1193,14 @@
                         }
 
                         if (u != Py.None && x != null && x.__nonzero__()) {
-                            stack.popN(4); // XXX - consider stack.stackadj op
-                            stack.push(Py.None);
-                        } else {
-                            stack.pop(); // this should be popping off a block
+                            stack.top -= 2; // XXX - consider stack.stackadj op
+                            stack.set_top(Py.None);
                         }
                         break;
                     }
 
-                    case Opcode.CALL_FUNCTION: {
+                    case CALL_FUNCTION: {
+                        // Todo: Review this regarding Python 2.7-update
                         int na = oparg & 0xff;
                         int nk = (oparg >> 8) & 0xff;
 
@@ -1118,12 +1212,13 @@
                         break;
                     }
 
-                    case Opcode.CALL_FUNCTION_VAR:
-                    case Opcode.CALL_FUNCTION_KW:
-                    case Opcode.CALL_FUNCTION_VAR_KW: {
+                    case CALL_FUNCTION_VAR:
+                    case CALL_FUNCTION_KW:
+                    case CALL_FUNCTION_VAR_KW: {
+                        // Todo: Review this regarding Python 2.7-update
                         int na = oparg & 0xff;
                         int nk = (oparg >> 8) & 0xff;
-                        int flags = (opcode - Opcode.CALL_FUNCTION) & 3;
+                        int flags = (opcode - CALL_FUNCTION) & 3;
                         call_function(na, nk,
                                 (flags & CALL_FLAG_VAR) != 0,
                                 (flags & CALL_FLAG_KW) != 0,
@@ -1131,7 +1226,8 @@
                         break;
                     }
 
-                    case Opcode.MAKE_FUNCTION: {
+                    case MAKE_FUNCTION: {
+                        // Todo: Review this regarding Python 2.7-update
                         PyCode code = (PyCode) stack.pop();
                         PyObject[] defaults = stack.popN(oparg);
                         PyObject doc = null;
@@ -1143,7 +1239,7 @@
                         break;
                     }
 
-                    case Opcode.MAKE_CLOSURE: {
+                    case MAKE_CLOSURE: {
                         PyCode code = (PyCode) stack.pop();
                         PyObject[] closure_cells = ((PySequenceList) (stack.pop())).getArray();
                         PyObject[] defaults = stack.popN(oparg);
@@ -1156,7 +1252,7 @@
                         break;
                     }
 
-                    case Opcode.BUILD_SLICE: {
+                    case BUILD_SLICE: {
                         PyObject step = oparg == 3 ? stack.pop() : null;
                         PyObject stop = stack.pop();
                         PyObject start = stack.pop();
@@ -1164,10 +1260,12 @@
                         break;
                     }
 
-                    case Opcode.EXTENDED_ARG:
+                    case EXTENDED_ARG:
+                        // Todo: Review this regarding Python 2.7-update
                         opcode = getUnsigned(co_code, next_instr++);
                         next_instr += 2;
-                        oparg = oparg << 16 | ((getUnsigned(co_code, next_instr) << 8) + getUnsigned(co_code, next_instr - 1));
+                        oparg = oparg << 16 | ((getUnsigned(co_code, next_instr) << 8) +
+                                getUnsigned(co_code, next_instr - 1));
                         break;
 
                     default:
@@ -1203,7 +1301,7 @@
                     System.err.println("Processing block: " + b);
                 }
                 assert (why != Why.YIELD);
-                if (b.b_type == Opcode.SETUP_LOOP && why == Why.CONTINUE) {
+                if (b.b_type == SETUP_LOOP && why == Why.CONTINUE) {
                     pushBlock(f, b);
                     why = Why.NOT;
                     next_instr = retval.asInt();
@@ -1212,15 +1310,16 @@
                 while (stack.size() > b.b_level) {
                     stack.pop();
                 }
-                if (b.b_type == Opcode.SETUP_LOOP && why == Why.BREAK) {
+                if (b.b_type == SETUP_LOOP && why == Why.BREAK) {
                     why = Why.NOT;
                     next_instr = b.b_handler;
                     break;
                 }
-                if (b.b_type == Opcode.SETUP_FINALLY || (b.b_type == Opcode.SETUP_EXCEPT && why == Why.EXCEPTION)) {
+                if (b.b_type == SETUP_FINALLY || (b.b_type == SETUP_EXCEPT && why == Why.EXCEPTION)
+                        || b.b_type == SETUP_WITH) {
                     if (why == Why.EXCEPTION) {
                         PyException exc = ts.exception;
-                        if (b.b_type == Opcode.SETUP_EXCEPT) {
+                        if (b.b_type == SETUP_EXCEPT || b.b_type == SETUP_WITH) {
                             exc.normalize();
                         }
                         stack.push(exc.traceback);
@@ -1251,7 +1350,7 @@
             if (why != Why.RETURN) {
                 retval = Py.None;
             }
-        } else {
+        } else { 
             // store the stack in the frame for reentry from the yield;
             f.f_savedlocals = stack.popN(stack.size());
         }
@@ -1264,7 +1363,7 @@
                     ", blocks: " + stringify_blocks(f));
         }
 
-        if (why == why.EXCEPTION) {
+        if (why == Why.EXCEPTION) {
             throw ts.exception;
         }
 
@@ -1380,7 +1479,6 @@
     }
 
     private static class PyStack {
-
         final PyObject[] stack;
         int top = -1;
 
@@ -1408,6 +1506,10 @@
             stack[top] = v;
         }
 
+        void set_top(int n, PyObject v) {
+            stack[top - n + 1] = v;
+        }
+
         void dup() {
             stack[top + 1] = stack[top];
             top++;
@@ -1500,15 +1602,12 @@
     }
 
     @Untraversable
-    private static class PyTryBlock extends PyObject { // purely to sit on top of the existing PyFrame in f_exits!!!
-
+    private static class PyTryBlock extends PyObject {
+        // purely to sit on top of the existing PyFrame in f_exits!!!
         int b_type;         /* what kind of block this is */
-
         int b_handler;      /* where to jump to find handler */
-
         int b_level;        /* value stack level to pop to */
 
-
         PyTryBlock(int type, int handler, int level) {
             b_type = type;
             b_handler = handler;
@@ -1540,26 +1639,10 @@
     }
 
     private class LineCache {
-
-        private class Pair {
-
-            private final int addr;
-            private final int line;
-
-            private Pair(int a, int b) {
-                this.addr = a;
-                this.line = b;
-            }
-
-            public String toString() {
-                return "(" + addr + "," + line + ")";
-            }
-        }
         List<Integer> addr_breakpoints = new ArrayList<Integer>();
         List<Integer> lines = new ArrayList<Integer>(); // length should be one more than addr_breakpoints
 
         private LineCache() { // based on dis.findlinestarts
-
             int size = co_lnotab.length / 2;
             int p = 0;
             int lastline = -1;
@@ -1584,7 +1667,6 @@
         }
 
         private int getline(int addrq) { // bisect_right to the lineno
-
             int lo = 0;
             int hi = addr_breakpoints.size();
             while (lo < hi) {

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list