1. Shashank Bharadwaj
  2. jython-notes

Commits

Shashank Bharadwaj  committed 55a796c

added all new content on MethodHandles, and finished the new formatting

  • Participants
  • Parent commits c7e35da
  • Branches default

Comments (0)

Files changed (1)

File jvmlangsummit-2011/slides.rst

View file
  • Ignore whitespace
 
 
 Outline
-=======
+-------
 
 * What is Jython?
 * Call-site specialization
 * Iterator Expression Transformation
 
+.. raw:: pdf
+  
+  PageBreak
+
 
 Outline
-=======
+-------
 
 * **What is Jython?**
 * Call-site specialization
 * Iterator Expression Transformation
 
+.. raw:: pdf
+  
+  PageBreak
+
 
 What is Jython?
 ===============
 
 Jython is an implementation of the *Python Programming Language*
-written in Java.
+that compiles to JVM bytecode.
 
 Jython 2.6 will:
 
        * improve performance by using invokedynamic
 
 
-How is Python compiled to Java?
-===============================
+.. raw:: pdf
+  
+  PageBreak
+
+
+How is Python compiled to Java Bytecode?
+----------------------------------------
 
 Consider the python program:
 
       print a + b + c
 
 
-
-
 .. raw:: pdf
 
    PageBreak
 
 .. code-block:: java
 
-   ... {
       PyObject a, b, c;
       PyObject tmp = a._add(b)._add(c);
       Py.println(tmp);
-   }
 
 .. raw:: pdf
 
    PageBreak
 
-Different flavors of argument passing in Python
------------------------------------------------
 
-.. code-block:: python
+Different flavors of arg passing in Python
+------------------------------------------
 
-   def f(a, b, c):
-     print a, b, c
-
-Call using formal arguments:
-
-.. code-block:: python
-
-   f(1, 2, 3)
-
-Will produce::
-
-   1 2 3
++------------------------------------+---------------------------------+
+| positional/formal arguments	     | .. code-block:: python          |
+| 		    		     | 	  	       		       |
+|				     |	f(1, 2, 3)		       |
++------------------------------------+---------------------------------+
+| keyword arguments        	     | .. code-block:: python          |
+| 		    		     | 	  	       		       |
+|				     |	f(b=2, c=3, a=1)	       |
++------------------------------------+---------------------------------+
+| star/variable arguments	     | .. code-block:: python          |
+| 		    		     | 	  	       		       |
+| 		    		     | 	vargs = (2, 3) 		       |
+|				     |	f(1, *vargs)		       |
++------------------------------------+---------------------------------+
+| variable keyword arguments	     | .. code-block:: python          |
+| 		    		     | 	  	       		       |
+| 		    		     | 	kwargs = {'a':1, 'b':2, 'c':3} |
+|				     |	f(**kwargs)		       |
++------------------------------------+---------------------------------+
 
 .. raw:: pdf
 
    PageBreak
 
-Different flavors of argument passing in Python
------------------------------------------------
 
-.. code-block:: python
 
-   def f(a, b, c):
-     print a, b, c
+Outline
+=======
 
-Call using keyword arguments:
-
-.. code-block:: python
-   
-   f(c=3, a=1, b=2)
-   
-Will produce::
-
-   1 2 3
+* What is Jython?
+* **Call-site specialization**
+* Iterator Expression Transformation
 
 .. raw:: pdf
 
    PageBreak
 
-Different flavors of argument passing in Python
------------------------------------------------
+Call-site specialization
+========================
 
-.. code-block:: python
 
