Fri, 10 May 2013 13:16:44 +0200
8014329: Slim down the label stack structure in CodeGenerator
Reviewed-by: attila, jlaskey
1.1 --- a/.hgignore Wed May 08 16:48:33 2013 +0200 1.2 +++ b/.hgignore Fri May 10 13:16:44 2013 +0200 1.3 @@ -8,6 +8,7 @@ 1.4 private.properties 1.5 webrev/* 1.6 webrev.zip 1.7 +.classpath 1.8 *.class 1.9 *.clazz 1.10 *.log
2.1 --- a/src/jdk/nashorn/internal/codegen/Attr.java Wed May 08 16:48:33 2013 +0200 2.2 +++ b/src/jdk/nashorn/internal/codegen/Attr.java Fri May 10 13:16:44 2013 +0200 2.3 @@ -539,9 +539,7 @@ 2.4 } 2.5 addLocalUse(identNode.getName()); 2.6 2.7 - end(identNode); 2.8 - 2.9 - return identNode.setSymbol(lc, symbol); 2.10 + return end(identNode.setSymbol(lc, symbol)); 2.11 } 2.12 2.13 /**
3.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java Wed May 08 16:48:33 2013 +0200 3.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Fri May 10 13:16:44 2013 +0200 3.3 @@ -298,6 +298,8 @@ 3.4 } 3.5 3.6 private static void printMemoryUsage(final String phaseName, final FunctionNode functionNode) { 3.7 + LOG.info(phaseName + " finished. Doing IR size calculation..."); 3.8 + 3.9 final ObjectSizeCalculator osc = new ObjectSizeCalculator(ObjectSizeCalculator.getEffectiveMemoryLayoutSpecification()); 3.10 osc.calculateObjectSize(functionNode); 3.11 3.12 @@ -324,7 +326,7 @@ 3.13 for (final ClassHistogramElement e : list) { 3.14 final String line = String.format(" %-48s %10d bytes (%8d instances)", e.getClazz(), e.getBytes(), e.getInstances()); 3.15 LOG.info(line); 3.16 - if (e.getBytes() < totalSize / 20) { 3.17 + if (e.getBytes() < totalSize / 200) { 3.18 LOG.info(" ..."); 3.19 break; // never mind, so little memory anyway 3.20 } 3.21 @@ -619,6 +621,4 @@ 3.22 USE_INT_ARITH = Options.getBooleanProperty("nashorn.compiler.intarithmetic"); 3.23 assert !USE_INT_ARITH : "Integer arithmetic is not enabled"; 3.24 } 3.25 - 3.26 - 3.27 }
4.1 --- a/src/jdk/nashorn/internal/codegen/Label.java Wed May 08 16:48:33 2013 +0200 4.2 +++ b/src/jdk/nashorn/internal/codegen/Label.java Fri May 10 13:16:44 2013 +0200 4.3 @@ -24,8 +24,6 @@ 4.4 */ 4.5 package jdk.nashorn.internal.codegen; 4.6 4.7 -import java.util.ArrayDeque; 4.8 - 4.9 import jdk.nashorn.internal.codegen.types.Type; 4.10 import jdk.nashorn.internal.runtime.Debug; 4.11 4.12 @@ -37,11 +35,83 @@ 4.13 * see -Dnashorn.codegen.debug, --log=codegen 4.14 */ 4.15 public final class Label { 4.16 + //byte code generation evaluation type stack for consistency check 4.17 + //and correct opcode selection. one per label as a label may be a 4.18 + //join point 4.19 + static final class Stack { 4.20 + Type[] data = new Type[8]; 4.21 + int sp = 0; 4.22 + 4.23 + Stack() { 4.24 + } 4.25 + 4.26 + private Stack(final Type[] type, final int sp) { 4.27 + this(); 4.28 + this.data = new Type[type.length]; 4.29 + this.sp = sp; 4.30 + for (int i = 0; i < sp; i++) { 4.31 + data[i] = type[i]; 4.32 + } 4.33 + } 4.34 + 4.35 + boolean isEmpty() { 4.36 + return sp == 0; 4.37 + } 4.38 + 4.39 + int size() { 4.40 + return sp; 4.41 + } 4.42 + 4.43 + boolean isEquivalentTo(final Stack other) { 4.44 + if (sp != other.sp) { 4.45 + return false; 4.46 + } 4.47 + for (int i = 0; i < sp; i++) { 4.48 + if (!data[i].isEquivalentTo(other.data[i])) { 4.49 + return false; 4.50 + } 4.51 + } 4.52 + return true; 4.53 + } 4.54 + 4.55 + void clear() { 4.56 + sp = 0; 4.57 + } 4.58 + 4.59 + void push(final Type type) { 4.60 + if (data.length == sp) { 4.61 + final Type[] newData = new Type[sp * 2]; 4.62 + for (int i = 0; i < sp; i++) { 4.63 + newData[i] = data[i]; 4.64 + } 4.65 + data = newData; 4.66 + } 4.67 + data[sp++] = type; 4.68 + } 4.69 + 4.70 + Type peek() { 4.71 + return peek(0); 4.72 + } 4.73 + 4.74 + Type peek(final int n) { 4.75 + int pos = sp - 1 - n; 4.76 + return pos < 0 ? null : data[pos]; 4.77 + } 4.78 + 4.79 + Type pop() { 4.80 + return data[--sp]; 4.81 + } 4.82 + 4.83 + Stack copy() { 4.84 + return new Stack(data, sp); 4.85 + } 4.86 + } 4.87 + 4.88 /** Name of this label */ 4.89 private final String name; 4.90 4.91 /** Type stack at this label */ 4.92 - private ArrayDeque<Type> stack; 4.93 + private Label.Stack stack; 4.94 4.95 /** ASM representation of this label */ 4.96 private jdk.internal.org.objectweb.asm.Label label; 4.97 @@ -74,11 +144,11 @@ 4.98 return label; 4.99 } 4.100 4.101 - ArrayDeque<Type> getStack() { 4.102 + Label.Stack getStack() { 4.103 return stack; 4.104 } 4.105 4.106 - void setStack(final ArrayDeque<Type> stack) { 4.107 + void setStack(final Label.Stack stack) { 4.108 this.stack = stack; 4.109 } 4.110 4.111 @@ -87,4 +157,3 @@ 4.112 return name + '_' + Debug.id(this); 4.113 } 4.114 } 4.115 -
5.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java Wed May 08 16:48:33 2013 +0200 5.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Fri May 10 13:16:44 2013 +0200 5.3 @@ -67,9 +67,7 @@ 5.4 5.5 import java.io.PrintStream; 5.6 import java.lang.reflect.Array; 5.7 -import java.util.ArrayDeque; 5.8 import java.util.EnumSet; 5.9 -import java.util.Iterator; 5.10 import java.util.List; 5.11 5.12 import jdk.internal.dynalink.support.NameCodec; 5.13 @@ -115,7 +113,7 @@ 5.14 private final MethodVisitor method; 5.15 5.16 /** Current type stack for current evaluation */ 5.17 - private ArrayDeque<Type> stack; 5.18 + private Label.Stack stack; 5.19 5.20 /** Parent classEmitter representing the class of this method */ 5.21 private final ClassEmitter classEmitter; 5.22 @@ -207,7 +205,7 @@ 5.23 } 5.24 5.25 private void newStack() { 5.26 - stack = new ArrayDeque<>(); 5.27 + stack = new Label.Stack(); 5.28 } 5.29 5.30 @Override 5.31 @@ -293,11 +291,7 @@ 5.32 * @return the type at position "pos" on the stack 5.33 */ 5.34 final Type peekType(final int pos) { 5.35 - final Iterator<Type> iter = stack.iterator(); 5.36 - for (int i = 0; i < pos; i++) { 5.37 - iter.next(); 5.38 - } 5.39 - return iter.next(); 5.40 + return stack.peek(pos); 5.41 } 5.42 5.43 /** 5.44 @@ -865,7 +859,7 @@ 5.45 } 5.46 5.47 private boolean isThisSlot(final int slot) { 5.48 - if(functionNode == null) { 5.49 + if (functionNode == null) { 5.50 return slot == CompilerConstants.JAVA_THIS.slot(); 5.51 } 5.52 final int thisSlot = compilerConstant(THIS).getSlot(); 5.53 @@ -909,7 +903,6 @@ 5.54 dup(); 5.55 return this; 5.56 } 5.57 - debug("load compiler constant ", symbol); 5.58 return load(symbol); 5.59 } 5.60 5.61 @@ -1502,24 +1495,6 @@ 5.62 * 5.63 * @return true if stacks are equivalent, false otherwise 5.64 */ 5.65 - private boolean stacksEquivalent(final ArrayDeque<Type> s0, final ArrayDeque<Type> s1) { 5.66 - if (s0.size() != s1.size()) { 5.67 - debug("different stack sizes", s0, s1); 5.68 - return false; 5.69 - } 5.70 - 5.71 - final Type[] s0a = s0.toArray(new Type[s0.size()]); 5.72 - final Type[] s1a = s1.toArray(new Type[s1.size()]); 5.73 - for (int i = 0; i < s0.size(); i++) { 5.74 - if (!s0a[i].isEquivalentTo(s1a[i])) { 5.75 - debug("different stack element", s0a[i], s1a[i]); 5.76 - return false; 5.77 - } 5.78 - } 5.79 - 5.80 - return true; 5.81 - } 5.82 - 5.83 /** 5.84 * A join in control flow - helper function that makes sure all entry stacks 5.85 * discovered for the join point so far are equivalent 5.86 @@ -1539,12 +1514,12 @@ 5.87 //ATHROW sequences instead of no code being generated at all. This should now be fixed. 5.88 assert stack != null : label + " entered with no stack. deadcode that remains?"; 5.89 5.90 - final ArrayDeque<Type> labelStack = label.getStack(); 5.91 + final Label.Stack labelStack = label.getStack(); 5.92 if (labelStack == null) { 5.93 - label.setStack(stack.clone()); 5.94 + label.setStack(stack.copy()); 5.95 return; 5.96 } 5.97 - assert stacksEquivalent(stack, labelStack) : "stacks " + stack + " is not equivalent with " + labelStack + " at join point"; 5.98 + assert stack.isEquivalentTo(labelStack) : "stacks " + stack + " is not equivalent with " + labelStack + " at join point"; 5.99 } 5.100 5.101 /** 5.102 @@ -1688,11 +1663,10 @@ 5.103 * @return array of Types 5.104 */ 5.105 protected Type[] getTypesFromStack(final int count) { 5.106 - final Iterator<Type> iter = stack.iterator(); 5.107 - final Type[] types = new Type[count]; 5.108 - 5.109 + final Type[] types = new Type[count]; 5.110 + int pos = 0; 5.111 for (int i = count - 1; i >= 0; i--) { 5.112 - types[i] = iter.next(); 5.113 + types[i] = stack.peek(pos++); 5.114 } 5.115 5.116 return types; 5.117 @@ -1708,11 +1682,11 @@ 5.118 * @return function signature for stack contents 5.119 */ 5.120 private String getDynamicSignature(final Type returnType, final int argCount) { 5.121 - final Iterator<Type> iter = stack.iterator(); 5.122 final Type[] paramTypes = new Type[argCount]; 5.123 5.124 + int pos = 0; 5.125 for (int i = argCount - 1; i >= 0; i--) { 5.126 - paramTypes[i] = iter.next(); 5.127 + paramTypes[i] = stack.peek(pos++); 5.128 } 5.129 final String descriptor = Type.getMethodDescriptor(returnType, paramTypes); 5.130 for (int i = 0; i < argCount; i++) { 5.131 @@ -2138,8 +2112,8 @@ 5.132 sb.append("{"); 5.133 sb.append(stack.size()); 5.134 sb.append(":"); 5.135 - for (final Iterator<Type> iter = stack.iterator(); iter.hasNext();) { 5.136 - final Type t = iter.next(); 5.137 + for (int pos = 0; pos < stack.size(); pos++) { 5.138 + final Type t = stack.peek(pos); 5.139 5.140 if (t == Type.SCOPE) { 5.141 sb.append("scope"); 5.142 @@ -2165,7 +2139,7 @@ 5.143 sb.append(t.getDescriptor()); 5.144 } 5.145 5.146 - if (iter.hasNext()) { 5.147 + if (pos + 1 < stack.size()) { 5.148 sb.append(' '); 5.149 } 5.150 }
6.1 --- a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java Wed May 08 16:48:33 2013 +0200 6.2 +++ b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java Fri May 10 13:16:44 2013 +0200 6.3 @@ -63,6 +63,7 @@ 6.4 return sstack.pop(); 6.5 } 6.6 6.7 + @SuppressWarnings("unchecked") 6.8 @Override 6.9 public <T extends LexicalContextNode> T pop(final T node) { 6.10 T expected = node;