8014329: Slim down the label stack structure in CodeGenerator
authorlagergren
Fri, 10 May 2013 13:16:44 +0200
changeset 17527 6e45d9c2328c
parent 17526 3194676cb555
child 17528 0f5bedbf0e06
8014329: Slim down the label stack structure in CodeGenerator Reviewed-by: attila, jlaskey
nashorn/.hgignore
nashorn/src/jdk/nashorn/internal/codegen/Attr.java
nashorn/src/jdk/nashorn/internal/codegen/Compiler.java
nashorn/src/jdk/nashorn/internal/codegen/Label.java
nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
nashorn/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
--- a/nashorn/.hgignore	Wed May 08 16:48:33 2013 +0200
+++ b/nashorn/.hgignore	Fri May 10 13:16:44 2013 +0200
@@ -8,6 +8,7 @@
 private.properties
 webrev/*
 webrev.zip
+.classpath
 *.class
 *.clazz
 *.log
--- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Wed May 08 16:48:33 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Fri May 10 13:16:44 2013 +0200
@@ -539,9 +539,7 @@
         }
         addLocalUse(identNode.getName());
 
-        end(identNode);
-
-        return identNode.setSymbol(lc, symbol);
+        return end(identNode.setSymbol(lc, symbol));
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java	Wed May 08 16:48:33 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java	Fri May 10 13:16:44 2013 +0200
@@ -298,6 +298,8 @@
     }
 
     private static void printMemoryUsage(final String phaseName, final FunctionNode functionNode) {
+        LOG.info(phaseName + " finished. Doing IR size calculation...");
+
         final ObjectSizeCalculator osc = new ObjectSizeCalculator(ObjectSizeCalculator.getEffectiveMemoryLayoutSpecification());
         osc.calculateObjectSize(functionNode);
 
@@ -324,7 +326,7 @@
         for (final ClassHistogramElement e : list) {
             final String line = String.format("    %-48s %10d bytes (%8d instances)", e.getClazz(), e.getBytes(), e.getInstances());
             LOG.info(line);
-            if (e.getBytes() < totalSize / 20) {
+            if (e.getBytes() < totalSize / 200) {
                 LOG.info("    ...");
                 break; // never mind, so little memory anyway
             }
@@ -619,6 +621,4 @@
         USE_INT_ARITH  =  Options.getBooleanProperty("nashorn.compiler.intarithmetic");
         assert !USE_INT_ARITH : "Integer arithmetic is not enabled";
     }
-
-
 }
--- a/nashorn/src/jdk/nashorn/internal/codegen/Label.java	Wed May 08 16:48:33 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Label.java	Fri May 10 13:16:44 2013 +0200
@@ -24,8 +24,6 @@
  */
 package jdk.nashorn.internal.codegen;
 
-import java.util.ArrayDeque;
-
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.Debug;
 
@@ -37,11 +35,83 @@
  * see -Dnashorn.codegen.debug, --log=codegen
  */
 public final class Label {
+    //byte code generation evaluation type stack for consistency check
+    //and correct opcode selection. one per label as a label may be a
+    //join point
+    static final class Stack {
+        Type[] data = new Type[8];
+        int sp = 0;
+
+        Stack() {
+        }
+
+        private Stack(final Type[] type, final int sp) {
+            this();
+            this.data = new Type[type.length];
+            this.sp   = sp;
+            for (int i = 0; i < sp; i++) {
+                data[i] = type[i];
+            }
+        }
+
+        boolean isEmpty() {
+            return sp == 0;
+        }
+
+        int size() {
+            return sp;
+        }
+
+        boolean isEquivalentTo(final Stack other) {
+            if (sp != other.sp) {
+                return false;
+            }
+            for (int i = 0; i < sp; i++) {
+                if (!data[i].isEquivalentTo(other.data[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        void clear() {
+            sp = 0;
+        }
+
+        void push(final Type type) {
+            if (data.length == sp) {
+                final Type[] newData = new Type[sp * 2];
+                for (int i = 0; i < sp; i++) {
+                    newData[i] = data[i];
+                }
+                data = newData;
+            }
+            data[sp++] = type;
+        }
+
+        Type peek() {
+            return peek(0);
+        }
+
+        Type peek(final int n) {
+            int pos = sp - 1 - n;
+            return pos < 0 ? null : data[pos];
+        }
+
+        Type pop() {
+            return data[--sp];
+        }
+
+        Stack copy() {
+            return new Stack(data, sp);
+        }
+    }
+
     /** Name of this label */
     private final String name;
 
     /** Type stack at this label */
-    private ArrayDeque<Type> stack;
+    private Label.Stack stack;
 
     /** ASM representation of this label */
     private jdk.internal.org.objectweb.asm.Label label;
@@ -74,11 +144,11 @@
         return label;
     }
 
-    ArrayDeque<Type> getStack() {
+    Label.Stack getStack() {
         return stack;
     }
 
-    void setStack(final ArrayDeque<Type> stack) {
+    void setStack(final Label.Stack stack) {
         this.stack = stack;
     }
 
@@ -87,4 +157,3 @@
         return name + '_' + Debug.id(this);
     }
 }
-
--- a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Wed May 08 16:48:33 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Fri May 10 13:16:44 2013 +0200
@@ -67,9 +67,7 @@
 
 import java.io.PrintStream;
 import java.lang.reflect.Array;
-import java.util.ArrayDeque;
 import java.util.EnumSet;
-import java.util.Iterator;
 import java.util.List;
 
 import jdk.internal.dynalink.support.NameCodec;
@@ -115,7 +113,7 @@
     private final MethodVisitor method;
 
     /** Current type stack for current evaluation */
-    private ArrayDeque<Type> stack;
+    private Label.Stack stack;
 
     /** Parent classEmitter representing the class of this method */
     private final ClassEmitter classEmitter;
@@ -207,7 +205,7 @@
     }
 
     private void newStack() {
-        stack = new ArrayDeque<>();
+        stack = new Label.Stack();
     }
 
     @Override
@@ -293,11 +291,7 @@
      * @return the type at position "pos" on the stack
      */
     final Type peekType(final int pos) {
-        final Iterator<Type> iter = stack.iterator();
-        for (int i = 0; i < pos; i++) {
-            iter.next();
-        }
-        return iter.next();
+        return stack.peek(pos);
     }
 
     /**
@@ -865,7 +859,7 @@
     }
 
     private boolean isThisSlot(final int slot) {
-        if(functionNode == null) {
+        if (functionNode == null) {
             return slot == CompilerConstants.JAVA_THIS.slot();
         }
         final int thisSlot = compilerConstant(THIS).getSlot();
@@ -909,7 +903,6 @@
             dup();
             return this;
         }
-        debug("load compiler constant ", symbol);
         return load(symbol);
     }
 
@@ -1502,24 +1495,6 @@
      *
      * @return true if stacks are equivalent, false otherwise
      */
-    private boolean stacksEquivalent(final ArrayDeque<Type> s0, final ArrayDeque<Type> s1) {
-        if (s0.size() != s1.size()) {
-            debug("different stack sizes", s0, s1);
-            return false;
-        }
-
-        final Type[] s0a = s0.toArray(new Type[s0.size()]);
-        final Type[] s1a = s1.toArray(new Type[s1.size()]);
-        for (int i = 0; i < s0.size(); i++) {
-            if (!s0a[i].isEquivalentTo(s1a[i])) {
-                debug("different stack element", s0a[i], s1a[i]);
-                return false;
-            }
-        }
-
-        return true;
-    }
-
     /**
      * A join in control flow - helper function that makes sure all entry stacks
      * discovered for the join point so far are equivalent
@@ -1539,12 +1514,12 @@
         //ATHROW sequences instead of no code being generated at all. This should now be fixed.
         assert stack != null : label + " entered with no stack. deadcode that remains?";
 
-        final ArrayDeque<Type> labelStack = label.getStack();
+        final Label.Stack labelStack = label.getStack();
         if (labelStack == null) {
-            label.setStack(stack.clone());
+            label.setStack(stack.copy());
             return;
         }
-        assert stacksEquivalent(stack, labelStack) : "stacks " + stack + " is not equivalent with " + labelStack + " at join point";
+        assert stack.isEquivalentTo(labelStack) : "stacks " + stack + " is not equivalent with " + labelStack + " at join point";
     }
 
     /**
@@ -1688,11 +1663,10 @@
      * @return array of Types
      */
     protected Type[] getTypesFromStack(final int count) {
-        final Iterator<Type> iter  = stack.iterator();
-        final Type[]         types = new Type[count];
-
+        final Type[] types = new Type[count];
+        int pos = 0;
         for (int i = count - 1; i >= 0; i--) {
-            types[i] = iter.next();
+            types[i] = stack.peek(pos++);
         }
 
         return types;
@@ -1708,11 +1682,11 @@
      * @return function signature for stack contents
      */
     private String getDynamicSignature(final Type returnType, final int argCount) {
-        final Iterator<Type> iter       = stack.iterator();
         final Type[]         paramTypes = new Type[argCount];
 
+        int pos = 0;
         for (int i = argCount - 1; i >= 0; i--) {
-            paramTypes[i] = iter.next();
+            paramTypes[i] = stack.peek(pos++);
         }
         final String descriptor = Type.getMethodDescriptor(returnType, paramTypes);
         for (int i = 0; i < argCount; i++) {
@@ -2138,8 +2112,8 @@
                 sb.append("{");
                 sb.append(stack.size());
                 sb.append(":");
-                for (final Iterator<Type> iter = stack.iterator(); iter.hasNext();) {
-                    final Type t = iter.next();
+                for (int pos = 0; pos < stack.size(); pos++) {
+                    final Type t = stack.peek(pos);
 
                     if (t == Type.SCOPE) {
                         sb.append("scope");
@@ -2165,7 +2139,7 @@
                         sb.append(t.getDescriptor());
                     }
 
-                    if (iter.hasNext()) {
+                    if (pos + 1 < stack.size()) {
                         sb.append(' ');
                     }
                 }
--- a/nashorn/src/jdk/nashorn/internal/ir/BlockLexicalContext.java	Wed May 08 16:48:33 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/ir/BlockLexicalContext.java	Fri May 10 13:16:44 2013 +0200
@@ -63,6 +63,7 @@
         return sstack.pop();
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public <T extends LexicalContextNode> T pop(final T node) {
         T expected = node;