[pypy-svn] rev 2442 - in pypy/trunk/src/pypy: interpreter objspace tool

tomek at codespeak.net tomek at codespeak.net
Wed Dec 17 14:58:40 CET 2003


Author: tomek
Date: Wed Dec 17 14:58:40 2003
New Revision: 2442

Added:
   pypy/trunk/src/pypy/tool/pydis.py
Modified:
   pypy/trunk/src/pypy/interpreter/baseobjspace.py
   pypy/trunk/src/pypy/interpreter/pyopcode.py
   pypy/trunk/src/pypy/objspace/trace.py
Log:
We have (Tomek and Richard) written an initial version of TraceObjectSpace. We inherit from an existing object space,
and provide tracing for bytecodes and space operation. Now we will try to write a proxy object for an existing object space,
so that we can take an existing object space and provide tracing for it at the runtime.



Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/trunk/src/pypy/interpreter/baseobjspace.py	Wed Dec 17 14:58:40 2003
@@ -117,7 +117,7 @@
 
     def getexecutioncontext(self):
         "Return what we consider to be the active execution context."
-        ec = getthreadlocals().executioncontext
+        ec = getthreadlocals().executioncontext  #it's allways None (dec. 2003)
         if ec is None:
             ec = self.createexecutioncontext()
         return ec

Modified: pypy/trunk/src/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/pyopcode.py	(original)
+++ pypy/trunk/src/pypy/interpreter/pyopcode.py	Wed Dec 17 14:58:40 2003
@@ -46,6 +46,7 @@
         if fn.has_arg:
             oparg = self.nextarg()
             fn(self, oparg)
+
         else:
             fn(self)
 
@@ -54,6 +55,38 @@
         self.next_instr += 1
         return ord(c)
 
+    def examineop(self):
+        # XXX Testing trace object space
+        # rxxxe Add test?
+
+        c = ord(self.code.co_code[self.next_instr])
+
+        fn = self.dispatch_table[c]
+        values = []
+        arg= ""
+        if fn.has_arg:
+            lo = ord(self.code.co_code[self.next_instr+1])
+            hi = ord(self.code.co_code[self.next_instr+2])
+            arg = (hi<<8) + lo 
+        
+##         for ii in [1,2,3]:
+##             if self.valuestack.depth() >= ii:
+##                 value = self.valuestack.top(ii - 1)
+##                 values.append(value)
+
+            
+        if hasattr(fn, "operationname"):
+            fn_name = fn.operationname
+        else:
+            fn_name = fn.__name__ 
+
+            
+        return c, fn_name, arg, self.next_instr
+
+    def get_index(self):
+        return index
+
+
     def nextarg(self):
         lo = self.nextop()
         hi = self.nextop()

Modified: pypy/trunk/src/pypy/objspace/trace.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/trace.py	(original)
+++ pypy/trunk/src/pypy/objspace/trace.py	Wed Dec 17 14:58:40 2003
@@ -1,6 +1,4 @@
-# ______________________________________________________________________
-import autopath
-import sys, operator, types, new
+import sys, operator, types, new, autopath
 import pypy
 from pypy.objspace.std import StdObjSpace
 from pypy.objspace.trivial import TrivialObjSpace
@@ -8,57 +6,47 @@
 from pypy.interpreter.executioncontext import ExecutionContext
 from pypy.interpreter.pycode import PyCode
 from pypy.interpreter import gateway
-debug = 0
+
+DONT_TRACK_BYTECODES = ["PRINT_ITEM", "PRINT_NEWLINE", "PRINT_EXPR", "PRINT_ITEM_TO", "PRINT_NEWLINE_TO"]
+
 
 class TraceExecutionContext(ExecutionContext):        
-        
+    
     def bytecode_trace(self, frame):
         "Trace function called before each bytecode."
-        #print "XXX %s, %s" % frame.examineop()
         self.space.notify_on_bytecode(frame)
 
-class Logger(object):
-    def __init__(self, name, fn, space, printme):
+
+class Tracer(object):
+    def __init__(self, name, fn, space):
         self.fn = fn
         self.name = name
         self.space = space
-        self.printme = printme
         
     def __call__(self, cls, *args, **kwds):
         assert (not kwds)
 
-        #print self.name
-        #print "%s %s(%s, %s)" % (self.printme, , str(args), str(kwds)) 
-        self.space.notify_on_operation(self.name, None)
+        self.space.notify_on_operation(self.name, args)
         return self.fn(*args, **kwds)
 
     def __getattr__(self, name):
         return getattr(self.fn, name)
 
 
