Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/asm/Instruction.java
38918 views
/*1* Copyright (c) 1994, 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 sun.tools.asm;2627import sun.tools.java.*;28import java.util.Enumeration;29import java.io.IOException;30import java.io.DataOutputStream;3132/**33* An Java instruction34*35* WARNING: The contents of this source file are not part of any36* supported API. Code that depends on them does so at its own risk:37* they are subject to change or removal without notice.38*/39public40class Instruction implements Constants {41long where;42int pc;43int opc;44Object value;45Instruction next;46//JCOV47boolean flagCondInverted; /* if true, the condition is reversed48relatively of source code */49boolean flagNoCovered = false; /* if true, the command will50ignored for coverage */515253/**54* Constructor55*/56public Instruction(long where, int opc, Object value, boolean flagCondInverted) {57this.where = where;58this.opc = opc;59this.value = value;60this.flagCondInverted = flagCondInverted;61}6263/**64* Constructor65*/66public Instruction(boolean flagNoCovered, long where, int opc, Object value) {67this.where = where;68this.opc = opc;69this.value = value;70this.flagNoCovered = flagNoCovered;71}7273/**74* Constructor75*/76public Instruction(long where, int opc, boolean flagNoCovered) {77this.where = where;78this.opc = opc;79this.flagNoCovered = flagNoCovered;80}81//end JCOV8283/**84* Constructor85*/86public Instruction(long where, int opc, Object value) {87this.where = where;88this.opc = opc;89this.value = value;90}9192/**93* When deciding between a lookupswitch and a tableswitch, this94* value is used in determining how much size increase is95* acceptable.96*/97public static final double SWITCHRATIO;9899static {100// Set SWITCHRATIO from the property javac.switchratio101// if it exists and is reasonable. Otherwise, set102// SWITCHRATIO to 1.5, meaning that we will accept a 1.5x103// blowup (for the instruction) to use a tableswitch instead104// of a lookupswitch.105double ratio = 1.5;106String valStr = System.getProperty("javac.switchratio");107if (valStr != null) {108try {109double temp = Double.valueOf(valStr).doubleValue();110if (!(Double.isNaN(temp) || temp < 0.0)) {111ratio = temp;112}113} catch (NumberFormatException ee) {}114}115SWITCHRATIO = ratio;116}117118/**119* Accessor120*/121public int getOpcode() {122return pc;123}124125public Object getValue() {126return value;127}128129public void setValue(Object value) {130this.value = value;131}132133134/**135* Optimize136*/137void optimize(Environment env) {138switch (opc) {139case opc_istore: case opc_lstore: case opc_fstore:140case opc_dstore: case opc_astore:141// Don't keep the LocalVariable info around, unless we142// are actually going to generate a local variable table.143if ((value instanceof LocalVariable) && !env.debug_vars()) {144value = new Integer(((LocalVariable)value).slot);145}146break;147148case opc_goto: {149Label lbl = (Label)value;150value = lbl = lbl.getDestination();151if (lbl == next) {152// goto to the next instruction, obsolete153opc = opc_dead;154break;155}156157// We optimize158//159// goto Tag160// ...161// Tag:162// return163//164// except when we're generating debuggable code. When165// we're generating debuggable code, we leave it alone,166// in order to provide better stepping behavior. Consider167// a method the end of which looks like this:168//169// ...170// break;171// } // end of loop172// } // end of method173//174// If we optimize the goto away, we'll be left with a175// single instruction (return) and the need to ascribe that176// instruction to two source lines (the break statement and177// the method's right curly). Can't get there from here.178// Depending on which line-number ascription we choose, the179// stepping user will step directly from the break statement180// back into the caller of the method (case 1) or from the181// statement that precedes the break statement to the method's182// right curly (case 2). Similarly, he'll be able to set a183// breakpoint on the break statement (case 1) or the method's184// right curly (case 2), but not on both. Neither case 1 nor185// case 2 is desirable. .We want him to see both the break186// statement and the method's right curly when stepping,187// and we want him to be able to set a breakpoint on either or188// both. So we suppress the optimization when generating189// debuggable code.190// (Above notes from brucek@eng in JDK1.0.2, copied here191// by kelly.ohair@eng for JDK1.1)192//193// With the changes to allow -O and -g at the same time,194// I've changed the condition to be whether optimization is195// on instead of the debugging flag being off.196// - david.stoutamire@eng for 1.2197198if (lbl.next != null && env.opt()) {199switch (lbl.next.opc) {200case opc_return: case opc_ireturn: case opc_lreturn:201case opc_freturn: case opc_dreturn: case opc_areturn:202// goto to return203opc = lbl.next.opc;204value = lbl.next.value;205break;206}207}208break;209}210211case opc_ifeq: case opc_ifne: case opc_ifgt:212case opc_ifge: case opc_iflt: case opc_ifle:213case opc_ifnull: case opc_ifnonnull:214value = ((Label)value).getDestination();215if (value == next) {216// branch to next instruction, obsolete217opc = opc_pop;218break;219}220if ((next.opc == opc_goto) && (value == next.next)) {221// Conditional branch over goto, invert222// Note that you can't invert all conditions, condition223// results for float/double compares are not invertable.224switch (opc) {225case opc_ifeq: opc = opc_ifne; break;226case opc_ifne: opc = opc_ifeq; break;227case opc_iflt: opc = opc_ifge; break;228case opc_ifle: opc = opc_ifgt; break;229case opc_ifgt: opc = opc_ifle; break;230case opc_ifge: opc = opc_iflt; break;231case opc_ifnull: opc = opc_ifnonnull; break;232case opc_ifnonnull: opc = opc_ifnull; break;233}234//JCOV235flagCondInverted = !flagCondInverted;236//end JCOV237value = next.value;238next.opc = opc_dead;239}240break;241242case opc_if_acmpeq: case opc_if_acmpne:243case opc_if_icmpeq: case opc_if_icmpne:244case opc_if_icmpgt: case opc_if_icmpge:245case opc_if_icmplt: case opc_if_icmple:246value = ((Label)value).getDestination();247if (value == next) {248// branch to next instruction, obsolete249opc = opc_pop2;250break;251}252if ((next.opc == opc_goto) && (value == next.next)) {253// Conditional branch over goto, invert254switch (opc) {255case opc_if_acmpeq: opc = opc_if_acmpne; break;256case opc_if_acmpne: opc = opc_if_acmpeq; break;257case opc_if_icmpeq: opc = opc_if_icmpne; break;258case opc_if_icmpne: opc = opc_if_icmpeq; break;259case opc_if_icmpgt: opc = opc_if_icmple; break;260case opc_if_icmpge: opc = opc_if_icmplt; break;261case opc_if_icmplt: opc = opc_if_icmpge; break;262case opc_if_icmple: opc = opc_if_icmpgt; break;263}264//JCOV265flagCondInverted = !flagCondInverted;266//end JCOV267value = next.value;268next.opc = opc_dead;269}270break;271272case opc_tableswitch:273case opc_lookupswitch: {274SwitchData sw = (SwitchData)value;275sw.defaultLabel = sw.defaultLabel.getDestination();276for (Enumeration<Integer> e = sw.tab.keys() ; e.hasMoreElements() ; ) {277Integer k = e.nextElement();278Label lbl = sw.tab.get(k);279sw.tab.put(k, lbl.getDestination());280}281282// Compute the approximate sizes of a tableswitch and a283// lookupswitch. Decide which one we want to generate.284285long range = (long)sw.maxValue - (long)sw.minValue + 1;286long entries = sw.tab.size();287288long tableSize = 4 + range;289long lookupSize = 3 + 2 * entries;290291if (tableSize <= lookupSize * SWITCHRATIO) {292opc = opc_tableswitch;293} else {294opc = opc_lookupswitch;295}296break;297}298299}300}301302/**303* Collect constants into the constant table304*/305void collect(ConstantPool tab) {306switch (opc) {307case opc_istore: case opc_lstore: case opc_fstore:308case opc_dstore: case opc_astore:309if (value instanceof LocalVariable) {310MemberDefinition field = ((LocalVariable)value).field;311tab.put(field.getName().toString());312tab.put(field.getType().getTypeSignature());313}314return;315316case opc_new: case opc_putfield:317case opc_putstatic: case opc_getfield:318case opc_getstatic: case opc_invokevirtual:319case opc_invokespecial: case opc_invokestatic:320case opc_invokeinterface: case opc_instanceof:321case opc_checkcast:322tab.put(value);323return;324325case opc_anewarray:326tab.put(value);327return;328329case opc_multianewarray:330tab.put(((ArrayData)value).type);331return;332333case opc_ldc:334case opc_ldc_w:335if (value instanceof Integer) {336int v = ((Integer)value).intValue();337if ((v >= -1) && (v <= 5)) {338opc = opc_iconst_0 + v;339return;340} else if ((v >= -(1 << 7)) && (v < (1 << 7))) {341opc = opc_bipush;342return;343} else if ((v >= -(1 << 15)) && (v < (1 << 15))) {344opc = opc_sipush;345return;346}347} else if (value instanceof Float) {348float v = ((Float)value).floatValue();349if (v == 0) {350if (Float.floatToIntBits(v) == 0) {351opc = opc_fconst_0;352return;353}354} else if (v == 1) {355opc = opc_fconst_1;356return;357} else if (v == 2) {358opc = opc_fconst_2;359return;360}361}362tab.put(value);363return;364365case opc_ldc2_w:366if (value instanceof Long) {367long v = ((Long)value).longValue();368if (v == 0) {369opc = opc_lconst_0;370return;371} else if (v == 1) {372opc = opc_lconst_1;373return;374}375} else if (value instanceof Double) {376double v = ((Double)value).doubleValue();377if (v == 0) {378if (Double.doubleToLongBits(v) == 0) {379opc = opc_dconst_0;380return;381}382} else if (v == 1) {383opc = opc_dconst_1;384return;385}386}387tab.put(value);388return;389390case opc_try:391for (Enumeration<CatchData> e = ((TryData)value).catches.elements() ; e.hasMoreElements() ;) {392CatchData cd = e.nextElement();393if (cd.getType() != null) {394tab.put(cd.getType());395}396}397return;398399case opc_nop:400if ((value != null) && (value instanceof ClassDeclaration))401tab.put(value);402return;403}404}405406/**407* Balance the stack408*/409int balance() {410switch (opc) {411case opc_dead: case opc_label: case opc_iinc:412case opc_arraylength: case opc_laload: case opc_daload:413case opc_nop: case opc_ineg: case opc_fneg:414case opc_lneg: case opc_dneg: case opc_i2f:415case opc_f2i: case opc_l2d: case opc_d2l:416case opc_i2b: case opc_i2c: case opc_i2s:417case opc_jsr: case opc_goto: case opc_jsr_w:418case opc_goto_w: case opc_return: case opc_ret:419case opc_instanceof: case opc_checkcast: case opc_newarray:420case opc_anewarray: case opc_try: case opc_swap:421return 0;422423case opc_ldc: case opc_ldc_w: case opc_bipush:424case opc_sipush: case opc_aconst_null: case opc_iconst_m1:425case opc_iconst_0: case opc_iconst_1: case opc_iconst_2:426case opc_iconst_3: case opc_iconst_4: case opc_iconst_5:427case opc_fconst_0: case opc_fconst_1: case opc_fconst_2:428case opc_iload: case opc_fload: case opc_aload:429case opc_dup: case opc_dup_x1: case opc_dup_x2:430case opc_i2l: case opc_i2d: case opc_f2l:431case opc_f2d: case opc_new:432return 1;433434case opc_lload: case opc_dload: case opc_dup2:435case opc_dup2_x1: case opc_dup2_x2: case opc_ldc2_w:436case opc_lconst_0: case opc_lconst_1: case opc_dconst_0:437case opc_dconst_1:438return 2;439440case opc_istore: case opc_fstore: case opc_astore:441case opc_iaload: case opc_faload: case opc_aaload:442case opc_baload: case opc_caload: case opc_saload:443case opc_pop: case opc_iadd: case opc_fadd:444case opc_isub: case opc_fsub: case opc_imul:445case opc_fmul: case opc_idiv: case opc_fdiv:446case opc_irem: case opc_frem: case opc_ishl:447case opc_ishr: case opc_iushr: case opc_lshl:448case opc_lshr: case opc_lushr: case opc_iand:449case opc_ior: case opc_ixor: case opc_l2i:450case opc_l2f: case opc_d2i: case opc_d2f:451case opc_ifeq: case opc_ifne: case opc_iflt:452case opc_ifle: case opc_ifgt: case opc_ifge:453case opc_ifnull: case opc_ifnonnull: case opc_fcmpl:454case opc_fcmpg: case opc_ireturn: case opc_freturn:455case opc_areturn: case opc_tableswitch: case opc_lookupswitch:456case opc_athrow: case opc_monitorenter: case opc_monitorexit:457return -1;458459case opc_lstore: case opc_dstore: case opc_pop2:460case opc_ladd: case opc_dadd: case opc_lsub:461case opc_dsub: case opc_lmul: case opc_dmul:462case opc_ldiv: case opc_ddiv: case opc_lrem:463case opc_drem: case opc_land: case opc_lor:464case opc_lxor: case opc_if_acmpeq: case opc_if_acmpne:465case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmplt:466case opc_if_icmple: case opc_if_icmpgt: case opc_if_icmpge:467case opc_lreturn: case opc_dreturn:468return -2;469470case opc_iastore: case opc_fastore: case opc_aastore:471case opc_bastore: case opc_castore: case opc_sastore:472case opc_lcmp: case opc_dcmpl: case opc_dcmpg:473return -3;474475case opc_lastore: case opc_dastore:476return -4;477478case opc_multianewarray:479return 1 - ((ArrayData)value).nargs;480481case opc_getfield:482return ((MemberDefinition)value).getType().stackSize() - 1;483484case opc_putfield:485return -1 - ((MemberDefinition)value).getType().stackSize();486487case opc_getstatic:488return ((MemberDefinition)value).getType().stackSize();489490case opc_putstatic:491return -((MemberDefinition)value).getType().stackSize();492493case opc_invokevirtual:494case opc_invokespecial:495case opc_invokeinterface:496return ((MemberDefinition)value).getType().getReturnType().stackSize() -497(((MemberDefinition)value).getType().stackSize() + 1);498499case opc_invokestatic:500return ((MemberDefinition)value).getType().getReturnType().stackSize() -501(((MemberDefinition)value).getType().stackSize());502}503throw new CompilerError("invalid opcode: " + toString());504}505506/**507* Return the size of the instruction508*/509int size(ConstantPool tab) {510switch (opc) {511case opc_try: case opc_label: case opc_dead:512return 0;513514case opc_bipush: case opc_newarray:515return 2;516517case opc_sipush: case opc_goto: case opc_jsr:518case opc_ifeq: case opc_ifne: case opc_ifgt:519case opc_ifge: case opc_iflt: case opc_ifle:520case opc_ifnull: case opc_ifnonnull: case opc_if_acmpeq:521case opc_if_acmpne: case opc_if_icmpeq: case opc_if_icmpne:522case opc_if_icmpgt: case opc_if_icmpge: case opc_if_icmplt:523case opc_if_icmple:524return 3;525526case opc_ldc:527case opc_ldc_w:528if (tab.index(value) < 256) {529opc = opc_ldc;530return 2;531} else {532opc = opc_ldc_w;533return 3;534}535536case opc_iload: case opc_lload: case opc_fload:537case opc_dload: case opc_aload: {538int v = ((Number)value).intValue();539if (v < 4) {540if (v < 0) {541throw new CompilerError("invalid slot: " + toString()542+ "\nThis error possibly resulted from poorly constructed class paths.");543}544opc = opc_iload_0 + (opc - opc_iload) * 4 + v;545return 1;546} else if (v <= 255) {547return 2;548} else {549opc += 256; // indicate wide variant550return 4;551}552}553554case opc_iinc: {555int register = ((int[])value)[0];556int increment = ((int[])value)[1];557if (register < 0) {558throw new CompilerError("invalid slot: " + toString());559}560if (register <= 255 && (((byte)increment) == increment)) {561return 3;562} else {563opc += 256; // indicate wide variant564return 6;565}566}567568case opc_istore: case opc_lstore: case opc_fstore:569case opc_dstore: case opc_astore: {570int v = (value instanceof Number) ?571((Number)value).intValue() : ((LocalVariable)value).slot;572if (v < 4) {573if (v < 0) {574throw new CompilerError("invalid slot: " + toString());575}576opc = opc_istore_0 + (opc - opc_istore) * 4 + v;577return 1;578} else if (v <= 255) {579return 2;580} else {581opc += 256; // indicate wide variant582return 4;583}584}585586case opc_ret: {587int v = ((Number)value).intValue();588if (v <= 255) {589if (v < 0) {590throw new CompilerError("invalid slot: " + toString());591}592return 2;593} else {594opc += 256; // indicate wide variant595return 4;596}597}598599case opc_ldc2_w: case opc_new:600case opc_putstatic: case opc_getstatic:601case opc_putfield: case opc_getfield:602case opc_invokevirtual: case opc_invokespecial:603case opc_invokestatic: case opc_instanceof:604case opc_checkcast: case opc_anewarray:605return 3;606607case opc_multianewarray:608return 4;609610case opc_invokeinterface:611case opc_goto_w:612case opc_jsr_w:613return 5;614615case opc_tableswitch: {616SwitchData sw = (SwitchData)value;617int n = 1;618for(; ((pc + n) % 4) != 0 ; n++);619return n + 16 + (sw.maxValue - sw.minValue) * 4;620}621622case opc_lookupswitch: {623SwitchData sw = (SwitchData)value;624int n = 1;625for(; ((pc + n) % 4) != 0 ; n++);626return n + 8 + sw.tab.size() * 8;627}628629case opc_nop:630if ((value != null) && !(value instanceof Integer))631return 2;632else633return 1;634}635636// most opcodes are only 1 byte long637return 1;638}639640/**641* Generate code642*/643@SuppressWarnings("fallthrough")644void write(DataOutputStream out, ConstantPool tab) throws IOException {645switch (opc) {646case opc_try: case opc_label: case opc_dead:647break;648649case opc_bipush: case opc_newarray:650case opc_iload: case opc_lload: case opc_fload:651case opc_dload: case opc_aload: case opc_ret:652out.writeByte(opc);653out.writeByte(((Number)value).intValue());654break;655656case opc_iload + 256: case opc_lload + 256:657case opc_fload + 256: case opc_dload + 256:658case opc_aload + 256: case opc_ret + 256:659out.writeByte(opc_wide);660out.writeByte(opc - 256);661out.writeShort(((Number)value).intValue());662break;663664case opc_istore: case opc_lstore: case opc_fstore:665case opc_dstore: case opc_astore:666out.writeByte(opc);667out.writeByte((value instanceof Number) ?668((Number)value).intValue() : ((LocalVariable)value).slot);669break;670671case opc_istore + 256: case opc_lstore + 256:672case opc_fstore + 256: case opc_dstore + 256:673case opc_astore + 256:674out.writeByte(opc_wide);675out.writeByte(opc - 256);676out.writeShort((value instanceof Number) ?677((Number)value).intValue() : ((LocalVariable)value).slot);678break;679680case opc_sipush:681out.writeByte(opc);682out.writeShort(((Number)value).intValue());683break;684685case opc_ldc:686out.writeByte(opc);687out.writeByte(tab.index(value));688break;689690case opc_ldc_w: case opc_ldc2_w:691case opc_new: case opc_putstatic:692case opc_getstatic: case opc_putfield:693case opc_getfield: case opc_invokevirtual:694case opc_invokespecial: case opc_invokestatic:695case opc_instanceof: case opc_checkcast:696out.writeByte(opc);697out.writeShort(tab.index(value));698break;699700case opc_iinc:701out.writeByte(opc);702out.writeByte(((int[])value)[0]); // register703out.writeByte(((int[])value)[1]); // increment704break;705706case opc_iinc + 256:707out.writeByte(opc_wide);708out.writeByte(opc - 256);709out.writeShort(((int[])value)[0]); // register710out.writeShort(((int[])value)[1]); // increment711break;712713case opc_anewarray:714out.writeByte(opc);715out.writeShort(tab.index(value));716break;717718case opc_multianewarray:719out.writeByte(opc);720out.writeShort(tab.index(((ArrayData)value).type));721out.writeByte(((ArrayData)value).nargs);722break;723724case opc_invokeinterface:725out.writeByte(opc);726out.writeShort(tab.index(value));727out.writeByte(((MemberDefinition)value).getType().stackSize() + 1);728out.writeByte(0);729break;730731case opc_goto: case opc_jsr: case opc_ifeq:732case opc_ifne: case opc_ifgt: case opc_ifge:733case opc_iflt: case opc_ifle: case opc_ifnull:734case opc_ifnonnull: case opc_if_acmpeq: case opc_if_acmpne:735case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpgt:736case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmple:737out.writeByte(opc);738out.writeShort(((Instruction)value).pc - pc);739break;740741case opc_goto_w:742case opc_jsr_w:743out.writeByte(opc);744out.writeLong(((Instruction)value).pc - pc);745break;746747case opc_tableswitch: {748SwitchData sw = (SwitchData)value;749out.writeByte(opc);750for(int n = 1 ; ((pc + n) % 4) != 0 ; n++) {751out.writeByte(0);752}753out.writeInt(sw.defaultLabel.pc - pc);754out.writeInt(sw.minValue);755out.writeInt(sw.maxValue);756for (int n = sw.minValue ; n <= sw.maxValue ; n++) {757Label lbl = sw.get(n);758int target_pc = (lbl != null) ? lbl.pc : sw.defaultLabel.pc;759out.writeInt(target_pc - pc);760}761break;762}763764case opc_lookupswitch: {765SwitchData sw = (SwitchData)value;766out.writeByte(opc);767int n = pc + 1;768for(; (n % 4) != 0 ; n++) {769out.writeByte(0);770}771out.writeInt(sw.defaultLabel.pc - pc);772out.writeInt(sw.tab.size());773for (Enumeration<Integer> e = sw.sortedKeys(); e.hasMoreElements() ; ) {774Integer v = e.nextElement();775out.writeInt(v.intValue());776out.writeInt(sw.get(v).pc - pc);777}778break;779}780781case opc_nop:782if (value != null) {783if (value instanceof Integer)784out.writeByte(((Integer)value).intValue());785else786out.writeShort(tab.index(value));787return;788}789// fall through790791default:792out.writeByte(opc);793break;794}795}796797/**798* toString799*/800public String toString() {801String prefix = (where >> WHEREOFFSETBITS) + ":\t";802switch (opc) {803case opc_try:804return prefix + "try " + ((TryData)value).getEndLabel().hashCode();805806case opc_dead:807return prefix + "dead";808809case opc_iinc: {810int register = ((int[])value)[0];811int increment = ((int[])value)[1];812return prefix + opcNames[opc] + " " + register + ", " + increment;813}814815default:816if (value != null) {817if (value instanceof Label) {818return prefix + opcNames[opc] + " " + value.toString();819} else if (value instanceof Instruction) {820return prefix + opcNames[opc] + " " + value.hashCode();821} else if (value instanceof String) {822return prefix + opcNames[opc] + " \"" + value + "\"";823} else {824return prefix + opcNames[opc] + " " + value;825}826} else {827return prefix + opcNames[opc];828}829}830}831}832833834