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 km...@apache.org on 2007/10/31 22:03:37 UTC
svn commit: r590827 - in
/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode:
BCMethod.java CodeChunk.java GClass.java
Author: kmarsden
Date: Wed Oct 31 14:03:35 2007
New Revision: 590827
URL: http://svn.apache.org/viewvc?rev=590827&view=rev
Log:
DERBY-766 (partial) Modify pushing a long value in generated code to avoid
using constant pool entries if the long is within the range of a short.
Then use the I2L instruction to convert the int to a long. Also if
the long is within range of an int, then create a integer constant pool
entry and I2L to avoid using two constant pool slots.
Add some clarifying comments over the code length in complete.
Add check to ensure a generated method is no split if it contains a return
instruction in the middle.
merge from trunk 378744,426825
Modified:
db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java
db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java
db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/GClass.java
Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java?rev=590827&r1=590826&r2=590827&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java Wed Oct 31 14:03:35 2007
@@ -224,11 +224,14 @@
*/
public void complete() {
+ // myCode.getPC() gives the code length since
+ // the program counter will be positioned after
+ // the last instruction. Note this value can
+ // be changed by the splitMethod call.
- int codeLength = myCode.getPC();
- if (codeLength > CODE_SPLIT_LENGTH)
+ if (myCode.getPC() > CODE_SPLIT_LENGTH)
splitMethod();
-
+
// write exceptions attribute info
writeExceptions();
@@ -491,6 +494,15 @@
}
+ /**
+ * Push an integer value. Uses the special integer opcodes
+ * for the constants -1 to 5, BIPUSH for values that fit in
+ * a byte and SIPUSH for values that fit in a short. Otherwise
+ * uses LDC with a constant pool entry.
+ *
+ * @param value Value to be pushed
+ * @param type Final type of the value.
+ */
private void push(int value, Type type) {
CodeChunk chunk = myCode;
@@ -505,23 +517,40 @@
int cpe = modClass.addConstant(value);
addInstrCPE(VMOpcode.LDC, cpe);
}
- growStack(1, type);
+ growStack(type.width(), type);
}
- public void push(long value){
- CodeChunk chunk = myCode;
-
- if (value == 0 || value == 1) {
- chunk.addInstr((short)(VMOpcode.LCONST_0+(short)value));
- }
- else {
- int cpe = modClass.addConstant(value);
- chunk.addInstrU2(VMOpcode.LDC2_W, cpe);
- }
- growStack(2, Type.LONG);
+ /**
+ * Push a long value onto the stack.
+ * For the values zero and one the LCONST_0 and
+ * LCONST_1 instructions are used.
+ * For values betwee Short.MIN_VALUE and Short.MAX_VALUE
+ * inclusive an byte/short/int value is pushed
+ * using push(int, Type) followed by an I2L instruction.
+ * This saves using a constant pool entry for such values.
+ * All other values use a constant pool entry. For values
+ * in the range of an Integer an integer constant pool
+ * entry is created to allow sharing with integer constants
+ * and to reduce constant pool slot entries.
+ */
+ public void push(long value) {
+ CodeChunk chunk = myCode;
- }
+ if (value == 0L || value == 1L) {
+ short opcode = value == 0L ? VMOpcode.LCONST_0 : VMOpcode.LCONST_1;
+ chunk.addInstr(opcode);
+ } else if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
+ // the push(int, Type) method grows the stack for us.
+ push((int) value, Type.LONG);
+ chunk.addInstr(VMOpcode.I2L);
+ return;
+ } else {
+ int cpe = modClass.addConstant(value);
+ chunk.addInstrU2(VMOpcode.LDC2_W, cpe);
+ }
+ growStack(2, Type.LONG);
+ }
public void push(float value) {
CodeChunk chunk = myCode;
Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java?rev=590827&r1=590826&r2=590827&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java Wed Oct 31 14:03:35 2007
@@ -974,6 +974,7 @@
private String getTypeDescriptor(ClassHolder ch, int pc) {
int cpi = getU2(pc);
+
// Field reference or method reference
CONSTANT_Index_info cii = (CONSTANT_Index_info) ch.getEntry(cpi);
@@ -1327,9 +1328,24 @@
// than the VM can handle. Save one for
// return instruction.
if (splitLength > BCMethod.CODE_SPLIT_LENGTH - 1) {
+ splitLength = -1;
+ }
+ else if (CodeChunk.isReturn(opcode))
+ {
+ // Don't handle a return in the middle of
+ // an instruction stream. Don't think this
+ // is generated, but be safe.
+ splitLength = -1;
+ }
+
+ // if splitLenth was set to -1 above then there
+ // is no possible split at this instruction.
+ if (splitLength == -1)
+ {
+ // no earlier split at all
if (possibleSplitLength == -1)
return -1;
-
+
// Decide if the earlier possible split is
// worth it. 100 is an arbitary number,
// a real low limit would be the number of
@@ -1510,5 +1526,26 @@
mb.maxStack = replaceChunk.findMaxStack(ch, 0, replaceChunk.getPC());
return postSplit_pc;
+ }
+
+ /**
+ * See if the opcode is a return instruction.
+ * @param opcode opcode to be checked
+ * @return true for is a return instruction, false otherwise.
+ */
+ private static boolean isReturn(short opcode)
+ {
+ switch (opcode)
+ {
+ case VMOpcode.RETURN:
+ case VMOpcode.ARETURN:
+ case VMOpcode.IRETURN:
+ case VMOpcode.FRETURN:
+ case VMOpcode.DRETURN:
+ case VMOpcode.LRETURN:
+ return true;
+ default:
+ return false;
+ }
}
}
Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/GClass.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/GClass.java?rev=590827&r1=590826&r2=590827&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/GClass.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/GClass.java Wed Oct 31 14:03:35 2007
@@ -93,7 +93,7 @@
}
}
- public final void validateType(String typeName1)
+ final void validateType(String typeName1)
{
if (SanityManager.DEBUG)
{
@@ -101,6 +101,8 @@
String typeName = typeName1.trim();
+ if ("void".equals(typeName)) return;
+
// first remove all array-ness
while (typeName.endsWith("[]")) typeName = typeName.substring(0,typeName.length()-2);
@@ -115,7 +117,6 @@
if ("int".equals(typeName)) return;
if ("long".equals(typeName)) return;
if ("short".equals(typeName)) return;
- if ("void".equals(typeName)) return;
// then see if it can be found
// REVISIT: this will fail if ASSERT is on and the