-## XXX Interaction not in scope (yet)
-## class InteractiveLogger(Logger):
-        
-##     def __call__(self, cls, *args, **kwds):
-##         res = Logger.__call__(self, cls, *args, **kwds)
-##         raw_input()
-##         return res
-        
-# ______________________________________________________________________
-
-def Trace(spacecls = StdObjSpace, logger_cls = Logger):
+def Trace(spacecls = StdObjSpace):
 
     class TraceObjSpace(spacecls):
         full_exceptions = False
         
         def initialize(self):
             self.tracing = 0
+            self.ignore_up_to_frame = None
             spacecls.initialize(self)
             method_names = [ii[0] for ii in ObjSpace.MethodTable]
             for key in method_names:
                 if key in method_names:
                     item = getattr(self, key)
-                    l = logger_cls(key, item, self, "class method")
+                    l = Tracer(key, item, self)
                     setattr(self, key, new.instancemethod(l, self, TraceObjSpace))
 
         def start_tracing(self):
@@ -72,16 +60,37 @@
             "Factory function for execution contexts."
             return TraceExecutionContext(self)
 
+        def handle_default(self, frame, opcode, opname, oparg, ins_idx):
+            return opcode, opname, "", ins_idx
+
+        def handle_SET_LINENO(self, frame, opcode, opname, oparg, ins_idx):
+            return opcode, opname, "%s" % oparg, ins_idx
+
+        def handle_LOAD_CONST(self, frame, opcode, opname, oparg, ins_idx):
+            return opcode, opname, "%s (%r)" % (oparg, frame.getconstant(oparg)), ins_idx
+
+        def handle_LOAD_FAST(self, frame, opcode, opname, oparg, ins_idx):
+            return opcode, opname, "%s (%s)" % (oparg, frame.getlocalvarname(oparg)), ins_idx
 
         def notify_on_bytecode(self, frame):
+            if not self.tracing and self.ignore_up_to_frame is frame:
+                self.tracing = 1
+                self.ignore_up_to_frame = None
             if self.tracing:
-                opcode, opname = frame.examineop()
-                self.log_list.append((opname, []))
+                opcode, opname, oparg, ins_idx = frame.examineop()
+                handle_method = getattr(self, "handle_%s" % opname, self.handle_default)
+                
+                opcode, opname, oparg, ins_idx = handle_method(frame, opcode, opname, oparg, ins_idx)
+                self.log_list.append(((opcode, opname, oparg, ins_idx), []))
+                if opname in DONT_TRACK_BYTECODES:
+                    self.ignore_up_to_frame = frame
+                    self.tracing = 0
 
 
         def notify_on_operation(self, name, args):
             if self.tracing:
                 self.log_list[-1][1].append((name, args))
+                
 
         def dump(self):
             return self.log_list
@@ -107,55 +116,32 @@
 
 
 Space = Trace
-#s = Trace(TrivialObjSpace)
-s = Trace()
+
 # ______________________________________________________________________
 # End of trace.py
 
-def add_func(space, func, w_globals):
-    """ Add a function to globals. """
-    func_name = func.func_name
-    w_func_name = space.wrap(func_name)
-    w_func = space.wrap(func)
-    space.setitem(w_globals, w_func_name, w_func)
-
-def run_function(space, func, *args):
-    # Get execution context and globals
-    ec = space.getexecutioncontext()
-    w_globals = ec.make_standard_w_globals()
-
-    # Add the function to globals
-    add_func(space, func, w_globals)
-
-    # Create wrapped args
-    args_w = [space.wrap(ii) for ii in args]
-    code = func.func_code
-    code = PyCode()._from_code(code)
-    # Create frame
-    frame = code.create_frame(space, w_globals)
-    frame.setfastscope(args_w)
-    
-    # start/stop tracing while running frame
-    space.start_tracing()
-    res = frame.run()
-    space.stop_tracing()
-
-    return res
 
+## if __name__ == "__main__":
 
-if __name__ == "__main__":
     
-    def a(b):
-        if b > 0:
-            return a(b-1)
-        else:
-            return b
-
-    print run_function(s, a, 3)
-
-    print ">>>>>>"
-    for line in s.dump():
-        print line
-    print ">>>>>>"
-    for line in s.rdump():
-        print line
+##     s = Trace(TrivialObjSpace)
+    
+##     def a(b):
+##         print "x"
+##         if b > 2:
+##             return b*2 
+##         else:
+##             return b
+
+##     print run_function(s, a, 1)
+
+##     print ">>>>>>"
+##     for line in s.dump():
+##         ((opcode, opname, arg, ins_idx), spaceops) = line
+##         print ins_idx, opname, spaceops
+##     print ">>>>>>"
+##     #for line in s.rdump():
+##     #    print line
+
+##     #import dis
+##     #dis.dis(a)

