[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-compiler-dev
Subject:    [Patch] Improve javap output -XDdetails:stackMaps
From:       Denis Istomin <istomin.den () gmail ! com>
Date:       2017-01-30 10:36:40
Message-ID: CAE63tTMW69deFNk+ODK6p-wkKLub4JKQfRr4NPdyuhmYupmb6A () mail ! gmail ! com
[Download RAW message or body]

Hi,
Made patch that improves javap output with parameters "-c -XDdetails:stackMaps":
1. Add more information about frame:
  1.1. frame_type
  1.2. offset information
  1.3. overall output of frame (there are unit-test that shows overall
output of javap)
2. Refactor StackMapWriter class – move inner classes into separate
files. Some classes become public in different package. Encapsulation
of other classes achived by "package-private scope level".
3. Rewrite StackMapTableVisitor (previous StackMapBuilder)
4. Other refactorings such as "Extract Method".
5. Also kind of fix of 8034066

-- 
Denis Istomin

["patch.txt" (text/plain)]

# HG changeset patch
# User istomin
# Date 1485768592 -18000
#      Mon Jan 30 14:29:52 2017 +0500
# Branch XDdetails-stackMaps
# Node ID 2bfca6302caaefde824772dff1ac6cb2409c1174
# Parent  37c0e34e835cd9722d4d0bb77288b080c66977a6
Improve javap output -XDdetails:stackMaps

diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/InitialVerificationTypeInfo.java \
b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/InitialVerificationTypeInfo.java
 new file mode 100644
--- /dev/null
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/InitialVerificationTypeInfo.java
 @@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javap.StackMap;
+
+import com.sun.tools.classfile.StackMapTable_attribute.verification_type_info;
+
+/**
+ * Initial locals of StackFrame.
+ */
+class InitialVerificationTypeInfo extends verification_type_info {
+    public InitialVerificationTypeInfo(String text) {
+        super(-1);
+        this.text = text;
+    }
+
+    public String getText(){
+        return text;
+    }
+
+    private String text;
+}
diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMap.java \
b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMap.java new file \
                mode 100644
--- /dev/null
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMap.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javap.StackMap;
+
+import com.sun.tools.classfile.StackMapTable_attribute.verification_type_info;
+
+/**
+ * StackMap data to print.
+ */
+public class StackMap {
+    public StackMap(StackMap stackmap, Integer type, Integer offset) {
+        this.type = type;
+        this.offset = offset;
+        this.locals = stackmap.locals;
+        this.stack = stackmap.stack;
+    }
+
+    public StackMap(Integer type, Integer offset, verification_type_info[] locals, \
verification_type_info[] stack) { +        this.type = type;
+        this.offset = offset;
+        this.locals = locals;
+        this.stack = stack;
+    }
+
+    public StackMap(Integer type, Integer offset, verification_type_info[] locals) {
+        this.type = type;
+        this.offset = offset;
+        this.locals = locals;
+        this.stack = empty;
+    }
+
+    public final verification_type_info[] locals;
+    public final verification_type_info[] stack;
+    public final int offset;
+    public final int type;
+
+    private final verification_type_info[] empty = { };
+}
diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMapBuilder.java \
b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMapBuilder.java new \
                file mode 100644
--- /dev/null
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMapBuilder.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javap.StackMap;
+
+import com.sun.tools.classfile.AccessFlags;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPool;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Descriptor;
+import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
+import com.sun.tools.classfile.Method;
+import com.sun.tools.classfile.StackMapTable_attribute;
+import com.sun.tools.classfile.StackMapTable_attribute.verification_type_info;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Builds HashMap with opcode as a key and stackMap as a value.
+ */
+public class StackMapBuilder {
+
+    public StackMapBuilder(StackMapTable_attribute attr, Method method, ClassFile \
classFile) { +        this.attr = attr;
+        this.method = method;
+        this.classFile = classFile;
+    }
+
+    public Map<Integer, StackMap> buildHashMap() {
+        verification_type_info[] initialLocals = getInitialLocals();
+        if (initialLocals == null)
+            return null;
+
+        return buildHashMap(initialLocals);
+    }
+
+    private verification_type_info[] getInitialLocals() {
+        if (attr == null) {
+            return null;
+        }
+
+        Descriptor d = method.descriptor;
+        String[] args;
+        try {
+            ConstantPool cp = classFile.constant_pool;
+            String argString = d.getParameterTypes(cp);
+            args = argString.substring(1, argString.length() - 1).split("[, ]+");
+        } catch (ConstantPoolException | InvalidDescriptor e) {
+            return null;
+        }
+        boolean isStatic = method.access_flags.is(AccessFlags.ACC_STATIC);
+
+        verification_type_info[] initialLocals = new \
verification_type_info[(isStatic ? 0 : 1) + args.length]; +        if (!isStatic)
+            initialLocals[0] = new InitialVerificationTypeInfo("this");
+        for (int i = 0; i < args.length; i++) {
+            initialLocals[(isStatic ? 0 : 1) + i] =
+                    new InitialVerificationTypeInfo(args[i].replace(".", "/"));
+        }
+
+        return initialLocals;
+    }
+
+    private HashMap<Integer, StackMap> buildHashMap(verification_type_info[] \
initialLocals){ +        // using -1 as the pc for the initial frame effectively \
compensates for +        // the difference in behavior for the first stack map frame \
(where the +        // pc offset is just offset_delta) compared to subsequent frames \
(where +        // the pc offset is always offset_delta+1).
+        int pc = -1;
+        StackMap stackMap = new StackMap(-1, -1, initialLocals);
+
+        StackMapTableVisitor builder = new StackMapTableVisitor();
+
+        HashMap<Integer, StackMap> map = new HashMap<>();;
+        for (int i = 0; i < attr.entries.length; i++) {
+            stackMap = attr.entries[i].accept(builder, stackMap);
+            pc += stackMap.offset + 1;
+            map.put(pc, stackMap);
+        }
+
+        return map;
+    }
+
+    private StackMapTable_attribute attr;
+    private ClassFile classFile;
+    private Method method;
+}
diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMapStringsUtils.java \
b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMapStringsUtils.java \
                new file mode 100644
--- /dev/null
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMapStringsUtils.java
 @@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javap.StackMap;
+
+import com.sun.tools.classfile.ConstantPool;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.StackMapTable_attribute.Object_variable_info;
+import com.sun.tools.classfile.StackMapTable_attribute.Uninitialized_variable_info;
+import com.sun.tools.classfile.StackMapTable_attribute.verification_type_info;
+
+import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.ITEM_Double;
 +import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.ITEM_Float;
 +import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.ITEM_Integer;
 +import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.ITEM_Long;
 +import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.ITEM_Null;
 +import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.ITEM_Object;
 +import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.ITEM_Top;
 +import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.ITEM_Uninitialized;
 +import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.ITEM_UninitializedThis;
 +
+/**
+ * User-friendly strings.
+ */
+public final class StackMapStringsUtils {
+
+    public static final String getTypeToPrint(StackMap stackMap){
+        int type = stackMap.type;
+
+        if (type <= 63)
+            return "same_frame /* 0-63 */";
+        else if (type <= 127)
+            return "same_locals_1_stack_item_frame /* 64-127 */";
+        else if (type <= 246)
+            return "unknown frame_type " + type;
+        else if (type == 247)
+            return "same_locals_1_stack_item_frame_extended /* 247 */";
+        else if (type <= 250)
+            return "chop_frame /* 248-250 */";
+        else if (type == 251)
+            return "same_frame_extended /* 251 */";
+        else if (type <= 254)
+            return "append_frame /* 252-254 */";
+        else
+            return "full_frame /* 255 */";
+    }
+
+    public static final String getStringToPrint(verification_type_info entry, \
ConstantPool cp) { +        String res = "";
+
+        if (entry == null) {
+            res = "ERROR";
+            return res;
+        }
+
+        switch (entry.tag) {
+            case -1:
+                res = ((InitialVerificationTypeInfo) entry).getText() + " /* init \
*/"; +                break;
+
+            case ITEM_Top:
+                res = "top /* 0 */";
+                break;
+
+            case ITEM_Integer:
+                res = "int /* 1 */";
+                break;
+
+            case ITEM_Float:
+                res = "float /* 2 */";
+                break;
+
+            case ITEM_Double:
+                res = "double /* 3 */";
+                break;
+
+            case ITEM_Long:
+                res = "long /* 4 */";
+                break;
+
+            case ITEM_Null:
+                res = "null /* 5 */";
+                break;
+
+            case ITEM_UninitializedThis:
+                res = "uninit_this /* 6 */";
+                break;
+
+            case ITEM_Object:
+                try {
+                    ConstantPool.CONSTANT_Class_info class_info = \
cp.getClassInfo(((Object_variable_info) entry).cpool_index); +                    res \
= "object " + cp.getUTF8Value(class_info.name_index) + " /* 7 */"; +                } \
catch (ConstantPoolException e) { +                    res = "??";
+                }
+                break;
+
+            case ITEM_Uninitialized:
+                res = "uninit " + ((Object)((Uninitialized_variable_info) \
entry).offset).toString() + " /* 8 */"; +                break;
+        }
+
+        return res;
+    }
+}
diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMapTableVisitor.java \
b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMapTableVisitor.java \
                new file mode 100644
--- /dev/null
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMap/StackMapTableVisitor.java
 @@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javap.StackMap;
+
+import com.sun.tools.classfile.StackMapTable_attribute;
+import com.sun.tools.classfile.StackMapTable_attribute.append_frame;
+import com.sun.tools.classfile.StackMapTable_attribute.chop_frame;
+import com.sun.tools.classfile.StackMapTable_attribute.full_frame;
+import com.sun.tools.classfile.StackMapTable_attribute.same_frame;
+import com.sun.tools.classfile.StackMapTable_attribute.same_frame_extended;
+import com.sun.tools.classfile.StackMapTable_attribute.same_locals_1_stack_item_frame;
 +import com.sun.tools.classfile.StackMapTable_attribute.same_locals_1_stack_item_frame_extended;
 +import com.sun.tools.classfile.StackMapTable_attribute.verification_type_info;
+
+import java.util.Arrays;
+
+/**
+ * Generates new StackMap to display, based on previous generated StackMap.
+ */
+class StackMapTableVisitor
+        implements StackMapTable_attribute.stack_map_frame.Visitor<StackMap, \
StackMap> { +
+    public StackMap visit_same_frame(same_frame frame, StackMap prev) {
+        assert(prev != null);
+        return new StackMap(prev, frame.frame_type, frame.getOffsetDelta());
+    }
+
+    public StackMap visit_same_frame_extended(same_frame_extended frame, StackMap \
prev) { +        assert(prev != null);
+        return new StackMap(prev, frame.frame_type, frame.getOffsetDelta());
+    }
+
+    public StackMap \
visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, StackMap \
prev) { +        assert(prev != null);
+        return new StackMap(frame.frame_type, frame.getOffsetDelta(), prev.locals, \
frame.stack); +    }
+
+    public StackMap \
visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended \
frame, StackMap prev) { +        assert(prev != null);
+        return new StackMap(frame.frame_type, frame.getOffsetDelta(), prev.locals, \
frame.stack); +    }
+
+    public StackMap visit_chop_frame(chop_frame frame, StackMap prev) {
+        assert(prev != null);
+        int k = 251 - frame.frame_type;
+        verification_type_info[] new_locals = Arrays.copyOf(prev.locals, \
prev.locals.length - k); +        return new StackMap(frame.frame_type, \
frame.getOffsetDelta(), new_locals); +    }
+
+    public StackMap visit_append_frame(append_frame frame, StackMap prev) {
+        assert(prev != null);
+        verification_type_info[] new_locals = new \
verification_type_info[prev.locals.length + frame.locals.length]; +        \
System.arraycopy(prev.locals, 0, new_locals, 0, prev.locals.length); +        \
System.arraycopy(frame.locals, 0, new_locals, prev.locals.length, \
frame.locals.length); +
+        return new StackMap(frame.frame_type, frame.getOffsetDelta(), new_locals);
+    }
+
+    public StackMap visit_full_frame(full_frame frame, StackMap prev) {
+        return new StackMap(frame.frame_type, frame.getOffsetDelta(), frame.locals, \
frame.stack); +    }
+}
diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMapWriter.java \
                b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMapWriter.java
--- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMapWriter.java
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMapWriter.java
@@ -25,23 +25,20 @@
 
 package com.sun.tools.javap;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.sun.tools.classfile.AccessFlags;
 import com.sun.tools.classfile.Attribute;
 import com.sun.tools.classfile.Code_attribute;
 import com.sun.tools.classfile.ConstantPool;
-import com.sun.tools.classfile.ConstantPoolException;
-import com.sun.tools.classfile.Descriptor;
-import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
 import com.sun.tools.classfile.Instruction;
-import com.sun.tools.classfile.Method;
 import com.sun.tools.classfile.StackMapTable_attribute;
-import com.sun.tools.classfile.StackMapTable_attribute.*;
+import com.sun.tools.classfile.StackMapTable_attribute.verification_type_info;
+import com.sun.tools.javap.StackMap.StackMap;
+import com.sun.tools.javap.StackMap.StackMapBuilder;
+import com.sun.tools.javap.StackMap.StackMapStringsUtils;
 
-import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;
 +import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * Annotate instructions with stack map.
@@ -65,49 +62,17 @@
         classWriter = ClassWriter.instance(context);
     }
 
