Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javap/StackMapWriter.java
38899 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 e) {85return;86} catch (InvalidDescriptor e) {87return;88}89boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC);9091verification_type_info[] initialLocals = new verification_type_info[(isStatic ? 0 : 1) + args.length];92if (!isStatic)93initialLocals[0] = new CustomVerificationTypeInfo("this");94for (int i = 0; i < args.length; i++) {95initialLocals[(isStatic ? 0 : 1) + i] =96new CustomVerificationTypeInfo(args[i].replace(".", "/"));97}9899map = new HashMap<Integer, StackMap>();100StackMapBuilder builder = new StackMapBuilder();101102// using -1 as the pc for the initial frame effectively compensates for103// the difference in behavior for the first stack map frame (where the104// pc offset is just offset_delta) compared to subsequent frames (where105// the pc offset is always offset_delta+1).106int pc = -1;107108map.put(pc, new StackMap(initialLocals, empty));109110for (int i = 0; i < attr.entries.length; i++)111pc = attr.entries[i].accept(builder, pc);112}113114public void writeInitialDetails() {115writeDetails(-1);116}117118public void writeDetails(Instruction instr) {119writeDetails(instr.getPC());120}121122private void writeDetails(int pc) {123if (map == null)124return;125126StackMap m = map.get(pc);127if (m != null) {128print("StackMap locals: ", m.locals);129print("StackMap stack: ", m.stack);130}131132}133134void print(String label, verification_type_info[] entries) {135print(label);136for (int i = 0; i < entries.length; i++) {137print(" ");138print(entries[i]);139}140println();141}142143void print(verification_type_info entry) {144if (entry == null) {145print("ERROR");146return;147}148149switch (entry.tag) {150case -1:151print(((CustomVerificationTypeInfo) entry).text);152break;153154case ITEM_Top:155print("top");156break;157158case ITEM_Integer:159print("int");160break;161162case ITEM_Float:163print("float");164break;165166case ITEM_Long:167print("long");168break;169170case ITEM_Double:171print("double");172break;173174case ITEM_Null:175print("null");176break;177178case ITEM_UninitializedThis:179print("uninit_this");180break;181182case ITEM_Object:183try {184ConstantPool cp = classWriter.getClassFile().constant_pool;185ConstantPool.CONSTANT_Class_info class_info = cp.getClassInfo(((Object_variable_info) entry).cpool_index);186print(cp.getUTF8Value(class_info.name_index));187} catch (ConstantPoolException e) {188print("??");189}190break;191192case ITEM_Uninitialized:193print(((Uninitialized_variable_info) entry).offset);194break;195}196197}198199private Map<Integer, StackMap> map;200private ClassWriter classWriter;201202class StackMapBuilder203implements StackMapTable_attribute.stack_map_frame.Visitor<Integer, Integer> {204205public Integer visit_same_frame(same_frame frame, Integer pc) {206int new_pc = pc + frame.getOffsetDelta() + 1;207StackMap m = map.get(pc);208assert (m != null);209map.put(new_pc, m);210return new_pc;211}212213public Integer visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, Integer pc) {214int new_pc = pc + frame.getOffsetDelta() + 1;215StackMap prev = map.get(pc);216assert (prev != null);217StackMap m = new StackMap(prev.locals, frame.stack);218map.put(new_pc, m);219return new_pc;220}221222public Integer visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, Integer pc) {223int new_pc = pc + frame.getOffsetDelta() + 1;224StackMap prev = map.get(pc);225assert (prev != null);226StackMap m = new StackMap(prev.locals, frame.stack);227map.put(new_pc, m);228return new_pc;229}230231public Integer visit_chop_frame(chop_frame frame, Integer pc) {232int new_pc = pc + frame.getOffsetDelta() + 1;233StackMap prev = map.get(pc);234assert (prev != null);235int k = 251 - frame.frame_type;236verification_type_info[] new_locals = Arrays.copyOf(prev.locals, prev.locals.length - k);237StackMap m = new StackMap(new_locals, empty);238map.put(new_pc, m);239return new_pc;240}241242public Integer visit_same_frame_extended(same_frame_extended frame, Integer pc) {243int new_pc = pc + frame.getOffsetDelta();244StackMap m = map.get(pc);245assert (m != null);246map.put(new_pc, m);247return new_pc;248}249250public Integer visit_append_frame(append_frame frame, Integer pc) {251int new_pc = pc + frame.getOffsetDelta() + 1;252StackMap prev = map.get(pc);253assert (prev != null);254verification_type_info[] new_locals = new verification_type_info[prev.locals.length + frame.locals.length];255System.arraycopy(prev.locals, 0, new_locals, 0, prev.locals.length);256System.arraycopy(frame.locals, 0, new_locals, prev.locals.length, frame.locals.length);257StackMap m = new StackMap(new_locals, empty);258map.put(new_pc, m);259return new_pc;260}261262public Integer visit_full_frame(full_frame frame, Integer pc) {263int new_pc = pc + frame.getOffsetDelta() + 1;264StackMap m = new StackMap(frame.locals, frame.stack);265map.put(new_pc, m);266return new_pc;267}268269}270271static class StackMap {272StackMap(verification_type_info[] locals, verification_type_info[] stack) {273this.locals = locals;274this.stack = stack;275}276277private final verification_type_info[] locals;278private final verification_type_info[] stack;279}280281static class CustomVerificationTypeInfo extends verification_type_info {282public CustomVerificationTypeInfo(String text) {283super(-1);284this.text = text;285}286private String text;287}288289private final verification_type_info[] empty = { };290}291292293