Added: pypy/trunk/src/pypy/tool/pydis.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/tool/pydis.py	Wed Dec 17 14:58:40 2003
@@ -0,0 +1,137 @@
+import autopath
+import repr
+
+from pypy.interpreter.pycode import PyCode
+from pypy.objspace.std import StdObjSpace
+from pypy.objspace.trivial import TrivialObjSpace
+from pypy.objspace.trace import Trace
+
+
+def get_repr():
+    " Our own repr function for pretty print. "
+    repr_obj = repr.Repr()
+    repr_obj.maxstring = 120
+    repr_obj.maxother = 120
+
+    def our_repr(*args):
+        try:
+            return repr_obj.repr(*args)
+
+        except:
+            return "ERROR"
+
+    return our_repr
+
+ 
+def rpretty_print(spacedump):
+    " Pretty print for rdump() calls to Trace object spaces. "
+
+    Repr = get_repr()
+    for operation, bytecodes in spacedump:
+        for opcode, opname, oparg, ins_idx in bytecodes:
+            print "\t%s\t%s\t\t%s"  % (ins_idx, opname, oparg) 
+
+        if operation is not None:
+            op_name = operation[0]
+            args = operation[1:]
+            print " ***\t", op_name, " ->",
+            for a in args:
+                print Repr(a),
+            print
+
+
+def add_func(space, func, w_globals):
+    """ Add a function to globals. """
+    func_name = func.func_name
+    w_func_name = space.wrap(func_name)
+    w_func = space.wrap(func)
+    space.setitem(w_globals, w_func_name, w_func)
+
+
+def run_in_space(space, func, *args):
+    # Get execution context and globals
+    ec = space.getexecutioncontext()
+    w_globals = ec.make_standard_w_globals()
+
+    # Add the function to globals
+    add_func(space, func, w_globals)
+
+    # Create wrapped args
+    args_w = [space.wrap(ii) for ii in args]
+    code = func.func_code
+    code = PyCode()._from_code(code)
+
+    # Create frame
+    frame = code.create_frame(space, w_globals)
+    frame.setfastscope(args_w)
+    
+    # start/stop tracing while running frame
+    space.start_tracing()
+    res = frame.run()
+    space.stop_tracing()
+
+    return res
+
+
+def pretty_print(spacedump):
+    " Pretty print for rdump() calls to Trace object spaces. "
+    Repr = get_repr()
+
+    for line in spacedump:
+        ((opcode, opname, arg, ins_idx), spaceops) = line
+        start = "%4i %s " % (ins_idx, opname)
+        start = start + " " * (20 - len(start)) + str(arg)
+        start = start + " " * (30 - len(start))
+        if not spaceops:
+            print start
+        else:
+            op = spaceops.pop(0)
+            print start
+            for op_name, args in spaceops:
+                print " " * 30, op_name, Repr(args)
+
+
+def _trace_function(space, reverse_pretty_print_flag, fn, *arg, **kwds):
+    res = run_in_space(space, fn, *arg, **kwds)
+    if reverse_pretty_print_flag:
+        # Get reverse dump
+        spacedump = space.rdump()
+
+        # Pretty print dump
+        rpretty_print(spacedump)
+    else:
+        # Get dump
+        spacedump = space.dump()
+
+        # Pretty dump
+        pretty_print(spacedump)
+
+    return res
+
+def trace_function(trace_space, fn, *arg, **kwds):
+    return _trace_function(trace_space, False, fn, *arg, **kwds)
+
+def rtrace_function(trace_space, fn, *arg, **kwds):
+    return _trace_function(trace_space, True, fn, *arg, **kwds)
+
+
+                   
+ 
+## # Create space
+## if __name__ == "__main__":
+##     try:
+##         import readline
+##     except ImportError:
+##         pass
+
+##     from pypy.tool import option
+##     from pypy.tool import test
+##     args = option.process_options(option.get_standard_options(),
+##                                   option.Options)
+##     objspace = option.objspace()
+
+
+##     def run(*args, **kwds):
+##     def run_function(space, func, *args):
+##     from pypy.objspace.std import StdObjSpace
+##     space = Trace(StdObjSpace)


More information about the Pypy-commit mailing list