+    /**
+     * Reset mapping of Instruction offset to StakMapFrame.
+     * @param attr Code attribute to parse.
+     */
     public void reset(Code_attribute attr) {
-        setStackMap((StackMapTable_attribute) \
                attr.attributes.get(Attribute.StackMapTable));
-    }
-
-    void setStackMap(StackMapTable_attribute attr) {
-        if (attr == null) {
-            map = null;
-            return;
-        }
+        StackMapBuilder stackMapBuilder = new StackMapBuilder(
+                (StackMapTable_attribute) \
attr.attributes.get(Attribute.StackMapTable), +                \
classWriter.getMethod(), +                classWriter.getClassFile());
 
-        Method m = classWriter.getMethod();
-        Descriptor d = m.descriptor;
-        String[] args;
-        try {
-            ConstantPool cp = classWriter.getClassFile().constant_pool;
-            String argString = d.getParameterTypes(cp);
-            args = argString.substring(1, argString.length() - 1).split("[, ]+");
-        } catch (ConstantPoolException | InvalidDescriptor e) {
-            return;
-        }
-        boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC);
-
-        verification_type_info[] initialLocals = new \
                verification_type_info[(isStatic ? 0 : 1) + args.length];
-        if (!isStatic)
-            initialLocals[0] = new CustomVerificationTypeInfo("this");
-        for (int i = 0; i < args.length; i++) {
-            initialLocals[(isStatic ? 0 : 1) + i] =
-                    new CustomVerificationTypeInfo(args[i].replace(".", "/"));
-        }
-
-        map = new HashMap<>();
-        StackMapBuilder builder = new StackMapBuilder();
-
-        // using -1 as the pc for the initial frame effectively compensates for
-        // the difference in behavior for the first stack map frame (where the
-        // pc offset is just offset_delta) compared to subsequent frames (where
-        // the pc offset is always offset_delta+1).
-        int pc = -1;
-
-        map.put(pc, new StackMap(initialLocals, empty));
-
-        for (int i = 0; i < attr.entries.length; i++)
-            pc = attr.entries[i].accept(builder, pc);
+        map = stackMapBuilder.buildHashMap();
     }
 
     public void writeInitialDetails() {
@@ -123,167 +88,37 @@
             return;
 
         StackMap m = map.get(pc);
-        if (m != null) {
-            print("StackMap locals: ", m.locals);
-            print("StackMap stack: ", m.stack);
+        if (m == null) {
+            return;
         }
 
+        indent(3);
+        println("[StackMap]");
+        print("type: ", StackMapStringsUtils.getTypeToPrint(m));
+        if (m.locals != null && m.locals.length > 0)
+            print("locals: ", m.locals);
+        if (m.stack != null && m.stack.length > 0)
+            print("stack: ", m.stack);
+            print("offset_delta: " + m.offset + ", offset_total: ", pc);
+        indent(-3);
     }
 
     void print(String label, verification_type_info[] entries) {
         print(label);
-        for (int i = 0; i < entries.length; i++) {
-            print(" ");
-            print(entries[i]);
-        }
+        ConstantPool cp = classWriter.getClassFile().constant_pool;
+        String strToPrint = Arrays.stream(entries)
+                .map(x -> StackMapStringsUtils.getStringToPrint(x, cp))
+                .collect(Collectors.joining(System.lineSeparator() + "        "));
+        print(strToPrint);
         println();
     }
 
-    void print(verification_type_info entry) {
-        if (entry == null) {
-            print("ERROR");
-            return;
-        }
-
-        switch (entry.tag) {
-            case -1:
-                print(((CustomVerificationTypeInfo) entry).text);
-                break;
-
-            case ITEM_Top:
-                print("top");
-                break;
-
-            case ITEM_Integer:
-                print("int");
-                break;
-
-            case ITEM_Float:
-                print("float");
-                break;
-
-            case ITEM_Long:
-                print("long");
-                break;
-
-            case ITEM_Double:
-                print("double");
-                break;
-
-            case ITEM_Null:
-                print("null");
-                break;
-
-            case ITEM_UninitializedThis:
-                print("uninit_this");
-                break;
-
-            case ITEM_Object:
-                try {
-                    ConstantPool cp = classWriter.getClassFile().constant_pool;
-                    ConstantPool.CONSTANT_Class_info class_info = \
                cp.getClassInfo(((Object_variable_info) entry).cpool_index);
-                    print(cp.getUTF8Value(class_info.name_index));
-                } catch (ConstantPoolException e) {
-                    print("??");
-                }
-                break;
-
-            case ITEM_Uninitialized:
-                print(((Uninitialized_variable_info) entry).offset);
-                break;
-        }
-
+    void print(String label, Object entry) {
+        print(label);
+        print(entry);
+        println();
     }
 
     private Map<Integer, StackMap> map;
     private ClassWriter classWriter;
-
-    class StackMapBuilder
-            implements StackMapTable_attribute.stack_map_frame.Visitor<Integer, \
                Integer> {
-
-        public Integer visit_same_frame(same_frame frame, Integer pc) {
-            int new_pc = pc + frame.getOffsetDelta() + 1;
-            StackMap m = map.get(pc);
-            assert (m != null);
-            map.put(new_pc, m);
-            return new_pc;
-        }
-
-        public Integer \
visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, Integer \
                pc) {
-            int new_pc = pc + frame.getOffsetDelta() + 1;
-            StackMap prev = map.get(pc);
-            assert (prev != null);
-            StackMap m = new StackMap(prev.locals, frame.stack);
-            map.put(new_pc, m);
-            return new_pc;
-        }
-
-        public Integer \
visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended \
                frame, Integer pc) {
-            int new_pc = pc + frame.getOffsetDelta() + 1;
-            StackMap prev = map.get(pc);
-            assert (prev != null);
-            StackMap m = new StackMap(prev.locals, frame.stack);
-            map.put(new_pc, m);
-            return new_pc;
-        }
-
-        public Integer visit_chop_frame(chop_frame frame, Integer pc) {
-            int new_pc = pc + frame.getOffsetDelta() + 1;
-            StackMap prev = map.get(pc);
-            assert (prev != null);
-            int k = 251 - frame.frame_type;
-            verification_type_info[] new_locals = Arrays.copyOf(prev.locals, \
                prev.locals.length - k);
-            StackMap m = new StackMap(new_locals, empty);
-            map.put(new_pc, m);
-            return new_pc;
-        }
-
-        public Integer visit_same_frame_extended(same_frame_extended frame, Integer \
                pc) {
-            int new_pc = pc + frame.getOffsetDelta();
-            StackMap m = map.get(pc);
-            assert (m != null);
-            map.put(new_pc, m);
-            return new_pc;
-        }
-
-        public Integer visit_append_frame(append_frame frame, Integer pc) {
-            int new_pc = pc + frame.getOffsetDelta() + 1;
-            StackMap prev = map.get(pc);
-            assert (prev != null);
-            verification_type_info[] new_locals = new \
                verification_type_info[prev.locals.length + frame.locals.length];
-            System.arraycopy(prev.locals, 0, new_locals, 0, prev.locals.length);
-            System.arraycopy(frame.locals, 0, new_locals, prev.locals.length, \
                frame.locals.length);
-            StackMap m = new StackMap(new_locals, empty);
-            map.put(new_pc, m);
-            return new_pc;
-        }
-
-        public Integer visit_full_frame(full_frame frame, Integer pc) {
-            int new_pc = pc + frame.getOffsetDelta() + 1;
-            StackMap m = new StackMap(frame.locals, frame.stack);
-            map.put(new_pc, m);
-            return new_pc;
-        }
-
-    }
-
-    static class StackMap {
-        StackMap(verification_type_info[] locals, verification_type_info[] stack) {
-            this.locals = locals;
-            this.stack = stack;
-        }
-
-        private final verification_type_info[] locals;
-        private final verification_type_info[] stack;
-    }
-
-    static class CustomVerificationTypeInfo extends verification_type_info {
-        public CustomVerificationTypeInfo(String text) {
-            super(-1);
-            this.text = text;
-        }
-        private String text;
-    }
-
-    private final verification_type_info[] empty = { };
 }