-   def f(a, b, c):
-     print a, b, c
-
-Call using var args or star args:
-
-.. code-block:: python
-   
-   vargs = (2, 3)
-   f(1, *args)
-
-Will produce::
-
-   1 2 3
-
++------------------------------------+---------------------------------+
+| positional/formal arguments        | .. code-block:: python          |
+| 		    		     | 	  	       		       |
+|				     |	f(1, 2, 3)		       |
++------------------------------------+---------------------------------+
+| keyword arguments        	     | .. code-block:: python          |
+| 		    		     | 	  	       		       |
+|				     |	f(b=2, c=3, a=1)	       |
++------------------------------------+---------------------------------+
+| star/variable arguments	     | .. code-block:: python          |
+| 		    		     | 	  	       		       |
+| 		    		     | 	vargs = (2, 3) 		       |
+|				     |	f(1, *vargs)		       |
++------------------------------------+---------------------------------+
+| variable keyword arguments	     | .. code-block:: python          |
+| 		    		     | 	  	       		       |
+| 		    		     | 	kwargs = {'a':1, 'b':2, 'c':3} |
+|				     |	f(**kwargs)		       |
++------------------------------------+---------------------------------+
 
 .. raw:: pdf
 
    PageBreak
 
-Different flavors of argument passing in Python
------------------------------------------------
+Python ``def`` compiles to ...
+------------------------------
 
 .. code-block:: python
 
    def f(a, b, c):
-     print a, b, c
-
-Call using a dictionary of keyword args:
-
-.. code-block:: python
-   
-   kwargs = {'a':1, 'c':3, 'b':2}
-   f(**kwargs)
-
-Will produce::
-
-   1 2 3
+       print a + b + c
 
 
 .. raw:: pdf
    PageBreak
 
 
-Support all argument types  by ``PyFrame``
-------------------------------------------
-
-.. code-block:: java
-
-   // Just before calling the function:
-   PyFrame frame = new PyFrame();
-   frame.setlocal(0, 1);
-   frame.setlocal(1, 2);
-   frame.setlocal(2, 3);
-
-   // Inside the function
-   PyObject a = frame.getlocal(0);
-   PyObject b = frame.getlocal(1);
-   PyObject c = frame.getlocal(2);
-
-* ``ArgParser`` is used to convert other types of arguments on the 
-  frame to match this calling convention
-
-.. raw:: pdf
-
-   PageBreak
-
-
-Putting it all together - function definition
----------------------------------------------
+Python ``def`` compiles to a method
+-----------------------------------
 
 .. code-block:: python
 
    PageBreak
 
 
-Putting it all together - call-site
----------------------------------------------
+Python ``def`` compiles to a method
+-----------------------------------
+
+.. code-block:: python
+
+   def f(a, b, c):
+       print a + b + c
+
+
+At the function definition:
+
+.. code-block:: java
+
+   PyCode f$1;
+
+   f$1 = Py.newCode(paramNames, "f", func_id, paramDefaults, ..);
+   PyFunction pyFunc = new PyFunction(f$1, ..);
+   frame.setglobal("f", pyFunc);
+
+.. raw:: pdf
+
+   PageBreak
+
+
+
+Python formal arg call compiles to
+----------------------------------
 
 .. code-block:: python
 
 
 .. code-block:: java
    
-   frame.getglobal("f").__call__(_1, _2, _3);
-   
    PyInteger _1 = PyInteger.new(1);
    PyInteger _2 = PyInteger.new(2);
    PyInteger _3 = PyInteger.new(3);
+   
+   frame.getglobal("f").__call__(_1, _2, _3);
 
 .. raw:: pdf
 
    PageBreak
 
 
+Python keyword arg call compiles to
+-----------------------------------
+
+.. code-block:: python
+
+   f(b=2, c=3, a=1)
+
+Is compiled to: 
+
+.. code-block:: java
+   
+    PyObject[] args = new PyObject[3];
+    args[0] = _2;
+    args[1] = _3;
+    args[2] = _1;
+    String[] kwString = new String[3];
+    kwString[0] = "b";
+    kwString[1] = "c";
+    kwString[2] = "a";
+    
+    frame.getglobal("f").__call__(args, kwString);
+
 
 
 Putting it all together
 -----------------------
 
-.. image:: images/call_function-1.png
+.. image:: images/before-1.png
 
 .. raw:: pdf
 
 Putting it all together
 -----------------------
 
