blob: 0b4105a6e55862458c403c421dca705a9ec30920 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.java.util.jar.pack;
27
28/**
29 * A parsed bytecode instruction.
30 * Provides accessors to various relevant bits.
31 * @author John Rose
32 */
33class Instruction implements Constants {
34 protected byte[] bytes; // bytecodes
35 protected int pc; // location of this instruction
36 protected int bc; // opcode of this instruction
37 protected int w; // 0 if normal, 1 if a _wide prefix at pc
38 protected int length; // bytes in this instruction
39
40 protected boolean special;
41
42 protected Instruction(byte[] bytes, int pc, int bc, int w, int length) {
43 reset(bytes, pc, bc, w, length);
44 }
45 private void reset(byte[] bytes, int pc, int bc, int w, int length) {
46 this.bytes = bytes;
47 this.pc = pc;
48 this.bc = bc;
49 this.w = w;
50 this.length = length;
51 }
52
53 public int getBC() {
54 return bc;
55 }
56 public boolean isWide() {
57 return w != 0;
58 }
59 public byte[] getBytes() {
60 return bytes;
61 }
62 public int getPC() {
63 return pc;
64 }
65 public int getLength() {
66 return length;
67 }
68 public int getNextPC() {
69 return pc + length;
70 }
71
72 public Instruction next() {
73 int npc = pc + length;
74 if (npc == bytes.length)
75 return null;
76 else
77 return Instruction.at(bytes, npc, this);
78 }
79
80 public boolean isNonstandard() {
81 return isNonstandard(bc);
82 }
83
84 public void setNonstandardLength(int length) {
85 assert(isNonstandard());
86 this.length = length;
87 }
88
89
90 /** A fake instruction at this pc whose next() will be at nextpc. */
91 public Instruction forceNextPC(int nextpc) {
92 int length = nextpc - pc;
93 return new Instruction(bytes, pc, -1, -1, length);
94 }
95
96 public static Instruction at(byte[] bytes, int pc) {
97 return Instruction.at(bytes, pc, null);
98 }
99
100 public static Instruction at(byte[] bytes, int pc, Instruction reuse) {
101 int bc = getByte(bytes, pc);
102 int prefix = -1;
103 int w = 0;
104 int length = BC_LENGTH[w][bc];
105 if (length == 0) {
106 // Hard cases:
107 switch (bc) {
108 case _wide:
109 bc = getByte(bytes, pc+1);
110 w = 1;
111 length = BC_LENGTH[w][bc];
112 if (length == 0) {
113 // unknown instruction; treat as one byte
114 length = 1;
115 }
116 break;
117 case _tableswitch:
118 return new TableSwitch(bytes, pc);
119 case _lookupswitch:
120 return new LookupSwitch(bytes, pc);
121 default:
122 // unknown instruction; treat as one byte
123 length = 1;
124 break;
125 }
126 }
127 assert(length > 0);
128 assert(pc+length <= bytes.length);
129 // Speed hack: Instruction.next reuses self if possible.
130 if (reuse != null && !reuse.special) {
131 reuse.reset(bytes, pc, bc, w, length);
132 return reuse;
133 }
134 return new Instruction(bytes, pc, bc, w, length);
135 }
136
137 // Return the constant pool reference type, or 0 if none.
138 public byte getCPTag() {
139 return BC_TAG[w][bc];
140 }
141
142 // Return the constant pool index, or -1 if none.
143 public int getCPIndex() {
144 int indexLoc = BC_INDEX[w][bc];
145 if (indexLoc == 0) return -1;
146 assert(w == 0);
147 if (length == 2)
148 return getByte(bytes, pc+indexLoc); // _ldc opcode only
149 else
150 return getShort(bytes, pc+indexLoc);
151 }
152
153 public void setCPIndex(int cpi) {
154 int indexLoc = BC_INDEX[w][bc];
155 assert(indexLoc != 0);
156 if (length == 2)
157 setByte(bytes, pc+indexLoc, cpi); // _ldc opcode only
158 else
159 setShort(bytes, pc+indexLoc, cpi);
160 assert(getCPIndex() == cpi);
161 }
162
163 public ConstantPool.Entry getCPRef(ConstantPool.Entry[] cpMap) {
164 int index = getCPIndex();
165 return (index < 0) ? null : cpMap[index];
166 }
167
168 // Return the slot of the affected local, or -1 if none.
169 public int getLocalSlot() {
170 int slotLoc = BC_SLOT[w][bc];
171 if (slotLoc == 0) return -1;
172 if (w == 0)
173 return getByte(bytes, pc+slotLoc);
174 else
175 return getShort(bytes, pc+slotLoc);
176 }
177
178 // Return the target of the branch, or -1 if none.
179 public int getBranchLabel() {
180 int branchLoc = BC_BRANCH[w][bc];
181 if (branchLoc == 0) return -1;
182 assert(w == 0);
183 assert(length == 3 || length == 5);
184 int offset;
185 if (length == 3)
186 offset = (short)getShort(bytes, pc+branchLoc);
187 else
188 offset = getInt(bytes, pc+branchLoc);
189 assert(offset+pc >= 0);
190 assert(offset+pc <= bytes.length);
191 return offset+pc;
192 }
193
194 public void setBranchLabel(int targetPC) {
195 int branchLoc = BC_BRANCH[w][bc];
196 assert(branchLoc != 0);
197 if (length == 3)
198 setShort(bytes, pc+branchLoc, targetPC-pc);
199 else
200 setInt(bytes, pc+branchLoc, targetPC-pc);
201 assert(targetPC == getBranchLabel());
202 }
203
204 // Return the trailing constant in the instruction (as a signed value).
205 // Return 0 if there is none.
206 public int getConstant() {
207 int conLoc = BC_CON[w][bc];
208 if (conLoc == 0) return 0;
209 switch (length - conLoc) {
210 case 1: return (byte) getByte(bytes, pc+conLoc);
211 case 2: return (short) getShort(bytes, pc+conLoc);
212 }
213 assert(false);
214 return 0;
215 }
216
217 public void setConstant(int con) {
218 int conLoc = BC_CON[w][bc];
219 assert(conLoc != 0);
220 switch (length - conLoc) {
221 case 1: setByte(bytes, pc+conLoc, con); break;
222 case 2: setShort(bytes, pc+conLoc, con); break;
223 }
224 assert(con == getConstant());
225 }
226
227 public abstract static class Switch extends Instruction {
228 // Each case is a (value, label) pair, indexed 0 <= n < caseCount
229 public abstract int getCaseCount();
230 public abstract int getCaseValue(int n);
231 public abstract int getCaseLabel(int n);
232 public abstract void setCaseCount(int caseCount);
233 public abstract void setCaseValue(int n, int value);
234 public abstract void setCaseLabel(int n, int targetPC);
235 protected abstract int getLength(int caseCount);
236
237 public int getDefaultLabel() { return intAt(0)+pc; }
238 public void setDefaultLabel(int targetPC) { setIntAt(0, targetPC-pc); }
239
240 protected int apc; // aligned pc (table base)
241 protected int intAt(int n) { return getInt(bytes, apc + n*4); }
242 protected void setIntAt(int n, int x) { setInt(bytes, apc + n*4, x); }
243 protected Switch(byte[] bytes, int pc, int bc) {
244 super(bytes, pc, bc, /*w*/0, /*length*/0);
245 this.apc = alignPC(pc+1);
246 this.special = true;
247 length = getLength(getCaseCount());
248 }
249 public int getAlignedPC() { return apc; }
250 public String toString() {
251 String s = super.toString();
252 s += " Default:"+labstr(getDefaultLabel());
253 int caseCount = getCaseCount();
254 for (int i = 0; i < caseCount; i++) {
255 s += "\n\tCase "+getCaseValue(i)+":"+labstr(getCaseLabel(i));
256 }
257 return s;
258 }
259 public static int alignPC(int apc) {
260 while (apc % 4 != 0) ++apc;
261 return apc;
262 }
263 }
264
265 public static class TableSwitch extends Switch {
266 // apc: (df, lo, hi, (hi-lo+1)*(label))
267 public int getLowCase() { return intAt(1); }
268 public int getHighCase() { return intAt(2); }
269 public int getCaseCount() { return intAt(2)-intAt(1)+1; }
270 public int getCaseValue(int n) { return getLowCase()+n; }
271 public int getCaseLabel(int n) { return intAt(3+n)+pc; }
272
273 public void setLowCase(int val) { setIntAt(1, val); }
274 public void setHighCase(int val) { setIntAt(2, val); }
275 public void setCaseLabel(int n, int tpc) { setIntAt(3+n, tpc-pc); }
276 public void setCaseCount(int caseCount) {
277 setHighCase(getLowCase() + caseCount - 1);
278 length = getLength(caseCount);
279 }
280 public void setCaseValue(int n, int val) {
281 if (n != 0) throw new UnsupportedOperationException();
282 int caseCount = getCaseCount();
283 setLowCase(val);
284 setCaseCount(caseCount); // keep invariant
285 }
286
287 TableSwitch(byte[] bytes, int pc) {
288 super(bytes, pc, _tableswitch);
289 }
290 protected int getLength(int caseCount) {
291 return (apc-pc) + (3 + caseCount) * 4;
292 }
293 }
294
295 public static class LookupSwitch extends Switch {
296 // apc: (df, nc, nc*(case, label))
297 public int getCaseCount() { return intAt(1); }
298 public int getCaseValue(int n) { return intAt(2+n*2+0); }
299 public int getCaseLabel(int n) { return intAt(2+n*2+1)+pc; }
300
301 public void setCaseCount(int caseCount) {
302 setIntAt(1, caseCount);
303 length = getLength(caseCount);
304 }
305 public void setCaseValue(int n, int val) { setIntAt(2+n*2+0, val); }
306 public void setCaseLabel(int n, int tpc) { setIntAt(2+n*2+1, tpc-pc); }
307
308 LookupSwitch(byte[] bytes, int pc) {
309 super(bytes, pc, _lookupswitch);
310 }
311 protected int getLength(int caseCount) {
312 return (apc-pc) + (2 + caseCount*2) * 4;
313 }
314 }
315
316 /** Two insns are equal if they have the same bytes. */
317 public boolean equals(Object o) {
318 return (o instanceof Instruction) && equals((Instruction)o);
319 }
320
321 public boolean equals(Instruction that) {
322 if (this.bc != that.bc) return false;
323 if (this.w != that.w) return false;
324 if (this.length != that.length) return false;
325 for (int i = 1; i < length; i++) {
326 if (this.bytes[this.pc+i] != that.bytes[that.pc+i])
327 return false;
328 }
329 return true;
330 }
331
332 static String labstr(int pc) {
333 if (pc >= 0 && pc < 100000)
334 return ((100000+pc)+"").substring(1);
335 return pc+"";
336 }
337 public String toString() {
338 return toString(null);
339 }
340 public String toString(ConstantPool.Entry[] cpMap) {
341 String s = labstr(pc) + ": ";
342 if (bc >= _bytecode_limit) {
343 s += Integer.toHexString(bc);
344 return s;
345 }
346 if (w == 1) s += "wide ";
347 String bcname = (bc < BC_NAME.length)? BC_NAME[bc]: null;
348 if (bcname == null) {
349 return s+"opcode#"+bc;
350 }
351 s += bcname;
352 int tag = getCPTag();
353 if (tag != 0) s += " "+ConstantPool.tagName(tag)+":";
354 int idx = getCPIndex();
355 if (idx >= 0) s += (cpMap == null) ? ""+idx : "="+cpMap[idx].stringValue();
356 int slt = getLocalSlot();
357 if (slt >= 0) s += " Local:"+slt;
358 int lab = getBranchLabel();
359 if (lab >= 0) s += " To:"+labstr(lab);
360 int con = getConstant();
361 if (con != 0) s += " Con:"+con;
362 return s;
363 }
364
365
366 //public static byte constantPoolTagFor(int bc) { return BC_TAG[0][bc]; }
367
368 /// Fetching values from byte arrays:
369
370 public int getIntAt(int off) {
371 return getInt(bytes, pc+off);
372 }
373 public int getShortAt(int off) {
374 return getShort(bytes, pc+off);
375 }
376 public int getByteAt(int off) {
377 return getByte(bytes, pc+off);
378 }
379
380
381 public static int getInt(byte[] bytes, int pc) {
382 return (getShort(bytes, pc+0) << 16) + (getShort(bytes, pc+2) << 0);
383 }
384 public static int getShort(byte[] bytes, int pc) {
385 return (getByte(bytes, pc+0) << 8) + (getByte(bytes, pc+1) << 0);
386 }
387 public static int getByte(byte[] bytes, int pc) {
388 return bytes[pc] & 0xFF;
389 }
390
391
392 public static void setInt(byte[] bytes, int pc, int x) {
393 setShort(bytes, pc+0, x >> 16);
394 setShort(bytes, pc+2, x >> 0);
395 }
396 public static void setShort(byte[] bytes, int pc, int x) {
397 setByte(bytes, pc+0, x >> 8);
398 setByte(bytes, pc+1, x >> 0);
399 }
400 public static void setByte(byte[] bytes, int pc, int x) {
401 bytes[pc] = (byte)x;
402 }
403
404 // some bytecode classifiers
405
406
407 public static boolean isNonstandard(int bc) {
408 return BC_LENGTH[0][bc] < 0;
409 }
410
411 public static int opLength(int bc) {
412 int l = BC_LENGTH[0][bc];
413 assert(l > 0);
414 return l;
415 }
416 public static int opWideLength(int bc) {
417 int l = BC_LENGTH[1][bc];
418 assert(l > 0);
419 return l;
420 }
421
422 public static boolean isLocalSlotOp(int bc) {
423 return (bc < BC_SLOT[0].length && BC_SLOT[0][bc] > 0);
424 }
425
426 public static boolean isBranchOp(int bc) {
427 return (bc < BC_BRANCH[0].length && BC_BRANCH[0][bc] > 0);
428 }
429
430 public static boolean isCPRefOp(int bc) {
431 if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return true;
432 if (bc >= _xldc_op && bc < _xldc_limit) return true;
433 return false;
434 }
435
436 public static byte getCPRefOpTag(int bc) {
437 if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return BC_TAG[0][bc];
438 if (bc >= _xldc_op && bc < _xldc_limit) return CONSTANT_Literal;
439 return CONSTANT_None;
440 }
441
442 public static boolean isFieldOp(int bc) {
443 return (bc >= _getstatic && bc <= _putfield);
444 }
445
446 public static boolean isInvokeInitOp(int bc) {
447 return (bc >= _invokeinit_op && bc < _invokeinit_limit);
448 }
449
450 public static boolean isSelfLinkerOp(int bc) {
451 return (bc >= _self_linker_op && bc < _self_linker_limit);
452 }
453
454 /// Format definitions.
455
456 static private final byte[][] BC_LENGTH = new byte[2][0x100];
457 static private final byte[][] BC_INDEX = new byte[2][0x100];
458 static private final byte[][] BC_TAG = new byte[2][0x100];
459 static private final byte[][] BC_BRANCH = new byte[2][0x100];
460 static private final byte[][] BC_SLOT = new byte[2][0x100];
461 static private final byte[][] BC_CON = new byte[2][0x100];
462 static private final String[] BC_NAME = new String[0x100]; // debug only
463 static private final String[][] BC_FORMAT = new String[2][_bytecode_limit]; // debug only
464 static {
465 for (int i = 0; i < _bytecode_limit; i++) {
466 BC_LENGTH[0][i] = -1;
467 BC_LENGTH[1][i] = -1;
468 }
469 def("b", _nop, _dconst_1);
470 def("bx", _bipush);
471 def("bxx", _sipush);
472 def("bk", _ldc); // do not pack
473 def("bkk", _ldc_w, _ldc2_w); // do not pack
474 def("blwbll", _iload, _aload);
475 def("b", _iload_0, _saload);
476 def("blwbll", _istore, _astore);
477 def("b", _istore_0, _lxor);
478 def("blxwbllxx", _iinc);
479 def("b", _i2l, _dcmpg);
480 def("boo", _ifeq, _jsr); // pack oo
481 def("blwbll", _ret);
482 def("", _tableswitch, _lookupswitch); // pack all ints, omit padding
483 def("b", _ireturn, _return);
484 def("bkf", _getstatic, _putfield); // pack kf (base=Field)
485 def("bkm", _invokevirtual, _invokestatic); // pack kn (base=Method)
486 def("bkixx", _invokeinterface); // pack ki (base=IMethod), omit xx
487 def("", _xxxunusedxxx);
488 def("bkc", _new); // pack kc
489 def("bx", _newarray);
490 def("bkc", _anewarray); // pack kc
491 def("b", _arraylength, _athrow);
492 def("bkc", _checkcast, _instanceof); // pack kc
493 def("b", _monitorenter, _monitorexit);
494 def("", _wide);
495 def("bkcx", _multianewarray); // pack kc
496 def("boo", _ifnull, _ifnonnull); // pack oo
497 def("boooo", _goto_w, _jsr_w); // pack oooo
498 for (int i = 0; i < _bytecode_limit; i++) {
499 //System.out.println(i+": l="+BC_LENGTH[0][i]+" i="+BC_INDEX[0][i]);
500 //assert(BC_LENGTH[0][i] != -1);
501 if (BC_LENGTH[0][i] == -1) {
502 assert(i == _xxxunusedxxx);
503 continue; // unknown opcode
504 }
505
506 // Have a complete mapping, to support spurious _wide prefixes.
507 if (BC_LENGTH[1][i] == -1)
508 BC_LENGTH[1][i] = (byte)(1+BC_LENGTH[0][i]);
509 }
510
511 String names =
512 "nop aconst_null iconst_m1 iconst_0 iconst_1 iconst_2 iconst_3 iconst_4 "+
513 "iconst_5 lconst_0 lconst_1 fconst_0 fconst_1 fconst_2 dconst_0 dconst_1 "+
514 "bipush sipush ldc ldc_w ldc2_w iload lload fload dload aload iload_0 "+
515 "iload_1 iload_2 iload_3 lload_0 lload_1 lload_2 lload_3 fload_0 fload_1 "+
516 "fload_2 fload_3 dload_0 dload_1 dload_2 dload_3 aload_0 aload_1 aload_2 "+
517 "aload_3 iaload laload faload daload aaload baload caload saload istore "+
518 "lstore fstore dstore astore istore_0 istore_1 istore_2 istore_3 lstore_0 "+
519 "lstore_1 lstore_2 lstore_3 fstore_0 fstore_1 fstore_2 fstore_3 dstore_0 "+
520 "dstore_1 dstore_2 dstore_3 astore_0 astore_1 astore_2 astore_3 iastore "+
521 "lastore fastore dastore aastore bastore castore sastore pop pop2 dup "+
522 "dup_x1 dup_x2 dup2 dup2_x1 dup2_x2 swap iadd ladd fadd dadd isub lsub "+
523 "fsub dsub imul lmul fmul dmul idiv ldiv fdiv ddiv irem lrem frem drem "+
524 "ineg lneg fneg dneg ishl lshl ishr lshr iushr lushr iand land ior lor "+
525 "ixor lxor iinc i2l i2f i2d l2i l2f l2d f2i f2l f2d d2i d2l d2f i2b i2c "+
526 "i2s lcmp fcmpl fcmpg dcmpl dcmpg ifeq ifne iflt ifge ifgt ifle if_icmpeq "+
527 "if_icmpne if_icmplt if_icmpge if_icmpgt if_icmple if_acmpeq if_acmpne "+
528 "goto jsr ret tableswitch lookupswitch ireturn lreturn freturn dreturn "+
529 "areturn return getstatic putstatic getfield putfield invokevirtual "+
530 "invokespecial invokestatic invokeinterface xxxunusedxxx new newarray "+
531 "anewarray arraylength athrow checkcast instanceof monitorenter "+
532 "monitorexit wide multianewarray ifnull ifnonnull goto_w jsr_w ";
533 for (int bc = 0; names.length() > 0; bc++) {
534 int sp = names.indexOf(' ');
535 BC_NAME[bc] = names.substring(0, sp);
536 names = names.substring(sp+1);
537 }
538 }
539 public static String byteName(int bc) {
540 String iname;
541 if (bc < BC_NAME.length && BC_NAME[bc] != null) {
542 iname = BC_NAME[bc];
543 } else if (isSelfLinkerOp(bc)) {
544 int idx = (bc - _self_linker_op);
545 boolean isSuper = (idx >= _self_linker_super_flag);
546 if (isSuper) idx -= _self_linker_super_flag;
547 boolean isAload = (idx >= _self_linker_aload_flag);
548 if (isAload) idx -= _self_linker_aload_flag;
549 int origBC = _first_linker_op + idx;
550 assert(origBC >= _first_linker_op && origBC <= _last_linker_op);
551 iname = BC_NAME[origBC];
552 iname += (isSuper ? "_super" : "_this");
553 if (isAload) iname = "aload_0&" + iname;
554 iname = "*"+iname;
555 } else if (isInvokeInitOp(bc)) {
556 int idx = (bc - _invokeinit_op);
557 switch (idx) {
558 case _invokeinit_self_option:
559 iname = "*invokespecial_init_this"; break;
560 case _invokeinit_super_option:
561 iname = "*invokespecial_init_super"; break;
562 default:
563 assert(idx == _invokeinit_new_option);
564 iname = "*invokespecial_init_new"; break;
565 }
566 } else {
567 switch (bc) {
568 case _ildc: iname = "*ildc"; break;
569 case _fldc: iname = "*fldc"; break;
570 case _ildc_w: iname = "*ildc_w"; break;
571 case _fldc_w: iname = "*fldc_w"; break;
572 case _dldc2_w: iname = "*dldc2_w"; break;
573 case _cldc: iname = "*cldc"; break;
574 case _cldc_w: iname = "*cldc_w"; break;
575 case _byte_escape: iname = "*byte_escape"; break;
576 case _ref_escape: iname = "*ref_escape"; break;
577 case _end_marker: iname = "*end"; break;
578 default: iname = "*bc#"+bc; break;
579 }
580 }
581 return iname;
582 }
583 private static int BW = 4; // width of classification field
584 private static void def(String fmt, int bc) {
585 def(fmt, bc, bc);
586 }
587 private static void def(String fmt, int from_bc, int to_bc) {
588 String[] fmts = { fmt, null };
589 if (fmt.indexOf('w') > 0) {
590 fmts[1] = fmt.substring(fmt.indexOf('w'));
591 fmts[0] = fmt.substring(0, fmt.indexOf('w'));
592 }
593 for (int w = 0; w <= 1; w++) {
594 fmt = fmts[w];
595 if (fmt == null) continue;
596 int length = fmt.length();
597 int index = Math.max(0, fmt.indexOf('k'));
598 int tag = CONSTANT_None;
599 int branch = Math.max(0, fmt.indexOf('o'));
600 int slot = Math.max(0, fmt.indexOf('l'));
601 int con = Math.max(0, fmt.indexOf('x'));
602 if (index > 0 && index+1 < length) {
603 switch (fmt.charAt(index+1)) {
604 case 'c': tag = CONSTANT_Class; break;
605 case 'k': tag = CONSTANT_Literal; break;
606 case 'f': tag = CONSTANT_Fieldref; break;
607 case 'm': tag = CONSTANT_Methodref; break;
608 case 'i': tag = CONSTANT_InterfaceMethodref; break;
609 }
610 assert(tag != CONSTANT_None);
611 } else if (index > 0 && length == 2) {
612 assert(from_bc == _ldc);
613 tag = CONSTANT_Literal; // _ldc opcode only
614 }
615 for (int bc = from_bc; bc <= to_bc; bc++) {
616 BC_FORMAT[w][bc] = fmt;
617 assert(BC_LENGTH[w][bc] == -1);
618 BC_LENGTH[w][bc] = (byte) length;
619 BC_INDEX[w][bc] = (byte) index;
620 BC_TAG[w][bc] = (byte) tag;
621 assert(!(index == 0 && tag != CONSTANT_None));
622 BC_BRANCH[w][bc] = (byte) branch;
623 BC_SLOT[w][bc] = (byte) slot;
624 assert(branch == 0 || slot == 0); // not both branch & local
625 assert(branch == 0 || index == 0); // not both branch & cp
626 assert(slot == 0 || index == 0); // not both local & cp
627 BC_CON[w][bc] = (byte) con;
628 }
629 }
630 }
631}