Commits

Jim Hugunin  committed f0f438b Draft

Two optimizations:
Add setslice, getslice, delslice methods to PyObject, so no need
to create a new PySlice object for simple slicing.
Also, use special invoke method on PyObject for __getattr__+__call__
This avoids creation of bound methods in most cases.

  • Participants
  • Parent commits 18f7aaa

Comments (0)

Files changed (2)

File org/python/compiler/CodeCompiler.java

 		c.freeLocal(strings);
 	}
 
+    public int invokea0, invokea1, invokea2;
+    public int invoke2;
+    public Object Invoke(SimpleNode inst, SimpleNode nname, SimpleNode[] values) throws Exception {
+		String name = (String)nname.getInfo();
+		inst.visit(this);
+        code.ldc(name);
+        
+        //System.out.println("invoke: "+name+": "+values.length);
+        
+	    switch (values.length) {
+	        case 0:
+	            if (mrefs.invokea0 == 0) {
+	                mrefs.invokea0 = code.pool.Methodref("org/python/core/PyObject", "invoke",
+				        "(Ljava/lang/String;)Lorg/python/core/PyObject;");
+				}
+				code.invokevirtual(mrefs.invokea0);
+				break;
+		    case 1:
+	            if (mrefs.invokea1 == 0) {
+	                mrefs.invokea1 = code.pool.Methodref("org/python/core/PyObject", "invoke",
+				        "(Ljava/lang/String;Lorg/python/core/PyObject;)Lorg/python/core/PyObject;");
+				}
+				values[0].visit(this);
+				code.invokevirtual(mrefs.invokea1);
+				break;
+		    case 2:
+	            if (mrefs.invokea2 == 0) {
+	                mrefs.invokea2 = code.pool.Methodref("org/python/core/PyObject", "invoke",
+				        "(Ljava/lang/String;Lorg/python/core/PyObject;Lorg/python/core/PyObject;)Lorg/python/core/PyObject;");
+				}
+				values[0].visit(this);
+				values[1].visit(this);
+				code.invokevirtual(mrefs.invokea2);
+				break;			    
+			default:
+    		    makeArray(values);
+    			if (mrefs.invoke2 == 0) {
+    				mrefs.invoke2 = code.pool.Methodref("org/python/core/PyObject", "invoke",
+    					"(Ljava/lang/String;[Lorg/python/core/PyObject;)Lorg/python/core/PyObject;");
+    			}
+    			code.invokevirtual(mrefs.invoke2);
+    			break;
+    	}
+
+		return null;
+        
+    }
+
+
 
 	public int call1, call2;
 	public int calla0, calla1, calla2, calla3, calla4;
 	public Object Call_Op(SimpleNode node) throws Exception {
 		//do name
-		node.getChild(0).visit(this);
+		SimpleNode callee = node.getChild(0);
 
 		//get arguments and keywords
 		SimpleNode args=null;
 		} else {
 			values = new SimpleNode[0];
 		}
-
-
+		
+		// Detect a method invocation with no keywords
+        if (nKeywords == 0 && callee.id == PythonGrammarTreeConstants.JJTDOT_OP) {
+		    return Invoke(callee.getChild(0), callee.getChild(1), values);
+		}
+		
+		callee.visit(this);
 
 		if (nKeywords > 0) {
 		    makeArray(values);
 		return null;
 	}
 