-.. image:: images/call_function-2.png
+.. image:: images/before-2.png
 
 .. raw:: pdf
 
 Putting it all together
 -----------------------
 
-.. image:: images/call_function-3.png
+.. image:: images/before-3.png
 
 .. raw:: pdf
 
 Putting it all together
 -----------------------
 
-.. image:: images/call_function-4.png
+.. image:: images/before-4.png
+
+.. raw:: pdf
+
+   PageBreak
+
+
+Putting it all together
+-----------------------
+
+.. image:: images/before-5.png
 
 .. raw:: pdf
 
 Putting it all together
 -----------------------
 
-.. image:: images/call_function-5.png
+.. image:: images/before-6.png
 
 .. raw:: pdf
 
    PageBreak
 
-Putting it all together
------------------------
-
-.. image:: images/call_function-6.png
-
-.. raw:: pdf
-
-   PageBreak
-
-
-But... storing args on frame is costly
---------------------------------------
-
-.. image:: images/slow_frame.png
-
-.. raw:: pdf
-
-   PageBreak
-
-But... ``call_function`` is megamorphic
----------------------------------------
-
-.. image:: images/megamorphic_call.png
-
-.. raw:: pdf
-
-   PageBreak
 
 
 Jython cannot statically bind, because
 
 .. code-block:: python
 
-   def foo():
-       print 'Hello World'
+   def foo(arg):
+       print 'Hi', arg
 
-   code_string = "print 'Hi'"
-   code = compile(code_string, "<string>", "exec")
-   
-   foo()         # prints 'Hello World'
-   foo.func_code = code
-   foo()         # prints 'Hi'
+   while(i > 0):
+       foo("JVM")
+       def foo(arg, opt="2011")
+       	  print 'Hi', arg, opt
+       i -= 1  
 
 Will produce::
 
-     Hello World
-     Hi
+     Hi JVM
+     Hi JVM 2011
 
+.. raw:: pdf
 
+   PageBreak
 
-Using Invokedynamic provides the solution (1)
----------------------------------------------
+
+Using ``MethodHandles`` for the solution [1]
+--------------------------------------------
 
 Create an function which takes in args on stack
 
 .. code-block:: java
 
     // optimized version 
