You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by dj...@apache.org on 2006/08/10 02:05:59 UTC

svn commit: r430193 - /db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java

Author: djd
Date: Wed Aug  9 17:05:59 2006
New Revision: 430193

URL: http://svn.apache.org/viewvc?rev=430193&view=rev
Log:
DERBY-766 (partial) Modify the approach in the split expressions method of CodeChunk to only identify
self-contained chunks of byte code from a limited set of instructions. Thus this is a "fail-safe" approach,
rather than trying to catch all the opcodes that would make a set of byte code not self-contained.
Incremental development, method is still not called and does not perform any splits yet,
I test it with calls from BCMethod and a reduced split threshold (e.g. split if the method
is ~3k big instead of the limit of 64k).

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java?rev=430193&r1=430192&r2=430193&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java Wed Aug  9 17:05:59 2006
@@ -1594,7 +1594,7 @@
      * for the arguments will push and pop values but never drop
      * below the stack value at the start of the byte code sequence.
      * E.g. in the examples the stack before the first arg will be
-     * N+1 (the instance for the method call) and at the end of the
+     * N+1 (the objectref for the method call) and at the end of the
      * byte code for arg1 will be N+2 or N+3 depending on if arg1 is
      * a single or double word argument. During the execution of
      * the byte code the stack may have had many arguments pushed
@@ -1602,7 +1602,7 @@
      * code for arg1 is independent of the stack's previous values
      * and is self contained. This self-containment then extends to
      * all the arguements, the method call itself and pushing the
-     * object reference for the method call, thus the complete
+     * objectref for the method call, thus the complete
      * sequence is self-contained.
      * <BR>
      * The self-containment breaks in a few cases, take the simple
@@ -1611,23 +1611,28 @@
      * push3 this swap invoke
      * </code>
      * In this case the byte code for arg1 (swap) is not self-contained
-     * and relies on earlier stack values. The set of instrcutions
+     * and relies on earlier stack values. The set of instructions
      * that break the self-containment are limited and thus can be
      * checked for easily.
      * <P>
      * How to identify "self-contained blocks of code".
      * <BR>
      * We walk through the byte code and maintain a history of
-     * the program counter when the stack most recently
-     * achieved each depth. E.g.
+     * the program counter when the stack changed. If a word
+     * was pushed by an opcode that does not depend on previous
+     * stack values the current program counter is recorded
+     * otherwise -1 is set to indicate stack value may depend
+     * on previous stack values.
      * <code>
      * pcDepth[N] = 45
-     * pcDepth[N+1] = 46
+     * pcDepth[N+1] = -1
      * pcDepth[N+2] = 52
      * </code>
-     * When an instruction causes the stack to decrease to M
-     * all the entries between M and the current stack value
-     * are cleared, once we determine if we need to split or not.
+     * <BR>
+     * The pcDepth represents a program counter that caused
+     * the stack to reach that depth and is independent of
+     * previous stack entries. Initially a very limited
+     * number of opcodes are supported as independent.
      * <BR>
      * If the instruction that caused the stack decrease
      * is an invoke byte code that matches what we are looking for
@@ -1647,7 +1652,8 @@
      *  WORK IN PROGRESS - Incremental development
      *  <BR>
      *  Currently just walks the method maintaining the
-     *  pcByDepth array. Does not perform any split.
+     *  pcByDepth array and identifies potential blocks
+     *  to splt. Does not perform any split.
      *  Not called by submitted code. Tested with local
      *  changes from calls in BCMethod.
      *  
@@ -1664,14 +1670,13 @@
         
         int stack = 0;
                
+        //TODO: this conditional handling is copied from
+        //the splitZeroStack code, need to check to see
+        // how it fits with the expression logic.
         // do not split until at least this point (inclusive)
         // used to ensure no split occurs in the middle of
         // a conditional.
-        int outerConditionalEnd_pc = -1;
-        
-        System.out.println("splitExpressionOut " + mb.getName()
-        		+ " " + codeLength);
-   
+        int outerConditionalEnd_pc = -1;  
 
         int end_pc = 0 + codeLength;
         for (int pc = 0; pc < end_pc;) {
@@ -1719,50 +1724,129 @@
                 }
                 continue;
             }
