[Patch] Improve javap output -XDdetails:stackMaps
Denis Istomin
istomin.den at gmail.com
Mon Jan 30 10:36:40 UTC 2017
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
-------------- next part --------------
# 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
More information about the compiler-dev
mailing list