-    public PyObject _f(PyFrame frame, ThreadState ts, PyObject a1,
+    public PyObject f$1(PyFrame frame, ThreadState ts, PyObject a1,
    	  	      PyObject a2, PyObject a3){
-        // implementation
+        Py.println(a1._add(a2)._add(a3));
     }		      
-
-    // wrapper function to support other types of argument passing
-    public PyObject f(PyFrame frame, ThreadState ts) {
-        _f(frame, ts, frame.getlocal(0),
-	              frame.getlocal(1),
-		      frame.getlocal(2));
-    }		      
-
         
 
 .. raw:: pdf
    PageBreak
 
 
+Using ``MethodHandles`` for the solution [2]
+--------------------------------------------
 
-Using Invokedynamic provides the solution (2)
----------------------------------------------
+At the function ``def`` point, create and store a methodhandle
 
-A ``SwitchPoint`` with:
+.. code-block:: java
 
-+---------------------+------------------------------------------------------------------------+
-| Target	      | .. code-block:: java                                                   |
-|                     |                                                        		       |
-|                     |    invoke_f(PyFrame prevFrame, ThreadState ts, PyObject a1,            |
-|                     |             PyObject a2, PyObject a3} {                       	       |
-|                     |        PyFrame frame = setup(...);                     	    	       |
-|                     |        _f(frame, ts, a1, a2, a3);				       |
-|                     |    }                                                    	       |
-+---------------------+------------------------------------------------------------------------+
-| Fallback            | .. code-block:: java						       |
-|                     |                                                          	       |
-|                     |    fallback(PyFrame prevFrame, ThreadState ts){         	       |
-|                     |        prevFrame.getglobal("foo").__call__(...);        	       |
-|                     |    }                                                    	       |
-+---------------------+------------------------------------------------------------------------+
+   PyCode f$1;
 
-invalidated when ``func_code`` is changed
+   f$1 = Py.newCode(paramNames, "f", func_id, paramDefaults, ..);
+   
+   f$1.mHandle = MethodHandles.lookup()
+                 .findVirtual(getClass(), "f$1", Py.getMethodType(3));
+   f$1.mHandle.bindTo(this);
+
+   PyFunction pyFunc = new PyFunction(f$1, ..);
+   frame.setglobal("f", pyFunc);
+   return frame;
+
 
 .. raw:: pdf
 
    PageBreak
 
-Using Invokedynamic provides the solution (3)
----------------------------------------------
-.. code-block:: python
 
-   f(1, 2, 3)
 
-.. code-block:: java
 
-   public PyObject _f(PyFrame frame, ThreadState ts, PyObject a1, 
-   	  	      PyObject a2, PyObject a3){ ... }
+Using ``MethodHandles`` for the solution [3]
+--------------------------------------------
 
-   // call-site
-   indy_dispatch(frame, ts, _1, _2, _3);
-
-   public PyObject invoke_f(PyFrame prevFrame, ThreadState ts, PyObject a1, 
-   	  	   	    PyObject a2, PyObject a3) {
-	// setup the frame
-	_f(frame, ts, a1, a2, a3);
-   }
-
+.. image:: images/after.png
 
 .. raw:: pdf
 
    PageBreak
 
 
-Results
--------
 
-* **4x** improvement on micro-benchmarks
-* Up-to xx% improvement on the benchmark suite
+Results: 2.3x improvement in Fibonacci
+--------------------------------------
+
+.. code-block:: python
+
+   def fibonacci(n):
+    if n == 1:
+        return 0
+    elif n == 2:
+        return 1
+    else:
+        return fibonacci(n - 1) + fibonacci(n - 2)
+
+   fibonacci(28)
+    
+.. raw:: pdf
+
+   PageBreak
+
+
+Results: Overall benchmark suite
+--------------------------------
+
+.. image:: images/MethodHandleOpt.png
+   :width: 90%
 
 .. raw:: pdf
 
    PageBreak
 
 
-Future
-------
+Future: Frame creation costly, use ``@frameless``?
+--------------------------------------------------
 
-* Extend the calling convention change to keyword arguments
-* Support annotations in Python like ``@frameless``
+.. image:: images/frameless_problem.png
 
-.. code-block:: python
+.. raw:: pdf
 
-   @frameless
-   def f(a, b, c):
-      print a, b, c
+   PageBreak
+
 
 Outline
-=======
+-------
 
 * What is Jython?
 * Call-site specialization
 * **Iterator Expression Transformation**
 
+.. raw:: pdf
 
-Iterator Expressions Transformation
-===================================
+   PageBreak
+
+
+Iterator Expression Transformation
+==================================
+
+Consider the ``for`` loop in Python
+
+.. code-block:: python
+
+    for i in xrange(1, 10000000):
+        sum += (sum ^ i) / i
+
+.. raw:: pdf
+
+   PageBreak
+
+
+Current implementation is slow
+------------------------------
+
+
+.. code-block:: java
+
+	PyObject _2 = Py.newInteger(1);
+   	PyObject _3 = Py.newInteger(10000000);
+        xrangePyObj = frame.getglobal("xrange").__call__(ts, _2, _3).__iter__();
+        do {
+            frame.setlocal(2, itemPyObj);
+            PyObject sumPyObj = frame.getlocal(1);
+            localPyObj = sumPyObj._iadd(paramPyFrame.getlocal(1)
+                                 ._xor(paramPyFrame.getlocal(2))
+                    		 ._div(paramPyFrame.getlocal(2)));
+            frame.setlocal(1, localPyObj);
+            itemPyObj = ((PyObject)xrangePyObj).__iternext__();
+        } while (itemPyObj != null);
+
+.. raw:: pdf
+
+   PageBreak
+
 
 Ideally
+-------
 
 .. code-block:: python
 
    PageBreak
 
 
-Jython with invokedynamic
--------------------------
 
-Setup a ``SwitchPoint`` with following ``target`` and ``fallback``
-
-.. code-block:: java
-
-	public static void xrangeFallback(PyObject self) throws Exception {
-		throw new IndyOptimizerException("Need to fall back out of xrange");
-	}
-
-	public static void xrangeTarget(PyObject self) {
-		return;
-	}
-
-
-The ``SwitchPoint`` is invalidated if the ``func_code`` is changed or a ``setglobal`` on ``"xrange"``
-
-.. raw:: pdf
-
-   PageBreak
-
-Jython with invokedynamic
--------------------------
+Using ``invokedynamic`` to improve performance
+----------------------------------------------
 
 .. code-block:: java
 
    try {
-        indyDispatch();
+        // invokedynamic(frame.getglobal("xrange"));
         int start, stop, step;
    	// fill up start, stop and step values
 
         }
 
     } catch (Exception e) {
-        // Call the Python Byte Code VM [PBCVM]
+        // fallback to the previous way of using
+	// __iternext__
     }
 
 