diff --git a/test/tools/javap/T6824493.java b/test/tools/javap/T6824493.java
--- a/test/tools/javap/T6824493.java
+++ b/test/tools/javap/T6824493.java
@@ -52,8 +52,13 @@
                 "catch[0]");
 
         test("-XDdetails:stackMaps",
-                "StackMap locals:  this java/lang/String int",
-                "StackMap stack:  java/lang/Throwable");
+                "[StackMap]",
+                "type: same_frame /* 0-63 */",
+                "locals: this /* init */",
+                        "java/lang/String /* init */",
+                        "int /* 1 */",
+                "stack: object java/lang/Throwable /* 7 */",
+                "offset_delta: 12, offset_total: 67");
 
         test("-XDdetails:localVariables",
                 "start local 3 // java.util.List list",
diff --git a/test/tools/javap/stackmap/XDdetailsStackMapsTest.java \
b/test/tools/javap/stackmap/XDdetailsStackMapsTest.java new file mode 100644
--- /dev/null
+++ b/test/tools/javap/stackmap/XDdetailsStackMapsTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import toolbox.JavapTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+import java.util.List;
+
+/*
+ * @test
+ * @summary Verify format of -XDdetails:stackMaps
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.classfile
+ *      jdk.jdeps/com.sun.tools.javap
+ * @library /tools/lib
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.JavapTask toolbox.Assert
+ * @run main XDdetailsStackMapsTest
+ */
+public class XDdetailsStackMapsTest {
+
+    public class Test implements Runnable {
+
+        public void run() {
+            System.out.println("run...");
+        }
+
+        public void main(String[] args) {
+            Test tcs = new Test();
+
+            Thread t = new Thread(tcs);
+            t.start();
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                System.out.println(e.toString());
+            }
+        }
+    }
+
+    String ExpectedString =
+            "Compiled from \"XDdetailsStackMapsTest.java\"\n" +
+            "public class XDdetailsStackMapsTest$Test implements java.lang.Runnable \
{\n" + +            "  final XDdetailsStackMapsTest this$0;\n" +
+            "\n" +
+            "  public XDdetailsStackMapsTest$Test(XDdetailsStackMapsTest);\n" +
+            "    Code:\n" +
+            "       0: aload_0\n" +
+            "       1: aload_1\n" +
+            "       2: putfield      #1                  // Field \
this$0:LXDdetailsStackMapsTest;\n" + +            "       5: aload_0\n" +
+            "       6: invokespecial #2                  // Method \
java/lang/Object.\"<init>\":()V\n" + +            "       9: return\n" +
+            "\n" +
+            "  public void run();\n" +
+            "    Code:\n" +
+            "       0: getstatic     #3                  // Field \
java/lang/System.out:Ljava/io/PrintStream;\n" + +            "       3: ldc           \
#4                  // String run...\n" + +            "       5: invokevirtual #5    \
// Method java/io/PrintStream.println:(Ljava/lang/String;)V\n" + +            "       \
8: return\n" + +            "\n" +
+            "  public void main(java.lang.String[]);\n" +
+            "    Code:\n" +
+            "       0: new           #6                  // class \
XDdetailsStackMapsTest$Test\n" + +            "       3: dup\n" +
+            "       4: aload_0\n" +
+            "       5: getfield      #1                  // Field \
this$0:LXDdetailsStackMapsTest;\n" + +            "       8: invokespecial #7         \
// Method \"<init>\":(LXDdetailsStackMapsTest;)V\n" + +            "      11: \
astore_2\n" + +            "      12: new           #8                  // class \
java/lang/Thread\n" + +            "      15: dup\n" +
+            "      16: aload_2\n" +
+            "      17: invokespecial #9                  // Method \
java/lang/Thread.\"<init>\":(Ljava/lang/Runnable;)V\n" + +            "      20: \
astore_3\n" + +            "      21: aload_3\n" +
+            "      22: invokevirtual #10                 // Method \
java/lang/Thread.start:()V\n" + +            "      25: ldc2_w        #11             \
// long 2000l\n" + +            "      28: invokestatic  #13                 // \
Method java/lang/Thread.sleep:(J)V\n" + +            "      31: goto          47\n" +
+            "          [StackMap]\n" +
+            "          type: full_frame /* 255 */\n" +
+            "          locals: object XDdetailsStackMapsTest$Test /* 7 */\n" +
+            "                  object [Ljava/lang/String; /* 7 */\n" +
+            "                  object XDdetailsStackMapsTest$Test /* 7 */\n" +
+            "                  object java/lang/Thread /* 7 */\n" +
+            "          stack: object java/lang/InterruptedException /* 7 */\n" +
+            "          offset_delta: 34, offset_total: 34\n" +
+            "      34: astore        4\n" +
+            "      36: getstatic     #3                  // Field \
java/lang/System.out:Ljava/io/PrintStream;\n" + +            "      39: aload         \
4\n" + +            "      41: invokevirtual #15                 // Method \
java/lang/InterruptedException.toString:()Ljava/lang/String;\n" + +            "      \
44: invokevirtual #5                  // Method \
java/io/PrintStream.println:(Ljava/lang/String;)V\n" + +            "          \
[StackMap]\n" + +            "          type: same_frame /* 0-63 */\n" +
+            "          locals: object XDdetailsStackMapsTest$Test /* 7 */\n" +
+            "                  object [Ljava/lang/String; /* 7 */\n" +
+            "                  object XDdetailsStackMapsTest$Test /* 7 */\n" +
+            "                  object java/lang/Thread /* 7 */\n" +
+            "          stack: object java/lang/InterruptedException /* 7 */\n" +
+            "          offset_delta: 12, offset_total: 47\n" +
+            "      47: return\n" +
+            "    Exception table:\n" +
+            "       from    to  target type\n" +
+            "          25    31    34   Class java/lang/InterruptedException\n" +
+            "}\n";
+
+    public static void main(String... args) {
+        new XDdetailsStackMapsTest().run();
+    }
+
+    void run() {
+        ToolBox tb = new ToolBox();
+
+        List<String> res = new JavapTask(tb)
+                .options("-c", "-XDdetails:stackMaps")
+                .classes("XDdetailsStackMapsTest.Test")
+                .run()
+                .getOutputLines(Task.OutputKind.DIRECT);
+        List<String> expectedList = tb.split(ExpectedString, "\n");
+
+        tb.checkEqual(expectedList, res);
+    }
+}
\ No newline at end of file



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic