1 /*
2 * Copyright (c) 2022, 2025, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.classfile.impl;
26
27 import java.lang.classfile.*;
28 import java.lang.classfile.attribute.CodeAttribute;
29 import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
30 import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
31 import java.lang.classfile.attribute.StackMapTableAttribute;
32 import java.lang.classfile.attribute.UnknownAttribute;
33 import java.lang.classfile.constantpool.ClassEntry;
34 import java.lang.classfile.instruction.*;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.Objects;
39 import java.util.Optional;
40 import java.util.function.Consumer;
41
42 import static jdk.internal.classfile.impl.StackMapGenerator.*;
43 import static jdk.internal.classfile.impl.RawBytecodeHelper.*;
44
45 public final class CodeImpl
46 extends BoundAttribute.BoundCodeAttribute
47 implements LabelContext {
48
49 static final Instruction[] SINGLETON_INSTRUCTIONS = new Instruction[256];
50
51 static {
52 for (var o : Opcode.values()) {
53 if (o.sizeIfFixed() == 1) {
54 SINGLETON_INSTRUCTIONS[o.bytecode()] = switch (o.kind()) {
55 case ARRAY_LOAD -> ArrayLoadInstruction.of(o);
56 case ARRAY_STORE -> ArrayStoreInstruction.of(o);
57 case CONSTANT -> ConstantInstruction.ofIntrinsic(o);
58 case CONVERT -> ConvertInstruction.of(o);
59 case LOAD -> new AbstractInstruction.UnboundLoadInstruction(o, BytecodeHelpers.intrinsicLoadSlot(o));
60 case MONITOR -> MonitorInstruction.of(o);
61 case NOP -> NopInstruction.of();
62 case OPERATOR -> OperatorInstruction.of(o);
63 case RETURN -> ReturnInstruction.of(o);
64 case STACK -> StackInstruction.of(o);
65 case STORE -> new AbstractInstruction.UnboundStoreInstruction(o, BytecodeHelpers.intrinsicStoreSlot(o));
66 case THROW_EXCEPTION -> ThrowInstruction.of();
67 default -> throw new AssertionError("invalid opcode: " + o);
68 };
69 }
70 }
71 }
72
73 List<ExceptionCatch> exceptionTable;
74 List<Attribute<?>> attributes;
75
76 // Inflated for iteration
77 LabelImpl[] labels;
78 int[] lineNumbers;
79 boolean inflated;
80
81 public CodeImpl(AttributedElement enclosing,
82 ClassReader reader,
83 AttributeMapper<CodeAttribute> mapper,
84 int payloadStart) {
85 super(enclosing, reader, mapper, payloadStart);
86 }
87
88 // LabelContext
89
90 @Override
91 public Label newLabel() {
92 throw new UnsupportedOperationException("CodeAttribute only supports fixed labels");
93 }
94
95 @Override
96 public void setLabelTarget(Label label, int bci) {
97 throw new UnsupportedOperationException("CodeAttribute only supports fixed labels");
98 }
99
100 @Override
101 public Label getLabel(int bci) {
102 if (bci < 0 || bci > codeLength)
103 throw new IllegalArgumentException(String.format("Bytecode offset out of range; bci=%d, codeLength=%d",
104 bci, codeLength));
105 if (labels == null)
106 labels = new LabelImpl[codeLength + 1];
107 LabelImpl l = labels[bci];
108 if (l == null)
109 l = labels[bci] = new LabelImpl(this, bci);
110 return l;
111 }
112
113 @Override
114 public int labelToBci(Label label) {
115 LabelImpl lab = (LabelImpl) label;
116 if (lab.labelContext() != this)
117 throw new IllegalArgumentException(String.format("Illegal label reuse; context=%s, label=%s",
118 this, lab.labelContext()));
119 return lab.getBCI();
120 }
121
122 private void inflateMetadata() {
123 if (!inflated) {
124 if (labels == null)
125 labels = new LabelImpl[codeLength + 1];
126 if (classReader.context().passLineNumbers())
127 inflateLineNumbers();
128 inflateJumpTargets();
129 inflateTypeAnnotations();
130 inflated = true;
131 }
132 }
133
134 // CodeAttribute
135
136 @Override
137 public List<Attribute<?>> attributes() {
138 if (attributes == null) {
139 attributes = BoundAttribute.readAttributes(this, classReader, attributePos, classReader.customAttributes());
140 }
141 return attributes;
142 }
143
144 @Override
145 public void writeTo(BufWriterImpl buf) {
146 var methodInfo = (MethodInfo) enclosingMethod;
147 if (Util.canSkipMethodInflation(classReader, methodInfo, buf)) {
148 super.writeTo(buf);
149 }
150 else {
151 DirectCodeBuilder.build(methodInfo,
152 Util.writingAll(this),
153 (SplitConstantPool)buf.constantPool(),
154 buf.context(),
155 null).writeTo(buf);
156 }
157 }
158
159 // CodeModel
160
161 @Override
162 public Optional<MethodModel> parent() {
163 return Optional.of(enclosingMethod);
164 }
165
166 @Override
167 public void forEach(Consumer<? super CodeElement> consumer) {
168 Objects.requireNonNull(consumer);
169 inflateMetadata();
170 boolean doLineNumbers = (lineNumbers != null);
171 generateCatchTargets(consumer);
172 if (classReader.context().passDebugElements())
173 generateDebugElements(consumer);
174 generateUserAttributes(consumer);
175 for (int pos=codeStart; pos<codeEnd; ) {
176 if (labels[pos - codeStart] != null)
177 consumer.accept(labels[pos - codeStart]);
178 if (doLineNumbers && lineNumbers[pos - codeStart] != 0)
179 consumer.accept(LineNumberImpl.of(lineNumbers[pos - codeStart]));
180 int bc = classReader.readU1(pos);
181 Instruction instr = bcToInstruction(bc, pos);
182 consumer.accept(instr);
183 pos += instr.sizeInBytes();
184 }
185 // There might be labels pointing to the bci at codeEnd
186 if (labels[codeEnd-codeStart] != null)
187 consumer.accept(labels[codeEnd - codeStart]);
188 if (doLineNumbers && lineNumbers[codeEnd - codeStart] != 0)
189 consumer.accept(LineNumberImpl.of(lineNumbers[codeEnd - codeStart]));
190 }
191
192 @Override
193 public List<ExceptionCatch> exceptionHandlers() {
194 if (exceptionTable == null) {
195 inflateMetadata();
196 exceptionTable = new ArrayList<>(exceptionHandlerCnt);
197 iterateExceptionHandlers(new ExceptionHandlerAction() {
198 @Override
199 public void accept(int s, int e, int h, int c) {
200 ClassEntry catchTypeEntry = c == 0
201 ? null
202 : constantPool().entryByIndex(c, ClassEntry.class);
203 exceptionTable.add(new AbstractPseudoInstruction.ExceptionCatchImpl(getLabel(h), getLabel(s), getLabel(e), catchTypeEntry));
204 }
205 });
206 exceptionTable = Collections.unmodifiableList(exceptionTable);
207 }
208 return exceptionTable;
209 }
210
211 private void generateUserAttributes(Consumer<? super CodeElement> consumer) {
212 for (var attr : attributes) {
213 if (attr instanceof CustomAttribute || attr instanceof UnknownAttribute) {
214 consumer.accept((CodeElement) attr);
215 }
216 }
217 }
218
219 public boolean compareCodeBytes(BufWriterImpl buf, int offset, int len) {
220 return codeLength == len
221 && classReader.compare(buf, offset, codeStart, codeLength);
222 }
223
224 private int adjustForObjectOrUninitialized(int bci) {
225 int vt = classReader.readU1(bci);
226 //inflate newTarget labels from Uninitialized VTIs
227 if (vt == 8) inflateLabel(classReader.readU2(bci + 1));
228 return (vt == 7 || vt == 8) ? bci + 3 : bci + 1;
229 }
230
231 private void inflateLabel(int bci) {
232 if (bci < 0 || bci > codeLength)
233 throw new IllegalArgumentException(String.format("Bytecode offset out of range; bci=%d, codeLength=%d",
234 bci, codeLength));
235 if (labels[bci] == null)
236 labels[bci] = new LabelImpl(this, bci);
237 }
238
239 private void inflateLineNumbers() {
240 for (Attribute<?> a : attributes()) {
241 if (a.attributeMapper() == Attributes.lineNumberTable()) {
242 BoundLineNumberTableAttribute attr = (BoundLineNumberTableAttribute) a;
243 if (lineNumbers == null)
244 lineNumbers = new int[codeLength + 1];
245
246 int nLn = classReader.readU2(attr.payloadStart);
247 int p = attr.payloadStart + 2;
248 int pEnd = p + (nLn * 4);
249 for (; p < pEnd; p += 4) {
250 int startPc = classReader.readU2(p);
251 if (startPc > codeLength) {
252 throw new IllegalArgumentException(String.format(
253 "Line number start_pc out of range; start_pc=%d, codeLength=%d", startPc, codeLength));
254 }
255 int lineNumber = classReader.readU2(p + 2);
256 lineNumbers[startPc] = lineNumber;
257 }
258 }
259 }
260 }
261
262 private void inflateJumpTargets() {
263 Optional<StackMapTableAttribute> a = findAttribute(Attributes.stackMapTable());
264 if (a.isEmpty()) {
265 if (classReader.readU2(6) <= ClassFile.JAVA_6_VERSION) {
266 //fallback to jump targets inflation without StackMapTableAttribute
267 for (int pos=codeStart; pos<codeEnd; ) {
268 var i = bcToInstruction(classReader.readU1(pos), pos);
269 switch (i.opcode().kind()) {
270 case BRANCH -> ((BranchInstruction) i).target();
271 case DISCONTINUED_JSR -> ((DiscontinuedInstruction.JsrInstruction) i).target();
272 case LOOKUP_SWITCH -> {
273 var ls = (LookupSwitchInstruction) i;
274 ls.defaultTarget();
275 ls.cases();
276 }
277 case TABLE_SWITCH -> {
278 var ts = (TableSwitchInstruction) i;
279 ts.defaultTarget();
280 ts.cases();
281 }
282 default -> {}
283 }
284 pos += i.sizeInBytes();
285 }
286 }
287 return;
288 }
289 int stackMapPos = ((BoundAttribute<StackMapTableAttribute>) a.get()).payloadStart;
290
291 int bci = -1; //compensate for offsetDelta + 1
292 int nEntries = classReader.readU2(stackMapPos);
293 int p = stackMapPos + 2;
294 for (int i = 0; i < nEntries; ++i) {
295 int frameType = classReader.readU1(p);
296 int offsetDelta = -1;
297 if (frameType <= SAME_FRAME_END) {
298 offsetDelta = frameType;
299 ++p;
300 }
301 else if (frameType <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) {
302 offsetDelta = frameType & 0x3f;
303 p = adjustForObjectOrUninitialized(p + 1);
304 }
305 else {
306 switch (frameType) {
307 case EARLY_LARVAL -> {
308 int numberOfUnsetFields = classReader.readU2(p + 1);
309 p += 3;
310 p += 2 * numberOfUnsetFields;
311 i--; // one more enclosed frame
312 continue;
313 }
314 case SAME_LOCALS_1_STACK_ITEM_EXTENDED -> {
315 offsetDelta = classReader.readU2(p + 1);
316 p = adjustForObjectOrUninitialized(p + 3);
317 }
318 case CHOP_FRAME_START, CHOP_FRAME_START + 1, CHOP_FRAME_END, SAME_FRAME_EXTENDED -> {
319 offsetDelta = classReader.readU2(p + 1);
320 p += 3;
321 }
322 case APPEND_FRAME_START, APPEND_FRAME_START + 1, APPEND_FRAME_END -> {
323 offsetDelta = classReader.readU2(p + 1);
324 int k = frameType - APPEND_FRAME_START + 1;
325 p += 3;
326 for (int c = 0; c < k; ++c) {
327 p = adjustForObjectOrUninitialized(p);
328 }
329 }
330 case FULL_FRAME -> {
331 offsetDelta = classReader.readU2(p + 1);
332 p += 3;
333 int k = classReader.readU2(p);
334 p += 2;
335 for (int c = 0; c < k; ++c) {
336 p = adjustForObjectOrUninitialized(p);
337 }
338 k = classReader.readU2(p);
339 p += 2;
340 for (int c = 0; c < k; ++c) {
341 p = adjustForObjectOrUninitialized(p);
342 }
343 }
344 default -> throw new IllegalArgumentException("Bad frame type: " + frameType);
345 }
346 }
347 bci += offsetDelta + 1;
348 inflateLabel(bci);
349 }
350 }
351
352 private void inflateTypeAnnotations() {
353 findAttribute(Attributes.runtimeVisibleTypeAnnotations()).ifPresent(RuntimeVisibleTypeAnnotationsAttribute::annotations);
354 findAttribute(Attributes.runtimeInvisibleTypeAnnotations()).ifPresent(RuntimeInvisibleTypeAnnotationsAttribute::annotations);
355 }
356
357 private void generateCatchTargets(Consumer<? super CodeElement> consumer) {
358 // We attach all catch targets to bci zero, because trying to attach them
359 // to their range could subtly affect the order of exception processing
360 iterateExceptionHandlers(new ExceptionHandlerAction() {
361 @Override
362 public void accept(int s, int e, int h, int c) {
363 ClassEntry catchType = c == 0
364 ? null
365 : classReader.entryByIndex(c, ClassEntry.class);
366 consumer.accept(new AbstractPseudoInstruction.ExceptionCatchImpl(getLabel(h), getLabel(s), getLabel(e), catchType));
367 }
368 });
369 }
370
371 private void generateDebugElements(Consumer<? super CodeElement> consumer) {
372 for (Attribute<?> a : attributes()) {
373 if (a.attributeMapper() == Attributes.characterRangeTable()) {
374 var attr = (BoundCharacterRangeTableAttribute) a;
375 int cnt = classReader.readU2(attr.payloadStart);
376 int p = attr.payloadStart + 2;
377 int pEnd = p + (cnt * 14);
378 for (; p < pEnd; p += 14) {
379 var instruction = new BoundCharacterRange(this, p);
380 inflateLabel(instruction.startPc());
381 inflateLabel(instruction.endPc() + 1);
382 consumer.accept(instruction);
383 }
384 }
385 else if (a.attributeMapper() == Attributes.localVariableTable()) {
386 var attr = (BoundLocalVariableTableAttribute) a;
387 int cnt = classReader.readU2(attr.payloadStart);
388 int p = attr.payloadStart + 2;
389 int pEnd = p + (cnt * 10);
390 for (; p < pEnd; p += 10) {
391 BoundLocalVariable instruction = new BoundLocalVariable(this, p);
392 inflateLabel(instruction.startPc());
393 inflateLabel(instruction.startPc() + instruction.length());
394 consumer.accept(instruction);
395 }
396 }
397 else if (a.attributeMapper() == Attributes.localVariableTypeTable()) {
398 var attr = (BoundLocalVariableTypeTableAttribute) a;
399 int cnt = classReader.readU2(attr.payloadStart);
400 int p = attr.payloadStart + 2;
401 int pEnd = p + (cnt * 10);
402 for (; p < pEnd; p += 10) {
403 BoundLocalVariableType instruction = new BoundLocalVariableType(this, p);
404 inflateLabel(instruction.startPc());
405 inflateLabel(instruction.startPc() + instruction.length());
406 consumer.accept(instruction);
407 }
408 }
409 else if (a.attributeMapper() == Attributes.runtimeVisibleTypeAnnotations()) {
410 consumer.accept((BoundRuntimeVisibleTypeAnnotationsAttribute) a);
411 }
412 else if (a.attributeMapper() == Attributes.runtimeInvisibleTypeAnnotations()) {
413 consumer.accept((BoundRuntimeInvisibleTypeAnnotationsAttribute) a);
414 }
415 }
416 }
417
418 public interface ExceptionHandlerAction {
419 void accept(int start, int end, int handler, int catchTypeIndex);
420 }
421
422 public void iterateExceptionHandlers(ExceptionHandlerAction a) {
423 int p = exceptionHandlerPos + 2;
424 for (int i = 0; i < exceptionHandlerCnt; ++i) {
425 a.accept(classReader.readU2(p), classReader.readU2(p + 2), classReader.readU2(p + 4), classReader.readU2(p + 6));
426 p += 8;
427 }
428 }
429
430 private Instruction bcToInstruction(int bc, int pos) {
431 return switch (bc) {
432 case BIPUSH -> new AbstractInstruction.BoundArgumentConstantInstruction(Opcode.BIPUSH, CodeImpl.this, pos);
433 case SIPUSH -> new AbstractInstruction.BoundArgumentConstantInstruction(Opcode.SIPUSH, CodeImpl.this, pos);
434 case LDC -> new AbstractInstruction.BoundLoadConstantInstruction(Opcode.LDC, CodeImpl.this, pos);
435 case LDC_W -> new AbstractInstruction.BoundLoadConstantInstruction(Opcode.LDC_W, CodeImpl.this, pos);
436 case LDC2_W -> new AbstractInstruction.BoundLoadConstantInstruction(Opcode.LDC2_W, CodeImpl.this, pos);
437 case ILOAD -> new AbstractInstruction.BoundLoadInstruction(Opcode.ILOAD, CodeImpl.this, pos);
438 case LLOAD -> new AbstractInstruction.BoundLoadInstruction(Opcode.LLOAD, CodeImpl.this, pos);
439 case FLOAD -> new AbstractInstruction.BoundLoadInstruction(Opcode.FLOAD, CodeImpl.this, pos);
440 case DLOAD -> new AbstractInstruction.BoundLoadInstruction(Opcode.DLOAD, CodeImpl.this, pos);
441 case ALOAD -> new AbstractInstruction.BoundLoadInstruction(Opcode.ALOAD, CodeImpl.this, pos);
442 case ISTORE -> new AbstractInstruction.BoundStoreInstruction(Opcode.ISTORE, CodeImpl.this, pos);
443 case LSTORE -> new AbstractInstruction.BoundStoreInstruction(Opcode.LSTORE, CodeImpl.this, pos);
444 case FSTORE -> new AbstractInstruction.BoundStoreInstruction(Opcode.FSTORE, CodeImpl.this, pos);
445 case DSTORE -> new AbstractInstruction.BoundStoreInstruction(Opcode.DSTORE, CodeImpl.this, pos);
446 case ASTORE -> new AbstractInstruction.BoundStoreInstruction(Opcode.ASTORE, CodeImpl.this, pos);
447 case IINC -> new AbstractInstruction.BoundIncrementInstruction(Opcode.IINC, CodeImpl.this, pos);
448 case IFEQ -> new AbstractInstruction.BoundBranchInstruction(Opcode.IFEQ, CodeImpl.this, pos);
449 case IFNE -> new AbstractInstruction.BoundBranchInstruction(Opcode.IFNE, CodeImpl.this, pos);
450 case IFLT -> new AbstractInstruction.BoundBranchInstruction(Opcode.IFLT, CodeImpl.this, pos);
451 case IFGE -> new AbstractInstruction.BoundBranchInstruction(Opcode.IFGE, CodeImpl.this, pos);
452 case IFGT -> new AbstractInstruction.BoundBranchInstruction(Opcode.IFGT, CodeImpl.this, pos);
453 case IFLE -> new AbstractInstruction.BoundBranchInstruction(Opcode.IFLE, CodeImpl.this, pos);
454 case IF_ICMPEQ -> new AbstractInstruction.BoundBranchInstruction(Opcode.IF_ICMPEQ, CodeImpl.this, pos);
455 case IF_ICMPNE -> new AbstractInstruction.BoundBranchInstruction(Opcode.IF_ICMPNE, CodeImpl.this, pos);
456 case IF_ICMPLT -> new AbstractInstruction.BoundBranchInstruction(Opcode.IF_ICMPLT, CodeImpl.this, pos);
457 case IF_ICMPGE -> new AbstractInstruction.BoundBranchInstruction(Opcode.IF_ICMPGE, CodeImpl.this, pos);
458 case IF_ICMPGT -> new AbstractInstruction.BoundBranchInstruction(Opcode.IF_ICMPGT, CodeImpl.this, pos);
459 case IF_ICMPLE -> new AbstractInstruction.BoundBranchInstruction(Opcode.IF_ICMPLE, CodeImpl.this, pos);
460 case IF_ACMPEQ -> new AbstractInstruction.BoundBranchInstruction(Opcode.IF_ACMPEQ, CodeImpl.this, pos);
461 case IF_ACMPNE -> new AbstractInstruction.BoundBranchInstruction(Opcode.IF_ACMPNE, CodeImpl.this, pos);
462 case GOTO -> new AbstractInstruction.BoundBranchInstruction(Opcode.GOTO, CodeImpl.this, pos);
463 case TABLESWITCH -> new AbstractInstruction.BoundTableSwitchInstruction(Opcode.TABLESWITCH, CodeImpl.this, pos);
464 case LOOKUPSWITCH -> new AbstractInstruction.BoundLookupSwitchInstruction(Opcode.LOOKUPSWITCH, CodeImpl.this, pos);
465 case GETSTATIC -> new AbstractInstruction.BoundFieldInstruction(Opcode.GETSTATIC, CodeImpl.this, pos);
466 case PUTSTATIC -> new AbstractInstruction.BoundFieldInstruction(Opcode.PUTSTATIC, CodeImpl.this, pos);
467 case GETFIELD -> new AbstractInstruction.BoundFieldInstruction(Opcode.GETFIELD, CodeImpl.this, pos);
468 case PUTFIELD -> new AbstractInstruction.BoundFieldInstruction(Opcode.PUTFIELD, CodeImpl.this, pos);
469 case INVOKEVIRTUAL -> new AbstractInstruction.BoundInvokeInstruction(Opcode.INVOKEVIRTUAL, CodeImpl.this, pos);
470 case INVOKESPECIAL -> new AbstractInstruction.BoundInvokeInstruction(Opcode.INVOKESPECIAL, CodeImpl.this, pos);
471 case INVOKESTATIC -> new AbstractInstruction.BoundInvokeInstruction(Opcode.INVOKESTATIC, CodeImpl.this, pos);
472 case INVOKEINTERFACE -> new AbstractInstruction.BoundInvokeInterfaceInstruction(Opcode.INVOKEINTERFACE, CodeImpl.this, pos);
473 case INVOKEDYNAMIC -> new AbstractInstruction.BoundInvokeDynamicInstruction(Opcode.INVOKEDYNAMIC, CodeImpl.this, pos);
474 case NEW -> new AbstractInstruction.BoundNewObjectInstruction(CodeImpl.this, pos);
475 case NEWARRAY -> new AbstractInstruction.BoundNewPrimitiveArrayInstruction(Opcode.NEWARRAY, CodeImpl.this, pos);
476 case ANEWARRAY -> new AbstractInstruction.BoundNewReferenceArrayInstruction(Opcode.ANEWARRAY, CodeImpl.this, pos);
477 case CHECKCAST -> new AbstractInstruction.BoundTypeCheckInstruction(Opcode.CHECKCAST, CodeImpl.this, pos);
478 case INSTANCEOF -> new AbstractInstruction.BoundTypeCheckInstruction(Opcode.INSTANCEOF, CodeImpl.this, pos);
479
480 case WIDE -> {
481 int bclow = classReader.readU1(pos + 1);
482 yield switch (bclow) {
483 case ILOAD -> new AbstractInstruction.BoundLoadInstruction(Opcode.ILOAD_W, this, pos);
484 case LLOAD -> new AbstractInstruction.BoundLoadInstruction(Opcode.LLOAD_W, this, pos);
485 case FLOAD -> new AbstractInstruction.BoundLoadInstruction(Opcode.FLOAD_W, this, pos);
486 case DLOAD -> new AbstractInstruction.BoundLoadInstruction(Opcode.DLOAD_W, this, pos);
487 case ALOAD -> new AbstractInstruction.BoundLoadInstruction(Opcode.ALOAD_W, this, pos);
488 case ISTORE -> new AbstractInstruction.BoundStoreInstruction(Opcode.ISTORE_W, this, pos);
489 case LSTORE -> new AbstractInstruction.BoundStoreInstruction(Opcode.LSTORE_W, this, pos);
490 case FSTORE -> new AbstractInstruction.BoundStoreInstruction(Opcode.FSTORE_W, this, pos);
491 case DSTORE -> new AbstractInstruction.BoundStoreInstruction(Opcode.DSTORE_W, this, pos);
492 case ASTORE -> new AbstractInstruction.BoundStoreInstruction(Opcode.ASTORE_W, this, pos);
493 case IINC -> new AbstractInstruction.BoundIncrementInstruction(Opcode.IINC_W, this, pos);
494 case RET -> new AbstractInstruction.BoundRetInstruction(Opcode.RET_W, this, pos);
495 default -> throw new IllegalArgumentException("unknown wide instruction: " + bclow);
496 };
497 }
498
499 case MULTIANEWARRAY -> new AbstractInstruction.BoundNewMultidimensionalArrayInstruction(Opcode.MULTIANEWARRAY, CodeImpl.this, pos);
500 case IFNULL -> new AbstractInstruction.BoundBranchInstruction(Opcode.IFNULL, CodeImpl.this, pos);
501 case IFNONNULL -> new AbstractInstruction.BoundBranchInstruction(Opcode.IFNONNULL, CodeImpl.this, pos);
502 case GOTO_W -> new AbstractInstruction.BoundBranchInstruction(Opcode.GOTO_W, CodeImpl.this, pos);
503
504 case JSR -> new AbstractInstruction.BoundJsrInstruction(Opcode.JSR, CodeImpl.this, pos);
505 case RET -> new AbstractInstruction.BoundRetInstruction(Opcode.RET, this, pos);
506 case JSR_W -> new AbstractInstruction.BoundJsrInstruction(Opcode.JSR_W, CodeImpl.this, pos);
507 default -> {
508 Instruction instr = SINGLETON_INSTRUCTIONS[bc];
509 if (instr == null)
510 throw new IllegalArgumentException("unknown instruction: " + bc);
511 yield instr;
512 }
513 };
514 }
515
516 @Override
517 public String toString() {
518 return String.format("CodeModel[id=%d]", System.identityHashCode(this));
519 }
520 }
--- EOF ---