+.. TODO: need to change the code so that in the fallback
+   we produce the whole code-block again
+
+.. raw:: pdf
+
+   PageBreak
+
 Results
 -------
 
-* **2x** to **10x** improvement on micro-benchmarks
-* Up-to 10% improvement on the benchmark suite
+* **10x** improvement on the following micro-benchmark
+
+.. code-block:: python
+
+   def main():
+       sum = 0
+       for i in range(1, 10000000):
+           sum += (sum ^ i) / i
+
+.. raw:: pdf
+   
+   PageBreak
+
+
+Results: 4% improvement across the suite
+----------------------------------------
+
+.. image:: images/xrange_result.png
+
+.. raw:: pdf
+   
+   PageBreak
+
+Future:
+-------
+
+* Extend the same logic to:
+  - Iterators
+  - Decorators
+
+.. raw:: pdf
+   
+   PageBreak
 
 
 Questions
-=========
+---------
 
    **Thank You!**
 
 
-.. Images will be put here
+But... ``call_function`` cannot inline
+--------------------------------------
 
-.. |Jython_small| image:: images/Jython-small.png
-   	   :align: bottom
-	   :alt: Jython Logo
++------------------------------------------------+----------------------------------------------+
+| .. code-block:: java                           | .. code-block:: java                         |
+|                                                |                                              |
+|    public PyObject f$1(PyFrame f,              |    public PyObject call(ThreadState ts,      |
+|                  ThreadState ts) {             |           PyObject a1, PyObject a2,          |
+|        // implementation                       |           PyObject a3) {                     |           
+|    }                                           |                                              |
+|                                                |        PyFrame frame = new PyFrame(this);    |
+|    PyFunction pyFunc = new PyFunction(f$1, .); |        frame.fastlocals[0] = a1;             |
+|    frame.setglobal("f", pyFunc);               |        frame.fastlocals[1] = a2;             |
+|                                                |        frame.fastlocals[2] = a3;             |
+|    frame.getglobal("f")                        |        call(ts, frame);                      |
+|         .__call__(_1, _2, _3);                 |    }                                         |
+|                                                |                                              |
+|    public PyObject call_function(int func_id,  |    public PyObject call(ThreadState ts,      |
+|           PyFrame f, ThreadState ts) {         |                         PyFrame frame) {     |
+|        switch(func_id){                        |        ...  // setup frame                   |
+|            case 1:                             |        call_function(func_id, frame, ts);    |
+|                return f$1(f, ts);              |    }                                         |
+|            ...                                 |                                              |
+|    }                                           |                                              |
++------------------------------------------------+----------------------------------------------+
+
+
+.. raw:: pdf
+
+   PageBreak
+
+