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