1 /*
2 * Copyright (c) 2018, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test id=default
26 * @key randomness
27 * @summary Fuzz tests for jdk.internal.vm.Continuation
28 * @requires vm.continuations
29 * @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4)
30 * @requires vm.opt.TieredCompilation == null | vm.opt.TieredCompilation == true
31 * @modules java.base java.base/jdk.internal.vm.annotation java.base/jdk.internal.vm
32 * @library /test/lib
33 * @enablePreview
34 * @build java.base/java.lang.StackWalkerHelper
35 * @build jdk.test.whitebox.WhiteBox
36 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
37 *
38 * @run main/othervm/timeout=1200 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
39 * Fuzz
40 */
41
42 /*
43 * @test id=preserve-fp
44 * @key randomness
45 * @summary Fuzz tests for jdk.internal.vm.Continuation
46 * @requires vm.continuations
47 * @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4)
48 * @requires vm.opt.TieredCompilation == null | vm.opt.TieredCompilation == true
49 * @modules java.base java.base/jdk.internal.vm.annotation java.base/jdk.internal.vm
50 * @library /test/lib
51 * @enablePreview
52 * @build java.base/java.lang.StackWalkerHelper
53 * @build jdk.test.whitebox.WhiteBox
54 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
55 *
56 * @run main/othervm/timeout=1200 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
57 * -XX:+PreserveFramePointer
58 * Fuzz
59 */
60
61 import jdk.internal.vm.Continuation;
62 import jdk.internal.vm.ContinuationScope;
63
64 import java.lang.invoke.*;
65 import java.lang.reflect.*;
66 import java.lang.StackWalker.StackFrame;
67 import java.nio.file.*;
68 import java.util.*;
69 import java.util.function.*;
70 import java.util.stream.*;
71 import static java.lang.Math.max;
72 import static java.lang.Math.min;
73 import jdk.internal.vm.annotation.DontInline;
74 import jdk.test.lib.Utils;
75 import jdk.test.whitebox.WhiteBox;
76
77 import jdk.test.lib.Platform;
78 import jtreg.SkippedException;
79
80 import com.sun.management.HotSpotDiagnosticMXBean;
81 import java.lang.management.ManagementFactory;
82
83 public class Fuzz implements Runnable {
84 static final boolean VERIFY_STACK = true; // could add significant time
85 static final boolean FILE = true;
86 static final boolean RANDOM = true;
87 static final boolean VERBOSE = false;
88 static final Random RAND = Utils.getRandomInstance();
89
90 static int COMPILATION_TIMEOUT = (int)(5_000 * Utils.TIMEOUT_FACTOR); // ms
91
92 static final Path TEST_DIR = Path.of(System.getProperty("test.src", "."));
93
94 public static void main(String[] args) {
95 if (Platform.isSlowDebugBuild() && Platform.isOSX() && Platform.isAArch64()) {
96 throw new SkippedException("Test is unstable with slowdebug bits "
97 + "on macosx-aarch64");
98 }
99 if (Platform.isPPC()) {
100 COMPILATION_TIMEOUT = COMPILATION_TIMEOUT * 2;
101 }
102 warmup();
103 for (int compileLevel : new int[]{4}) {
104 for (boolean compileRun : new boolean[]{true}) {
105 COMPILE_LEVEL = compileLevel;
106 COMPILE_RUN = compileRun;
107 resetCompilation();
108 runTests();
109 }
110 }
111 }
112
113 static void runTests() {
114 if (FILE) testFile("fuzz.dat");
115 if (RANDOM) testRandom(RAND.nextLong(), 50);
116 }
117
118 ////////////////
119
120 enum Op {
121 CALL_I_INT, CALL_I_DBL, CALL_I_MANY, CALL_I_VAL,
122 CALL_C_INT, CALL_C_DBL, CALL_C_MANY, CALL_C_VAL,
123 CALL_I_CTCH, CALL_C_CTCH,
124 CALL_I_PIN, CALL_C_PIN,
125 MH_I_INT, MH_C_INT, MH_I_MANY, MH_C_MANY,
126 REF_I_INT, REF_C_INT, REF_I_MANY, REF_C_MANY,
127 LOOP, YIELD, THROW, DONE;
128
129 static final EnumSet<Op> BASIC = EnumSet.of(LOOP, YIELD);
130 static final EnumSet<Op> STANDARD = EnumSet.range(CALL_I_INT, CALL_C_CTCH);
131 static final EnumSet<Op> PIN = EnumSet.range(CALL_I_PIN, CALL_C_PIN);
132 static final EnumSet<Op> MH = EnumSet.range(MH_I_INT, MH_C_MANY);
133 static final EnumSet<Op> REFLECTED = EnumSet.range(REF_I_INT, REF_C_MANY);
134 static final EnumSet<Op> NON_CALLS = EnumSet.range(LOOP, DONE);
135 static final EnumSet<Op> COMPILED = EnumSet.copyOf(Arrays.stream(Op.values()).filter(x -> x.toString().contains("_C_")).collect(Collectors.toList()));
136 static final EnumSet<Op> INTERPRETED = EnumSet.copyOf(Arrays.stream(Op.values()).filter(x -> x.toString().contains("_I_")).collect(Collectors.toList()));
137
138 static Op toInterpreted(Op op) { return INTERPRETED.contains(op) ? op : Enum.valueOf(Op.class, op.toString().replace("_C_", "_I_")); }
139 static Op toCompiled(Op op) { return COMPILED.contains(op) ? op : Enum.valueOf(Op.class, op.toString().replace("_I_", "_C_")); }
140 }
141
142 static class Generator {
143 public Op[] generate() {
144 final int length = max(1, pick(5, 10, 50/*, 200*/) + plusOrMinus(5));
145
146 Set<Op> highProb = new HashSet<Op>();
147 Set<Op> lowProb = new HashSet<Op>();
148
149 if (percent(100)) highProb.addAll(Op.BASIC);
150 if (percent(100)) highProb.addAll(Op.STANDARD);
151 if (percent(1)) lowProb.add(Op.THROW);
152 if (percent(3)) lowProb.addAll(Op.PIN);
153 if (percent(3)) lowProb.addAll(Op.MH);
154 if (percent(0)) lowProb.addAll(Op.REFLECTED);
155 if (percent(50)) {
156 highProb.removeAll(Op.INTERPRETED);
157 lowProb.removeAll(Op.INTERPRETED);
158 }
159 Op[] highProb0 = highProb.toArray(Op[]::new);
160 Op[] lowProb0 = lowProb.toArray(Op[]::new);
161
162 int loops = 7;
163 Op[] trace = new Op[length];
164 for (int i=0; i < trace.length; i++) {
165 trace[i] = pick((lowProb.isEmpty() || percent(90)) ? highProb0 : lowProb0);
166 if (trace[i] == Op.LOOP && (loops--) <= 0) i--;
167 }
168 return trace;
169 }
170
171 private final Random rnd;
172 public Generator(Random rnd) { this.rnd = rnd; }
173 @SafeVarargs
174 private <T> T pick(T... values) { return values[rnd.nextInt(values.length)]; }
175 private boolean percent(int percent) { return rnd.nextInt(100) < percent; }
176 private int plusOrMinus(int n) { return rnd.nextInt(2*n + 1) - n; }
177 }
178
179 static Stream<Op[]> random(Random rnd) {
180 var g = new Generator(rnd);
181 return Stream.iterate(0, x->x+1).map(__ -> g.generate());
182 }
183
184 static void testRandom(long seed, int number) {
185 System.out.println("-- RANDOM (seed: " + seed + ") --");
186 testStream(random(new Random(seed)).limit(number));
187 }
188
189 static void testFile(String fileName) {
190 System.out.println("-- FILE (" + fileName + ") --");
191 try {
192 testStream(file(TEST_DIR.resolve(fileName)));
193 } catch (java.io.IOException e) { throw new RuntimeException(e); }
194 }
195
196 static Stream<Op[]> file(Path file) throws java.io.IOException {
197 return Files.lines(file).map(String::trim).filter(s -> !s.isBlank() && !s.startsWith("#")).map(Fuzz::parse);
198 }
199
200 static Op[] parse(String line) {
201 return Arrays.stream(line.split(", ")).map(s -> Enum.valueOf(Op.class, s))
202 .collect(Collectors.toList()).toArray(Op[]::new);
203 }
204
205 static int testCounter;
206
207 static void testStream(Stream<Op[]> traces) { testCounter = 0; traces.forEach(Fuzz::testTrace); }
208
209 ////////////////////////////////////////
210
211 static void testTrace(Op[] trace) {
212 testCounter++;
213 System.out.println("\n" + testCounter + ": COMPILE_LEVEL: " + COMPILE_LEVEL + " COMPILE_RUN: " + COMPILE_RUN);
214 for (int attempt = 0; attempt < 3; attempt++) {
215 if (attempt > 0) System.out.println("RETRYING " + attempt);
216
217 compile();
218
219 long start = time();
220 var fuzz = new Fuzz(trace);
221 fuzz.verbose = VERBOSE && attempt == 0;
222 fuzz.print();
223 int yields = fuzz.test();
224 time(start, "Test (" + yields + " yields)");
225
226 if (fuzz.checkCompilation())
227 break;
228 }
229 }
230
231 static final ContinuationScope SCOPE = new ContinuationScope() {};
232
233 static class FuzzException extends RuntimeException {
234 public FuzzException(String msg) { super(msg); }
235 }
236
237 boolean verbose = false;
238
239 private final Op[] trace;
240 private int index = -1;
241 private int result = -1;
242
243 private Fuzz(Op[] trace) { this.trace = trace; }
244
245 int test() {
246 Continuation cont = new Continuation(SCOPE, this) {
247 @Override protected void onPinned(Pinned reason) { if (verbose) System.out.println("PINNED " + reason); }
248 };
249
250 this.yields = 0;
251 int count = 0;
252 try {
253 while (true) {
254 var start = time();
255 cont.run();
256 if (cont.isDone()) break;
257
258 assert !shouldThrow();
259 verifyStack(cont);
260 count++;
261 time(start, "Iteration");
262 }
263 verifyResult(result);
264 } catch (FuzzException e) {
265 assert shouldThrow();
266 assert e.getMessage().equals("EX");
267 assert cont.isDone();
268 }
269 assert count == yields : "count: " + count + " yields: " + yields;
270 return count;
271 }
272
273 void print() { printTrace(trace); }
274
275 private Op trace(int i) { return i < trace.length ? trace[i] : Op.DONE; }
276 private Op current() { return trace(index); }
277 private Op next(int c) { logOp(c); index++; return current(); }
278
279 ////// Compilation
280
281 private static boolean COMPILE_RUN;
282 private static int COMPILE_LEVEL;
283
284 static final int WARMUP_ITERS = 15_000;
285 static final Op[] WARMUP_TRACE = {Op.MH_C_INT, Op.MH_C_MANY, Op.REF_C_INT, Op.REF_C_MANY, Op.CALL_C_INT, Op.CALL_C_VAL};
286
287 static void warmup() {
288 final long start = time();
289 warmup(WARMUP_TRACE, WARMUP_ITERS); // generate (for reflection) and compile method handles
290 time(start, "Warmup");
291 }
292
293 static void warmup(Op[] trace, int times) {
294 for (int i=0; i<times; i++) {
295 new Fuzz(trace).run();
296 }
297 }
298
299 static void resetCompilation() {
300 Set<Method> compile = Op.COMPILED.stream().map(Fuzz::method).collect(Collectors.toCollection(HashSet::new));
301 compile.add(run);
302
303 for (Method m : compile) {
304 WB.deoptimizeMethod(m);
305 WB.clearMethodState(m);
306 }
307 }
308
309 static void enqueueForCompilation(Method m) {
310 if (WB.isMethodCompiled(m)) return;
311 // WB compilation tasks do not expire while others do,
312 // so we wait for an existing task to finish before enqueuing.
313 // Alternatively run with -XX:TieredCompileTaskTimeout=5000
314 Utils.waitForCondition(() -> WB.isMethodQueuedForCompilation(m), 1000);
315 if (WB.isMethodCompiled(m)) return;
316 WB.enqueueMethodForCompilation(m, COMPILE_LEVEL);
317 }
318
319 static void waitForCompilation(Method m) {
320 if (!Utils.waitForCondition(() -> WB.isMethodCompiled(m), COMPILATION_TIMEOUT)) {
321 System.out.println(">>> Compilation status for: " + m);
322 System.out.println("isMethodCompiled: " + WB.isMethodCompiled(m) + " " +
323 "isMethodCompilable: " + WB.isMethodCompilable(m) + " " +
324 "isMethodQueuedForCompilation: " + WB.isMethodQueuedForCompilation(m) + " " +
325 "getMethodCompilationLevel: " + WB.getMethodCompilationLevel(m));
326 throw new AssertionError("Failed to compile " + m + " in " + COMPILATION_TIMEOUT + "ms");
327 }
328 }
329
330 static void compileContinuation() {
331 var compile = new HashSet<Method>();
332 for (Method m : Continuation.class.getDeclaredMethods()) {
333 if (!WB.isMethodCompiled(m)) {
334 if (!Modifier.isNative(m.getModifiers())
335 && (m.getName().startsWith("enter")
336 || m.getName().startsWith("yield"))) {
337 enqueueForCompilation(m);
338 compile.add(m);
339 }
340 }
341 }
342
343 for (Method m : compile) waitForCompilation(m);
344 }
345
346 static void compile() {
347 final long start = time();
348
349 compileContinuation();
350
351 Set<Method> compile = Op.COMPILED.stream().map(Fuzz::method).collect(Collectors.toCollection(HashSet::new));
352 Set<Method> interpret = Op.INTERPRETED.stream().map(Fuzz::method).collect(Collectors.toCollection(HashSet::new));
353 (COMPILE_RUN ? compile : interpret).add(run);
354
355 compile.addAll(precompile);
356
357 for (Method m : interpret) WB.makeMethodNotCompilable(m);
358
359 for (Method m : compile) enqueueForCompilation(m);
360 for (Method m : compile) waitForCompilation(m);
361 for (Method m : compile) assert WB.isMethodCompiled(m) : "method: " + m;
362 for (Method m : interpret) assert !WB.isMethodCompiled(m) : "method: " + m;
363
364 time(start, "Compile");
365 }
366
367 boolean checkContinuationCompilation() {
368 for (Method m : Continuation.class.getDeclaredMethods()) {
369 if (!WB.isMethodCompiled(m)) {
370 if (!Modifier.isNative(m.getModifiers())
371 && (m.getName().startsWith("enter")
372 || m.getName().startsWith("yield"))) {
373 return false;
374 }
375 }
376 }
377 return true;
378 }
379
380 boolean checkCompilation() {
381 boolean res = true;
382
383 if (!checkContinuationCompilation()) {
384 res = false;
385 System.out.println("CHANGED CONTINUATION COMPILATION");
386 }
387
388 Op[] newTrace = Arrays.copyOf(trace, trace.length);
389 if (!checkCompilation(newTrace)) {
390 res = false;
391 System.out.println("CHANGED COMPILATION");
392 printTrace(newTrace);
393 }
394
395 return res;
396 }
397
398 static boolean checkCompilation(Op[] trace) {
399 boolean ok = true;
400 for (int i = 0; i < trace.length; i++) {
401 Op op = trace[i];
402 if (Op.COMPILED.contains(op) && !WB.isMethodCompiled(method(op))) trace[i] = Op.toInterpreted(op);
403 if (Op.INTERPRETED.contains(op) && WB.isMethodCompiled(method(op))) trace[i] = Op.toCompiled(op);
404 if (op != trace[i]) ok = false;
405 }
406 return ok;
407 }
408
409 /////////// Instance Helpers
410
411 private StackTraceElement[] backtrace;
412 private StackFrame[] fbacktrace;
413 private StackFrame[] lfbacktrace;
414 private int yields;
415
416 void indent(int depth) {
417 // depth = index;
418 for (int i=0; i<depth; i++) System.out.print(" ");
419 }
420
421 void logOp(int iter) {
422 if (!verbose) return;
423
424 int depth = depth();
425 System.out.print("> " + depth + " ");
426 indent(depth);
427 System.out.println("iter: " + iter + " index: " + index + " op: " + trace(index+1));
428 }
429
430 <T> T log(T result) {
431 if (!verbose) return result;
432
433 int depth = depth();
434 System.out.print("> " + depth + " ");
435 indent(depth);
436 System.out.println("result " + result);
437 return result;
438 }
439
440 int depth() {
441 int d = 0;
442 for (int i=0; i<=index && i < trace.length; i++) if (!Op.NON_CALLS.contains(trace[i])) d++;
443 return d;
444 }
445
446 boolean traceHas(Predicate<Op> pred) {
447 for (int i = 0; i < index; i++) if (pred.test(trace[i])) return true;
448 return false;
449 }
450
451 String[] expectedStackTrace() {
452 var ms = new ArrayList<String>();
453 for (int i = index; i >= 0; i--) if (!Op.NON_CALLS.contains(trace[i])) ms.add(method(trace[i]).getName());
454 ms.add("run");
455 return ms.toArray(new String[0]);
456 }
457
458 int computeResult() {
459 // To compute the expected result, we remove all YIELDs from the trace and run it
460 Op[] trace0 = Arrays.stream(trace).filter(op -> op != Op.YIELD)
461 .collect(Collectors.toList()).toArray(Op[]::new);
462
463 Fuzz f0 = new Fuzz(trace0);
464 // if (VERBOSE) {
465 // System.out.println(">>>> RESULT");
466 // f0.verbose = true;
467 // }
468 f0.run();
469 return f0.result;
470 }
471
472 void verifyResult(int result) {
473 int computed = computeResult();
474 assert result == computed : "result: " + result + " expected: " + computed;
475 }
476
477 boolean shouldPin() {
478 // Returns false since we never pin after we removed legacy locking.
479 return traceHas(Op.PIN::contains) && false;
480 }
481
482 void verifyPin(boolean yieldResult) {
483 if (yieldResult) yields++;
484 if (!yieldResult && traceHas(op -> Op.INTERPRETED.contains(op) && Op.REFLECTED.contains(op))) return;
485 assert yieldResult != shouldPin() : "res: " + yieldResult + " shouldPin: " + shouldPin();
486 }
487
488 boolean shouldThrow() {
489 for (int i = 0; i <= index && i < trace.length; i++) {
490 switch (trace[i]) {
491 case CALL_I_CTCH, CALL_C_CTCH -> { return false; }
492 case THROW -> { return true; }
493 default -> {}
494 }
495 }
496 return false;
497 }
498
499 void captureStack() {
500 // Thread.dumpStack();
501 if (!VERIFY_STACK) return;
502 backtrace = Thread.currentThread().getStackTrace();
503 fbacktrace = StackWalkerHelper.getStackFrames(SCOPE);
504 lfbacktrace = StackWalkerHelper.getLiveStackFrames(SCOPE);
505 }
506
507 void verifyStack() {
508 if (!VERIFY_STACK) return;
509 var start = time();
510 verifyStack(backtrace);
511 verifyStack(backtrace, StackWalkerHelper.toStackTraceElement(fbacktrace));
512 verifyStack(fbacktrace, lfbacktrace);
513
514 verifyStack(backtrace, Thread.currentThread().getStackTrace());
515 verifyStack(fbacktrace, StackWalkerHelper.getStackFrames(SCOPE));
516 verifyStack(lfbacktrace, StackWalkerHelper.getLiveStackFrames(SCOPE));
517 time(start, "Verify stack");
518 }
519
520 void verifyStack(Continuation cont) {
521 if (!VERIFY_STACK) return;
522 var start = time();
523 verifyStack(backtrace);
524 verifyStack(backtrace, StackWalkerHelper.toStackTraceElement(fbacktrace));
525 verifyStack(fbacktrace, lfbacktrace);
526
527 verifyStack(backtrace, cont.getStackTrace());
528 verifyStack(fbacktrace, StackWalkerHelper.getStackFrames(cont));
529 verifyStack(lfbacktrace, StackWalkerHelper.getLiveStackFrames(cont));
530 time(start, "Verify continuation stack");
531 }
532
533 static boolean isStackCaptureMechanism(Object sf) {
534 return Fuzz.class.getName().equals(sfClassName(sf))
535 && ("captureStack".equals(sfMethodName(sf)) || "verifyStack".equals(sfMethodName(sf)));
536 }
537
538 static boolean isPrePostYield(Object sf) {
539 return Fuzz.class.getName().equals(sfClassName(sf))
540 && ("preYield".equals(sfMethodName(sf)) || "postYield".equals(sfMethodName(sf)));
541 }
542
543 static <T> T[] cutStack(T[] stack) {
544 var list = new ArrayList<T>();
545 int i = 0;
546 while (i < stack.length && (!Fuzz.class.getName().equals(sfClassName(stack[i])) || isPrePostYield(stack[i]) || isStackCaptureMechanism(stack[i]))) i++;
547 while (i < stack.length && !Continuation.class.getName().equals(sfClassName(stack[i]))) { list.add(stack[i]); i++; }
548 // while (i < stack.length && Continuation.class.getName().equals(sfClassName(stack[i])) && !"enterSpecial".equals(sfMethodName(stack[i]))) { list.add(stack[i]); i++; }
549 return list.toArray(arrayType(stack));
550 }
551
552 void verifyStack(Object[] observed) {
553 verifyStack(
554 expectedStackTrace(),
555 Arrays.stream(cutStack(observed)).filter(sf -> Fuzz.class.getName().equals(sfClassName(sf)))
556 .collect(Collectors.toList()).toArray(Object[]::new));
557 }
558
559 static void verifyStack(Object[] expected, Object[] observed) {
560 expected = cutStack(expected);
561 observed = cutStack(observed);
562 boolean equal = true;
563 if (expected.length == observed.length) {
564 for (int i=0; i < expected.length; i++) {
565 if (!sfEquals(expected[i], observed[i])) {
566 // we allow a different line number for the first element
567 if (i > 0 || !Objects.equals(sfClassName(expected[i]), sfClassName(observed[i])) || !Objects.equals(sfMethodName(expected[i]), sfMethodName(observed[i]))) {
568 System.out.println("At index " + i + " expected: " + sfToString(expected[i]) + " observed: " + sfToString(observed[i]));
569
570 equal = false;
571 break;
572 }
573 }
574 }
575 } else {
576 equal = false;
577 System.out.println("Expected length: " + expected.length + " Observed length: " + observed.length);
578 }
579 if (!equal) {
580 System.out.println("Expected: "); for (var sf : expected) System.out.println("\t" + sf);
581 System.out.println("Observed: "); for (var sf : observed) System.out.println("\t" + sf);
582 }
583 assert equal;
584 }
585
586 static String sfClassName(Object f) {
587 return f instanceof String ? Fuzz.class.getName() :
588 (f instanceof StackTraceElement ? ((StackTraceElement)f).getClassName() : ((StackFrame)f).getClassName()); }
589 static String sfMethodName(Object f) {
590 return f instanceof String ? (String)f :
591 (f instanceof StackTraceElement ? ((StackTraceElement)f).getMethodName() : ((StackFrame)f).getMethodName()); }
592
593 static boolean sfEquals(Object a, Object b) {
594 if (a instanceof String)
595 return sfClassName(a).equals(sfClassName(b)) && sfMethodName(a).equals(sfMethodName(b));
596
597 return a instanceof StackTraceElement ? Objects.equals(a, b)
598 : StackWalkerHelper.equals((StackFrame)a, (StackFrame)b);
599 }
600
601 static String sfToString(Object f) {
602 return f instanceof StackFrame ? StackWalkerHelper.frameToString((StackFrame)f) : Objects.toString(f);
603 }
604
605 //// Value Classes
606
607 static abstract value class BaseValue {
608 public abstract int res();
609 };
610
611 static value class SmallValue extends BaseValue {
612 int x1;
613 int x2;
614
615 public SmallValue(int i) {
616 x1 = i;
617 x2 = i;
618 }
619
620 public int res() {
621 return x1 + x2;
622 }
623 };
624
625 static value class LargeValue extends BaseValue {
626 int x1;
627 int x2;
628 int x3;
629 int x4;
630 int x5;
631 int x6;
632 int x7;
633
634 public LargeValue(int i) {
635 x1 = i;
636 x2 = i;
637 x3 = i;
638 x4 = i;
639 x5 = i;
640 x6 = i;
641 x7 = i;
642 }
643
644 public int res() {
645 return x1 + x2 + x3 + x4 + x5 + x6 + x7;
646 }
647 };
648
649 static value class OopsValue extends BaseValue {
650 Object x1;
651 Object x2;
652 Object x3;
653 Object x4;
654 Object x5;
655 int x6;
656
657 public OopsValue(int i) {
658 x1 = new Object();
659 x2 = new Object();
660 x3 = new Object();
661 x4 = new Object();
662 x5 = new Object();
663 x6 = i;
664 }
665
666 public int res() {
667 return x6;
668 }
669 };
670
671 public static value class DoubleValue extends BaseValue {
672 double d1;
673 double d2;
674 double d3;
675 double d4;
676 double d5;
677 double d6;
678 double d7;
679
680 public DoubleValue(double d) {
681 d1 = d;
682 d2 = d + 1;
683 d3 = d + 2;
684 d4 = d + 3;
685 d5 = d + 4;
686 d6 = d + 4;
687 d7 = d + 4;
688 }
689
690 public int res() {
691 return (int)(d1 + d2 + d3 + d4 + d5 + d6 + d7);
692 }
693 };
694
695 static value class MixedValue extends BaseValue {
696 byte x1;
697 short x2;
698 int x3;
699 long x4;
700 double x5;
701 boolean x6;
702
703 public MixedValue(int i) {
704 x1 = (byte)i;
705 x2 = (short)i;
706 x3 = i;
707 x4 = i;
708 x5 = i;
709 x6 = (i % 2) == 0;
710 }
711
712 public int res() {
713 return (int)x1 + (int)x2 + (int)x3 + (int)x4 + (int)x5 + (x6 ? 1 : 0);
714 }
715 };
716
717 //// Static Helpers
718
719 static void rethrow(Throwable t) {
720 if (t instanceof Error) throw (Error)t;
721 if (t instanceof RuntimeException) throw (RuntimeException)t;
722 throw new AssertionError(t);
723 }
724
725 static <T> T[] arrayType(T[] array) {
726 return (T[])java.lang.reflect.Array.newInstance(array.getClass().componentType(), 0);
727 }
728
729 static void printTrace(Op[] trace) { System.out.println(write(trace)); }
730
731 static String write(Op[] trace) {
732 return Arrays.stream(trace).map(Object::toString).collect(Collectors.joining(", "));
733 }
734
735 static Method method(Op op) { return method.get(op); }
736 static MethodHandle handle(Op op) { return handle.get(op); }
737
738 static long time() { return System.nanoTime(); }
739 static void time(long startNanos, String message) {
740 final long duration = (System.nanoTime() - startNanos)/1_000_000;
741 if (duration > 500)
742 System.out.println(message + " in " + duration + " ms");
743 }
744
745 //////
746
747 private static final WhiteBox WB = WhiteBox.getWhiteBox();
748
749 static final Class<?>[] run_sig = new Class<?>[]{};
750 static final Class<?>[] int_sig = new Class<?>[]{int.class, int.class};
751 static final Class<?>[] dbl_sig = new Class<?>[]{int.class, double.class};
752 static final Class<?>[] val_sig = new Class<?>[]{int.class, SmallValue.class,
753 LargeValue.class, OopsValue.class, DoubleValue.class, MixedValue.class};
754 static final Class<?>[] mny_sig = new Class<?>[]{int.class,
755 int.class, double.class, long.class, float.class, Object.class,
756 int.class, double.class, long.class, float.class, Object.class,
757 int.class, double.class, long.class, float.class, Object.class,
758 int.class, double.class, long.class, float.class, Object.class};
759 static final MethodType run_type = MethodType.methodType(void.class, run_sig);
760 static final MethodType int_type = MethodType.methodType(int.class, int_sig);
761 static final MethodType dbl_type = MethodType.methodType(double.class, dbl_sig);
762 static final MethodType mny_type = MethodType.methodType(int.class, mny_sig);
763
764 static final List<Method> precompile = new ArrayList<>();
765
766 static final Method run;
767 static final Map<Op, Method> method = new EnumMap<>(Op.class);
768 static final Map<Op, MethodHandle> handle = new EnumMap<>(Op.class);
769
770 static {
771 try {
772 run = Fuzz.class.getDeclaredMethod("run", run_sig);
773 // precompile.add(Fuzz.class.getDeclaredMethod("maybeResetIndex", new Class<?>[]{int.class}));
774
775 method.put(Op.CALL_I_INT, Fuzz.class.getDeclaredMethod("int_int", int_sig));
776 method.put(Op.CALL_C_INT, Fuzz.class.getDeclaredMethod("com_int", int_sig));
777 method.put(Op.CALL_I_DBL, Fuzz.class.getDeclaredMethod("int_dbl", dbl_sig));
778 method.put(Op.CALL_C_DBL, Fuzz.class.getDeclaredMethod("com_dbl", dbl_sig));
779 method.put(Op.CALL_I_VAL, Fuzz.class.getDeclaredMethod("int_val", val_sig));
780 method.put(Op.CALL_C_VAL, Fuzz.class.getDeclaredMethod("com_val", val_sig));
781 method.put(Op.CALL_I_MANY, Fuzz.class.getDeclaredMethod("int_mny", mny_sig));
782 method.put(Op.CALL_C_MANY, Fuzz.class.getDeclaredMethod("com_mny", mny_sig));
783 method.put(Op.CALL_I_PIN, Fuzz.class.getDeclaredMethod("int_pin", int_sig));
784 method.put(Op.CALL_C_PIN, Fuzz.class.getDeclaredMethod("com_pin", int_sig));
785
786 method.put(Op.CALL_I_CTCH, method(Op.CALL_I_INT));
787 method.put(Op.CALL_C_CTCH, method(Op.CALL_C_INT));
788
789 method.put(Op.MH_I_INT, method(Op.CALL_I_INT));
790 method.put(Op.MH_C_INT, method(Op.CALL_C_INT));
791 method.put(Op.MH_I_MANY, method(Op.CALL_I_MANY));
792 method.put(Op.MH_C_MANY, method(Op.CALL_C_MANY));
793
794 method.put(Op.REF_I_INT, method(Op.CALL_I_INT));
795 method.put(Op.REF_C_INT, method(Op.CALL_C_INT));
796 method.put(Op.REF_I_MANY, method(Op.CALL_I_MANY));
797 method.put(Op.REF_C_MANY, method(Op.CALL_C_MANY));
798
799 MethodHandles.Lookup lookup = MethodHandles.lookup();
800
801 handle.put(Op.MH_I_INT, lookup.unreflect(method(Op.CALL_I_INT)));
802 handle.put(Op.MH_C_INT, lookup.unreflect(method(Op.CALL_C_INT)));
803 handle.put(Op.MH_I_MANY, lookup.unreflect(method(Op.CALL_I_MANY)));
804 handle.put(Op.MH_C_MANY, lookup.unreflect(method(Op.CALL_C_MANY)));
805 } catch (ReflectiveOperationException e) {
806 throw new AssertionError(e);
807 }
808 }
809
810 @DontInline void preYield() { captureStack(); }
811 @DontInline void postYield(boolean yieldResult) { verifyPin(yieldResult); verifyStack(); }
812 @DontInline void maybeResetIndex(int index0) { this.index = current() != Op.YIELD ? index0 : index; }
813 @DontInline void throwException() { throw new FuzzException("EX"); }
814
815 @Override
816 public void run() {
817 final int depth = 0;
818 int res = 3;
819
820 int x1 = (int)res, x2 = (int)res, x3 = (int)res, x4 = (int)res;
821 double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res;
822 long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res;
823 float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res;
824 Object o1 = res, o2 = res, o3 = res, o4 = res;
825 SmallValue sv = new SmallValue(res);
826 LargeValue lv = new LargeValue(res);
827 OopsValue ov = new OopsValue(res);
828 DoubleValue dv = new DoubleValue((double)res);
829 MixedValue mv = new MixedValue(res);
830
831 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
832 switch (next(c)) {
833 case THROW -> throwException();
834 case LOOP -> { c += 2; index0 = index; }
835 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
836 case DONE -> { break; }
837 case CALL_I_INT -> res += int_int(depth+1, (int)res);
838 case CALL_C_INT -> res += com_int(depth+1, (int)res);
839 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
840 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
841 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
842 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
843 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
844 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
845 case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
846 case CALL_C_MANY -> res += com_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
847 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
848 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
849 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
850 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
851 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
852 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
853 default -> throw new AssertionError("Unknown op: " + current());
854 }
855 }
856
857 this.result = log(res);
858 }
859
860 @DontInline
861 int int_int(final int depth, int x) {
862 int res = x;
863
864 int x1 = (int)res, x2 = (int)res, x3 = (int)res, x4 = (int)res;
865 double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res;
866 long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res;
867 float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res;
868 Object o1 = res, o2 = res, o3 = res, o4 = res;
869 SmallValue sv = new SmallValue(x);
870 LargeValue lv = new LargeValue(x);
871 OopsValue ov = new OopsValue(x);
872 DoubleValue dv = new DoubleValue((double)x);
873 MixedValue mv = new MixedValue(x);
874
875 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
876 switch (next(c)) {
877 case THROW -> throwException();
878 case LOOP -> { c += 2; index0 = index; }
879 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
880 case DONE -> { break; }
881 case CALL_I_INT -> res += int_int(depth+1, (int)res);
882 case CALL_C_INT -> res += com_int(depth+1, (int)res);
883 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
884 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
885 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
886 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
887 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
888 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
889 case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
890 case CALL_C_MANY -> res += com_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
891 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
892 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
893 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
894 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
895 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
896 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
897 default -> throw new AssertionError("Unknown op: " + current());
898 }
899 }
900
901 return log(res);
902 }
903
904 @DontInline
905 int com_int(final int depth, int x) {
906 int res = x;
907
908 int x1 = (int)res, x2 = (int)res, x3 = (int)res, x4 = (int)res;
909 double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res;
910 long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res;
911 float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res;
912 Object o1 = res, o2 = res, o3 = res, o4 = res;
913 SmallValue sv = new SmallValue(x);
914 LargeValue lv = new LargeValue(x);
915 OopsValue ov = new OopsValue(x);
916 DoubleValue dv = new DoubleValue((double)x);
917 MixedValue mv = new MixedValue(x);
918
919 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
920 switch (next(c)) {
921 case THROW -> throwException();
922 case LOOP -> { c += 2; index0 = index; }
923 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
924 case DONE -> { break; }
925 case CALL_I_INT -> res += int_int(depth+1, (int)res);
926 case CALL_C_INT -> res += com_int(depth+1, (int)res);
927 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
928 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
929 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
930 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
931 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
932 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
933 case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
934 case CALL_C_MANY -> res += com_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
935 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
936 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
937 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
938 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
939 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
940 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
941 default -> throw new AssertionError("Unknown op: " + current());
942 }
943 }
944
945 return log(res);
946 }
947
948 @DontInline
949 double int_dbl(final int depth, double x) {
950 double res = 3.0;
951
952 int x1 = (int)res, x2 = (int)res, x3 = (int)res, x4 = (int)res;
953 double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res;
954 long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res;
955 float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res;
956 Object o1 = res, o2 = res, o3 = res, o4 = res;
957 SmallValue sv = new SmallValue(x1);
958 LargeValue lv = new LargeValue(x1);
959 OopsValue ov = new OopsValue(x1);
960 DoubleValue dv = new DoubleValue((double)x1);
961 MixedValue mv = new MixedValue(x1);
962
963 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
964 switch (next(c)) {
965 case THROW -> throwException();
966 case LOOP -> { c += 2; index0 = index; }
967 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
968 case DONE -> { break; }
969 case CALL_I_INT -> res += int_int(depth+1, (int)res);
970 case CALL_C_INT -> res += com_int(depth+1, (int)res);
971 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
972 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
973 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
974 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
975 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
976 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
977 case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
978 case CALL_C_MANY -> res += com_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
979 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
980 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
981 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
982 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
983 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
984 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
985 default -> throw new AssertionError("Unknown op: " + current());
986 }
987 }
988
989 return log(res);
990 }
991
992 @DontInline
993 double com_dbl(final int depth, double x) {
994 double res = 3.0;
995
996 int x1 = (int)res, x2 = (int)res, x3 = (int)res, x4 = (int)res;
997 double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res;
998 long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res;
999 float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res;
1000 Object o1 = res, o2 = res, o3 = res, o4 = res;
1001 SmallValue sv = new SmallValue(x1);
1002 LargeValue lv = new LargeValue(x1);
1003 OopsValue ov = new OopsValue(x1);
1004 DoubleValue dv = new DoubleValue((double)x1);
1005 MixedValue mv = new MixedValue(x1);
1006
1007 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
1008 switch (next(c)) {
1009 case THROW -> throwException();
1010 case LOOP -> { c += 2; index0 = index; }
1011 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
1012 case DONE -> { break; }
1013 case CALL_I_INT -> res += int_int(depth+1, (int)res);
1014 case CALL_C_INT -> res += com_int(depth+1, (int)res);
1015 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
1016 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
1017 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
1018 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
1019 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
1020 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
1021 case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
1022 case CALL_C_MANY -> res += com_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
1023 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
1024 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
1025 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
1026 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
1027 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1028 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1029 default -> throw new AssertionError("Unknown op: " + current());
1030 }
1031 }
1032
1033 return log(res);
1034 }
1035
1036 @DontInline
1037 BaseValue int_val(final int depth, SmallValue x1, LargeValue x2, OopsValue x3, DoubleValue x4, MixedValue x5) {
1038 int res = x1.res();
1039
1040 int x11 = (int)res, x12 = (int)res, x13 = (int)res, x14 = (int)res;
1041 double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res;
1042 long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res;
1043 float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res;
1044 Object o1 = res, o2 = res, o3 = res, o4 = res;
1045 SmallValue sv = new SmallValue(res);
1046 LargeValue lv = new LargeValue(res);
1047 OopsValue ov = new OopsValue(res);
1048 DoubleValue dv = new DoubleValue((double)res);
1049 MixedValue mv = new MixedValue(res);
1050
1051 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
1052 switch (next(c)) {
1053 case THROW -> throwException();
1054 case LOOP -> { c += 2; index0 = index; }
1055 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
1056 case DONE -> { break; }
1057 case CALL_I_INT -> res += int_int(depth+1, (int)res);
1058 case CALL_C_INT -> res += com_int(depth+1, (int)res);
1059 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
1060 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
1061 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
1062 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
1063 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
1064 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
1065 case CALL_I_MANY -> res += int_mny(depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4);
1066 case CALL_C_MANY -> res += com_mny(depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4);
1067 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
1068 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
1069 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
1070 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
1071 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1072 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1073 default -> throw new AssertionError("Unknown op: " + current());
1074 }
1075 }
1076
1077 int positiveRes = (res == Integer.MIN_VALUE) ? Integer.MAX_VALUE : Math.abs(res);
1078 switch (positiveRes % 5) {
1079 case 0 -> { return log(new SmallValue(res)); }
1080 case 1 -> { return log(new LargeValue(res)); }
1081 case 2 -> { return log(new OopsValue(res)); }
1082 case 3 -> { return log(new DoubleValue((double)res)); }
1083 case 4 -> { return log(new MixedValue(res)); }
1084 default -> throw new AssertionError("Invalid case");
1085 }
1086 }
1087
1088 @DontInline
1089 BaseValue com_val(final int depth, SmallValue x1, LargeValue x2, OopsValue x3, DoubleValue x4, MixedValue x5) {
1090 int res = x1.res();
1091
1092 int x11 = (int)res, x12 = (int)res, x13 = (int)res, x14 = (int)res;
1093 double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res;
1094 long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res;
1095 float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res;
1096 Object o1 = res, o2 = res, o3 = res, o4 = res;
1097 SmallValue sv = new SmallValue(res);
1098 LargeValue lv = new LargeValue(res);
1099 OopsValue ov = new OopsValue(res);
1100 DoubleValue dv = new DoubleValue((double)res);
1101 MixedValue mv = new MixedValue(res);
1102
1103 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
1104 switch (next(c)) {
1105 case THROW -> throwException();
1106 case LOOP -> { c += 2; index0 = index; }
1107 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
1108 case DONE -> { break; }
1109 case CALL_I_INT -> res += int_int(depth+1, (int)res);
1110 case CALL_C_INT -> res += com_int(depth+1, (int)res);
1111 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
1112 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
1113 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
1114 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
1115 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
1116 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
1117 case CALL_I_MANY -> res += int_mny(depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4);
1118 case CALL_C_MANY -> res += com_mny(depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4);
1119 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
1120 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
1121 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
1122 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
1123 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1124 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x11, d1, l1, f1, o1, x12, d2, l2, f2, o2, x13, d3, l3, f3, o3, x14, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1125 default -> throw new AssertionError("Unknown op: " + current());
1126 }
1127 }
1128
1129 int positiveRes = (res == Integer.MIN_VALUE) ? Integer.MAX_VALUE : Math.abs(res);
1130 switch (positiveRes % 5) {
1131 case 0 -> { return log(new SmallValue(res)); }
1132 case 1 -> { return log(new LargeValue(res)); }
1133 case 2 -> { return log(new OopsValue(res)); }
1134 case 3 -> { return log(new DoubleValue((double)res)); }
1135 case 4 -> { return log(new MixedValue(res)); }
1136 default -> throw new AssertionError("Invalid case");
1137 }
1138 }
1139
1140 @DontInline
1141 int int_pin(final int depth, int x) {
1142 int res = x;
1143
1144 int x1 = (int)res, x2 = (int)res, x3 = (int)res, x4 = (int)res;
1145 double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res;
1146 long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res;
1147 float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res;
1148 Object o1 = res, o2 = res, o3 = res, o4 = res;
1149 SmallValue sv = new SmallValue(x);
1150 LargeValue lv = new LargeValue(x);
1151 OopsValue ov = new OopsValue(x);
1152 DoubleValue dv = new DoubleValue((double)x);
1153 MixedValue mv = new MixedValue(x);
1154
1155 synchronized (this) {
1156
1157 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
1158 switch (next(c)) {
1159 case THROW -> throwException();
1160 case LOOP -> { c += 2; index0 = index; }
1161 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
1162 case DONE -> { break; }
1163 case CALL_I_INT -> res += int_int(depth+1, (int)res);
1164 case CALL_C_INT -> res += com_int(depth+1, (int)res);
1165 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
1166 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
1167 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
1168 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
1169 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
1170 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
1171 case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
1172 case CALL_C_MANY -> res += com_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
1173 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
1174 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
1175 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
1176 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
1177 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1178 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1179 default -> throw new AssertionError("Unknown op: " + current());
1180 }
1181 }
1182
1183 }
1184
1185 return log(res);
1186 }
1187
1188 @DontInline
1189 int com_pin(final int depth, int x) {
1190 int res = x;
1191
1192 int x1 = (int)res, x2 = (int)res, x3 = (int)res, x4 = (int)res;
1193 double d1 = (double)res, d2 = (double)res, d3 = (double)res, d4 = (double)res;
1194 long l1 = (long)res, l2 = (long)res, l3 = (long)res, l4 = (long)res;
1195 float f1 = (float)res, f2 = (float)res, f3 = (float)res, f4 = (float)res;
1196 Object o1 = res, o2 = res, o3 = res, o4 = res;
1197 SmallValue sv = new SmallValue(x);
1198 LargeValue lv = new LargeValue(x);
1199 OopsValue ov = new OopsValue(x);
1200 DoubleValue dv = new DoubleValue((double)x);
1201 MixedValue mv = new MixedValue(x);
1202
1203 synchronized (this) {
1204
1205 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
1206 switch (next(c)) {
1207 case THROW -> throwException();
1208 case LOOP -> { c += 2; index0 = index; }
1209 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
1210 case DONE -> { break; }
1211 case CALL_I_INT -> res += int_int(depth+1, (int)res);
1212 case CALL_C_INT -> res += com_int(depth+1, (int)res);
1213 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
1214 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
1215 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
1216 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
1217 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
1218 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
1219 case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
1220 case CALL_C_MANY -> res += com_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
1221 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
1222 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
1223 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
1224 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
1225 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1226 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1227 default -> throw new AssertionError("Unknown op: " + current());
1228 }
1229 }
1230
1231 }
1232
1233 return log(res);
1234 }
1235
1236 @DontInline
1237 int int_mny(int depth,
1238 int x1, double d1, long l1, float f1, Object o1,
1239 int x2, double d2, long l2, float f2, Object o2,
1240 int x3, double d3, long l3, float f3, Object o3,
1241 int x4, double d4, long l4, float f4, Object o4) {
1242
1243 double res = x1 + d2 + f3 + l4 + (double)(o4 instanceof Double ? (Double)o4 : (Integer)o4);
1244 SmallValue sv = new SmallValue(x1);
1245 LargeValue lv = new LargeValue(x1);
1246 OopsValue ov = new OopsValue(x1);
1247 DoubleValue dv = new DoubleValue((double)x1);
1248 MixedValue mv = new MixedValue(x1);
1249
1250 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
1251 switch (next(c)) {
1252 case THROW -> throwException();
1253 case LOOP -> { c += 2; index0 = index; }
1254 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
1255 case DONE -> { break; }
1256 case CALL_I_INT -> res += int_int(depth+1, (int)res);
1257 case CALL_C_INT -> res += com_int(depth+1, (int)res);
1258 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
1259 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
1260 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
1261 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
1262 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
1263 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
1264 case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
1265 case CALL_C_MANY -> res += com_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
1266 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
1267 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
1268 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
1269 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
1270 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1271 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1272 default -> throw new AssertionError("Unknown op: " + current());
1273 }
1274 }
1275
1276 return log((int)res);
1277 }
1278
1279 @DontInline
1280 int com_mny(int depth,
1281 int x1, double d1, long l1, float f1, Object o1,
1282 int x2, double d2, long l2, float f2, Object o2,
1283 int x3, double d3, long l3, float f3, Object o3,
1284 int x4, double d4, long l4, float f4, Object o4) {
1285
1286 double res = x1 + d2 + f3 + l4 + (double)(o4 instanceof Double ? (Double)o4 : (Integer)o4);
1287 SmallValue sv = new SmallValue(x1);
1288 LargeValue lv = new LargeValue(x1);
1289 OopsValue ov = new OopsValue(x1);
1290 DoubleValue dv = new DoubleValue((double)x1);
1291 MixedValue mv = new MixedValue(x1);
1292
1293 for (int c = 1, index0 = index; c > 0; c--, maybeResetIndex(index0)) { // index0 is the index to which we return when we loop
1294 switch (next(c)) {
1295 case THROW -> throwException();
1296 case LOOP -> { c += 2; index0 = index; }
1297 case YIELD -> { preYield(); boolean y = Continuation.yield(SCOPE); postYield(y); c++; }
1298 case DONE -> { break; }
1299 case CALL_I_INT -> res += int_int(depth+1, (int)res);
1300 case CALL_C_INT -> res += com_int(depth+1, (int)res);
1301 case CALL_I_DBL -> res += (int)int_dbl(depth+1, res);
1302 case CALL_C_DBL -> res += (int)com_dbl(depth+1, res);
1303 case CALL_I_VAL -> res += int_val(depth+1, sv, lv, ov, dv, mv).res();
1304 case CALL_C_VAL -> res += com_val(depth+1, sv, lv, ov, dv, mv).res();
1305 case CALL_I_PIN -> res += int_pin(depth+1, (int)res);
1306 case CALL_C_PIN -> res += com_pin(depth+1, (int)res);
1307 case CALL_I_MANY -> res += int_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
1308 case CALL_C_MANY -> res += com_mny(depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4);
1309 case CALL_I_CTCH -> {try { res += int_int(depth+1, (int)res); } catch (FuzzException e) {}}
1310 case CALL_C_CTCH -> {try { res += com_int(depth+1, (int)res); } catch (FuzzException e) {}}
1311 case MH_I_INT, MH_C_INT -> {try { res += (int)handle(current()).invokeExact(this, depth+1, (int)res); } catch (Throwable e) { rethrow(e); }}
1312 case MH_I_MANY, MH_C_MANY -> {try { res += (int)handle(current()).invokeExact(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (Throwable e) { rethrow(e); }}
1313 case REF_I_INT, REF_C_INT -> {try { res += (int)method(current()).invoke(this, depth+1, (int)res); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1314 case REF_I_MANY, REF_C_MANY -> {try { res += (int)method(current()).invoke(this, depth+1, x1, d1, l1, f1, o1, x2, d2, l2, f2, o2, x3, d3, l3, f3, o3, x4, d4, l4, f4, o4); } catch (InvocationTargetException e) { rethrow(e.getCause()); } catch (IllegalAccessException e) { assert false; }}
1315 default -> throw new AssertionError("Unknown op: " + current());
1316 }
1317 }
1318
1319 return log((int)res);
1320 }
1321 }