-            
-            if (stackDelta == 0)
-                continue;
+
+            // Set up independent points.
+            // 
+            // Code in this switch either
+            // 1) 'break's out not changing anything
+            // to indicate the instruction left the
+            // stack in such that its independence
+            // at the current stack level is left unchanged.
+            //
+            // 2) Marks the opcode_pc as the independent
+            // start point for the current stack depth.
+            //
+            // 3) marks the current stack depth as not
+            // having an independent start point. In some cases
+            // that may be a false assertion as it's a fail safe
+            // system. Only a small defined set of instructions
+            // are handled as valid starting points. More development
+            // and thought can be put into handling more cases as required.
+            // The 'this' ALOAD_0 instruction will cover most cases.
             
             int opcode_pc = pc - instructionLength(opcode);
-
-            // Only split when the stack is having items popped
-            if (stackDelta > 0)
+            switch (opcode)
             {
-                // pushing double word.
-                if (stackDelta == 2)
-                    pcByDepth[stack - 1] = -1;
-                pcByDepth[stack] = opcode_pc;
-                continue;
-            }
-            
-            // Only handle the cases discussed above.
-            switch (opcode) {
+            // Independent instructions that do not modify the stack
+            case VMOpcode.NOP: 
+            	break;
+            	
+            // Independent instructions that push one value
+            case VMOpcode.ALOAD_0: // push 'this'
+            	pcByDepth[stack] = opcode_pc;
+            	break;
+
             case VMOpcode.INVOKEINTERFACE:
             case VMOpcode.INVOKEVIRTUAL:
-                //TODO: work on identifying self-contained blocks
-                //TODO: work on splits.
+            {
+            	//   ...,objectref[,word]*
+            	//   
+            	// => ...
+            	// => ...,word
+            	// => ...,word1,word2
+            	
+                // Width of the value returned by the method call.
+                String vmDescriptor = getTypeDescriptor(ch, opcode_pc);
+                int width = CodeChunk.getDescriptorWordCount(vmDescriptor);
+     
+                // Need to determine the pc of the
+            	// instruction that pushed the objectref
+            	// for the method call. Three cases depending
+            	// on the return type:
+            	// 1) void method
+            	//     pcDepth[stack + 1]
+            	// 2) returns single word
+            	//     pcDepth[stack]
+            	// 3) returns double word
+            	//     pcDepth[stack - 1]
+                
+                // Special case of zero arguments
+                // and returning an single word value.
+                // In this case most likely the code
+                // block to the objectref is not
+                // worth splitting, but it also
+                // does not affect the independence
+                // of the current stack depth.
+                // If the objectref was independent
+                // then the current stack value will
+                // be. This is looking
+                // for the case of this.getXXXFactory().
+                //
+                // 
+                // objectref is popped and single word
+                // value pushed by method call, so
+                // stackDelta must be zero.
+                if (stackDelta == 0 && width == 1)
+                {
+                	break;
+                }
+                
+                int stackDepthForObjectref = stack + (1 - width);
+                
+                // Look for an starting point that is independent
+                // starting at the objectref and working backwards
+                // in the code by looking for program counters
+                // that pushed an independent value.
+                int selfContainedBlockStart = -1;
+                for (int sd = stackDepthForObjectref; sd >= 0; sd--)
+                {
+                	int pcStart = pcByDepth[sd];
+                	
+                	// not a independent value
+                	if (pcStart == -1)
+                		continue;
+                	
+                	// found a suitable block if
+                	if ((pc - pcStart) >= optimalMinLength)
+                	{
+                		selfContainedBlockStart = pcStart;
+                		break;
+                	}
+                }
+            	
+            	// Did we find an independent starting pc
+            	if (selfContainedBlockStart != -1)
+            	{     
+            		// TODO: actual extract & split
+             	    return -1;
+            	}
+            	pcByDepth[stack] = -1;
+            	if (width == 2)
+            		pcByDepth[stack - 1] = -1;
             	break;
-            default:
-            	// no split to handle
-            	continue;
-            }
-
+              }
+               //TODO: work on splits.
+              default:
+            	// assume the instruction is not independent
+            	// (fail-safe)
+            	pcByDepth[stack] = -1;
+                // account for opcodes pushing longs/doubles.
+                if (stackDelta == 2)
+                	pcByDepth[stack - 1] = -1;
+                break;
+            }   	
+       }
             
-            // assume single word args, single word return
-            // this arg1 arg2 arg3 invoke
-            // 
-            // Stack was 7
-            // Stack now 4
-            // stackDelta = -3
-            // pcByDepth[4] = -1?
-            // pcByDepth[4] = pc of this instruction?
-            // pcByDepth[4] = pc of original instruction (this)?
-            // 
-            //
-            Arrays.fill(pcByDepth, stack,
-            		(stack - stackDelta) + 1, -1);
-         
-        }
         return -1;
     }