Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMapWriter.java
58461 views
/*1* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.javap;2627import java.util.Arrays;28import java.util.HashMap;29import java.util.Map;3031import com.sun.tools.classfile.AccessFlags;32import com.sun.tools.classfile.Attribute;33import com.sun.tools.classfile.Code_attribute;34import com.sun.tools.classfile.ConstantPool;35import com.sun.tools.classfile.ConstantPoolException;36import com.sun.tools.classfile.Descriptor;37import com.sun.tools.classfile.Descriptor.InvalidDescriptor;38import com.sun.tools.classfile.Instruction;39import com.sun.tools.classfile.Method;40import com.sun.tools.classfile.StackMapTable_attribute;41import com.sun.tools.classfile.StackMapTable_attribute.*;4243import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;4445/**46* Annotate instructions with stack map.47*48* <p><b>This is NOT part of any supported API.49* If you write code that depends on this, you do so at your own risk.50* This code and its internal interfaces are subject to change or51* deletion without notice.</b>52*/53public class StackMapWriter extends InstructionDetailWriter {54static StackMapWriter instance(Context context) {55StackMapWriter instance = context.get(StackMapWriter.class);56if (instance == null)57instance = new StackMapWriter(context);58return instance;59}6061protected StackMapWriter(Context context) {62super(context);63context.put(StackMapWriter.class, this);64classWriter = ClassWriter.instance(context);65}6667public void reset(Code_attribute attr) {68setStackMap((StackMapTable_attribute) attr.attributes.get(Attribute.StackMapTable));69}7071void setStackMap(StackMapTable_attribute attr) {72if (attr == null) {73map = null;74return;75}7677Method m = classWriter.getMethod();78Descriptor d = m.descriptor;79String[] args;80try {81ConstantPool cp = classWriter.getClassFile().constant_pool;82String argString = d.getParameterTypes(cp);83args = argString.substring(1, argString.length() - 1).split("[, ]+");84} catch (ConstantPoolException | InvalidDescriptor e) {85return;86}87boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC);8889verification_type_info[] initialLocals = new verification_type_info[(isStatic ? 0 : 1) + args.length];90if (!isStatic)91initialLocals[0] = new CustomVerificationTypeInfo("this");92for (int i = 0; i < args.length; i++) {93initialLocals[(isStatic ? 0 : 1) + i] =94new CustomVerificationTypeInfo(args[i].replace(".", "/"));95}9697map = new HashMap<>();98StackMapBuilder builder = new StackMapBuilder();99100// using -1 as the pc for the initial frame effectively compensates for101// the difference in behavior for the first stack map frame (where the102// pc offset is just offset_delta) compared to subsequent frames (where103// the pc offset is always offset_delta+1).104int pc = -1;105106map.put(pc, new StackMap(initialLocals, empty));107108for (int i = 0; i < attr.entries.length; i++)109pc = attr.entries[i].accept(builder, pc);110}111112public void writeInitialDetails() {113writeDetails(-1);114}115116public void writeDetails(Instruction instr) {117writeDetails(instr.getPC());118}119120private void writeDetails(int pc) {121if (map == null)122return;123124StackMap m = map.get(pc);125if (m != null) {126print("StackMap locals: ", m.locals);127print("StackMap stack: ", m.stack);128}129130}131132void print(String label, verification_type_info[] entries) {133print(label);134for (int i = 0; i < entries.length; i++) {135print(" ");136print(entries[i]);137}138println();139}140141void print(verification_type_info entry) {142if (entry == null) {143print("ERROR");144return;145}146147switch (entry.tag) {148case -1:149print(((CustomVerificationTypeInfo) entry).text);150break;151152case ITEM_Top:153print("top");154break;155156case ITEM_Integer:157print("int");158break;159160case ITEM_Float:161print("float");162break;163164case ITEM_Long:165print("long");166break;167168case ITEM_Double:169print("double");170break;171172case ITEM_Null:173print("null");174break;175176case ITEM_UninitializedThis:177print("uninit_this");178break;179180case ITEM_Object:181try {182ConstantPool cp = classWriter.getClassFile().constant_pool;183ConstantPool.CONSTANT_Class_info class_info = cp.getClassInfo(((Object_variable_info) entry).cpool_index);184print(cp.getUTF8Value(class_info.name_index));185} catch (ConstantPoolException e) {186print("??");187}188break;189190case ITEM_Uninitialized:191print(((Uninitialized_variable_info) entry).offset);192break;193}194195}196197private Map<Integer, StackMap> map;198private ClassWriter classWriter;199200class StackMapBuilder201implements StackMapTable_attribute.stack_map_frame.Visitor<Integer, Integer> {202203public Integer visit_same_frame(same_frame frame, Integer pc) {204int new_pc = pc + frame.getOffsetDelta() + 1;205StackMap m = map.get(pc);206assert (m != null);207map.put(new_pc, m);208return new_pc;209}210211public Integer visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, Integer pc) {212int new_pc = pc + frame.getOffsetDelta() + 1;213StackMap prev = map.get(pc);214assert (prev != null);215StackMap m = new StackMap(prev.locals, frame.stack);216map.put(new_pc, m);217return new_pc;218}219220public Integer visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, Integer pc) {221int new_pc = pc + frame.getOffsetDelta() + 1;222StackMap prev = map.get(pc);223assert (prev != null);224StackMap m = new StackMap(prev.locals, frame.stack);225map.put(new_pc, m);226return new_pc;227}228229public Integer visit_chop_frame(chop_frame frame, Integer pc) {230int new_pc = pc + frame.getOffsetDelta() + 1;231StackMap prev = map.get(pc);232assert (prev != null);233int k = 251 - frame.frame_type;234verification_type_info[] new_locals = Arrays.copyOf(prev.locals, prev.locals.length - k);235StackMap m = new StackMap(new_locals, empty);236map.put(new_pc, m);237return new_pc;238}239240public Integer visit_same_frame_extended(same_frame_extended frame, Integer pc) {241int new_pc = pc + frame.getOffsetDelta();242StackMap m = map.get(pc);243assert (m != null);244map.put(new_pc, m);245return new_pc;246}247248public Integer visit_append_frame(append_frame frame, Integer pc) {249int new_pc = pc + frame.getOffsetDelta() + 1;250StackMap prev = map.get(pc);251assert (prev != null);252verification_type_info[] new_locals = new verification_type_info[prev.locals.length + frame.locals.length];253System.arraycopy(prev.locals, 0, new_locals, 0, prev.locals.length);254System.arraycopy(frame.locals, 0, new_locals, prev.locals.length, frame.locals.length);255StackMap m = new StackMap(new_locals, empty);256map.put(new_pc, m);257return new_pc;258}259260public Integer visit_full_frame(full_frame frame, Integer pc) {261int new_pc = pc + frame.getOffsetDelta() + 1;262StackMap m = new StackMap(frame.locals, frame.stack);263map.put(new_pc, m);264return new_pc;265}266267}268269static class StackMap {270StackMap(verification_type_info[] locals, verification_type_info[] stack) {271this.locals = locals;272this.stack = stack;273}274275private final verification_type_info[] locals;276private final verification_type_info[] stack;277}278279static class CustomVerificationTypeInfo extends verification_type_info {280public CustomVerificationTypeInfo(String text) {281super(-1);282this.text = text;283}284private String text;285}286287private final verification_type_info[] empty = { };288}289290291