+
+    public int getslice, setslice, delslice;
+    public Object Slice_Op(SimpleNode seq, SimpleNode node) throws Exception {
+		int old_mode = mode;
+		mode = GET;		
+		seq.visit(this);
+		
+		SimpleNode[] slice = new SimpleNode[3];
+		int n = node.getNumChildren();
+		int i=0;
+		for(int j=0; j<n; j++) {
+			SimpleNode child = node.getChild(j);
+			if (child.id == PythonGrammarTreeConstants.JJTCOLON) i++;
+			else slice[i] = child;
+		}
+		for(i=0; i<3; i++) {
+			if (slice[i] == null) {
+				code.aconst_null();
+			} else {
+				slice[i].visit(this);
+			}
+		}
+		mode = old_mode;
+
+		switch(mode) {
+		case DEL:
+			if (mrefs.delslice == 0) {
+				mrefs.delslice = code.pool.Methodref("org/python/core/PyObject", "__delslice__",
+					"(Lorg/python/core/PyObject;Lorg/python/core/PyObject;Lorg/python/core/PyObject;)V");
+			}
+			code.invokevirtual(mrefs.delslice);
+			return null;
+		case GET:
+			if (mrefs.getslice == 0) {
+				mrefs.getslice = code.pool.Methodref("org/python/core/PyObject", "__getslice__",
+					"(Lorg/python/core/PyObject;Lorg/python/core/PyObject;Lorg/python/core/PyObject;)Lorg/python/core/PyObject;");
+			}
+			code.invokevirtual(mrefs.getslice);
+			return null;
+		case SET:
+			code.aload(temporary);
+			if (mrefs.setslice == 0) {
+				mrefs.setslice = code.pool.Methodref("org/python/core/PyObject", "__setslice__",
+					"(Lorg/python/core/PyObject;Lorg/python/core/PyObject;Lorg/python/core/PyObject;Lorg/python/core/PyObject;)V");
+			}
+			code.invokevirtual(mrefs.setslice);
+			return null;
+		}
+		return null;
+        
+    }
+
 	public int getitem, delitem, setitem;
 	public Object Index_Op(SimpleNode node) throws Exception {
+		SimpleNode seq = node.getChild(0);
+		SimpleNode index = node.getChild(1);
+        if (index.id == PythonGrammarTreeConstants.JJTSLICE) return Slice_Op(seq, index);
+		
 		int old_mode = mode;
-		mode = GET;
-		node.getChild(0).visit(this);
-		node.getChild(1).visit(this);
+		mode = GET;		
+		seq.visit(this);
+		index.visit(this);
 		mode = old_mode;
 
 		switch(mode) {

File org/python/core/PySequence.java

 	}
 
     protected static final int sliceLength(int start, int stop, int step) {
+        //System.err.println("slice: "+start+", "+stop+", "+step);
         if (step > 0) {
             return (stop-start+step-1)/step;
         } else {
 	}
 
     private static final int getIndex(PyObject index, int defaultValue) {
-        if (index == Py.None) return defaultValue;
+        if (index == Py.None || index == null) return defaultValue;
         if (!(index instanceof PyInteger)) throw Py.TypeError("slice index must be int");
         return ((PyInteger)index).getValue();
     }
 	    }
 	    return ret;
 	}
+	
+	public PyObject __getslice__(PyObject s_start, PyObject s_stop, PyObject s_step) {
+		int start, stop, step;
+        int length = __len__();
+        step = getIndex(s_step, 1);
+        if (step == 0) throw Py.TypeError("slice step of zero not allowed");
+        
+        if (step > 0) {
+            start = getIndex(s_start, 0);
+            stop = getIndex(s_stop, length);
+        } else {
+            start = getIndex(s_stop, 0);
+            stop = getIndex(s_start, length);
+        }
+		
+		if (start < 0) {
+		    start = length+start;
+		    if (start < 0) start = 0;
+		} else if (start > length) {
+		    start = length;
+		}
+		if (stop < 0) {
+		    stop = length+stop;
+		    if (stop < 0) stop = 0;
+		} else if (stop > length) {
+		    stop = length;
+		}
+		
+		if (stop < start) stop = start;
+		
+		if (step <= 0) {
+		    int tmp = start; start = stop; stop = tmp;
+		}
+		return getslice(start, stop, step);
+	}
+	public void __setslice__(PyObject s_start, PyObject s_stop, PyObject s_step, PyObject value) {
+		int start, stop, step;
+        int length = __len__();
+        step = getIndex(s_step, 1);
+        if (step == 0) throw Py.TypeError("slice step of zero not allowed");
+        
+        if (step > 0) {
+            start = getIndex(s_start, 0);
+            stop = getIndex(s_stop, length);
+        } else {
+            start = getIndex(s_stop, 0);
+            stop = getIndex(s_start, length);
+        }
+		
+		if (start < 0) {
+		    start = length+start;
+		    if (start < 0) start = 0;
+		} else if (start > length) {
+		    start = length;
+		}
+		if (stop < 0) {
+		    stop = length+stop;
+		    if (stop < 0) stop = 0;
+		} else if (stop > length) {
+		    stop = length;
+		}
+		
+		if (stop < start) stop = start;
+		
+		if (step <= 0) {
+		    int tmp = start; start = stop; stop = tmp;
+		}
+        setslice(start, stop, step, value);
+	}
+	public void __delslice__(PyObject s_start, PyObject s_stop, PyObject s_step) {
+		int start, stop, step;
+        int length = __len__();
+        step = getIndex(s_step, 1);
+        if (step == 0) throw Py.TypeError("slice step of zero not allowed");
+        
+        if (step > 0) {
+            start = getIndex(s_start, 0);
+            stop = getIndex(s_stop, length);
+        } else {
+            start = getIndex(s_stop, 0);
+            stop = getIndex(s_start, length);
+        }
+		
+		if (start < 0) {
+		    start = length+start;
+		    if (start < 0) start = 0;
+		} else if (start > length) {
+		    start = length;
+		}
+		if (stop < 0) {
+		    stop = length+stop;
+		    if (stop < 0) stop = 0;
+		} else if (stop > length) {
+		    stop = length;
+		}
+		
+		if (stop < start) stop = start;
+		
+		if (step <= 0) {
+		    int tmp = start; start = stop; stop = tmp;
+		}
+        delRange(start, stop, step);
+	}		
 
 	public void __setitem__(int index, PyObject value) {
 		int i = fixindex(index);