|
315 | 315 | import com.oracle.truffle.espresso.classfile.attributes.BootstrapMethodsAttribute;
|
316 | 316 | import com.oracle.truffle.espresso.classfile.attributes.LineNumberTableAttribute;
|
317 | 317 | import com.oracle.truffle.espresso.classfile.constantpool.ClassConstant;
|
318 |
| -import com.oracle.truffle.espresso.classfile.constantpool.ClassMethodRefConstant; |
319 | 318 | import com.oracle.truffle.espresso.classfile.constantpool.DoubleConstant;
|
320 | 319 | import com.oracle.truffle.espresso.classfile.constantpool.DynamicConstant;
|
321 | 320 | import com.oracle.truffle.espresso.classfile.constantpool.FloatConstant;
|
|
376 | 375 | import com.oracle.truffle.espresso.nodes.quick.invoke.InvokeVirtualQuickNode;
|
377 | 376 | import com.oracle.truffle.espresso.nodes.quick.invoke.inline.InlinedMethodNode;
|
378 | 377 | import com.oracle.truffle.espresso.perf.DebugCounter;
|
| 378 | +import com.oracle.truffle.espresso.resolver.CallKind; |
| 379 | +import com.oracle.truffle.espresso.resolver.CallSiteType; |
| 380 | +import com.oracle.truffle.espresso.resolver.LinkResolver; |
| 381 | +import com.oracle.truffle.espresso.resolver.ResolvedCall; |
379 | 382 | import com.oracle.truffle.espresso.runtime.EspressoContext;
|
380 | 383 | import com.oracle.truffle.espresso.runtime.EspressoException;
|
381 | 384 | import com.oracle.truffle.espresso.runtime.EspressoExitException;
|
@@ -2394,141 +2397,38 @@ private int quickenArrayStore(final VirtualFrame frame, int top, int curBCI, int
|
2394 | 2397 | // endregion quickenForeign
|
2395 | 2398 |
|
2396 | 2399 | private InvokeQuickNode dispatchQuickened(int top, int curBCI, char cpi, int opcode, int statementIndex, Method resolutionSeed, boolean allowBytecodeInlining) {
|
2397 |
| - Method resolved = resolutionSeed; |
2398 |
| - int resolvedOpCode = opcode; |
2399 |
| - switch (opcode) { |
2400 |
| - case INVOKESTATIC: |
2401 |
| - // Otherwise, if the resolved method is an instance method, the invokestatic |
2402 |
| - // instruction throws an IncompatibleClassChangeError. |
2403 |
| - if (!resolved.isStatic()) { |
2404 |
| - enterLinkageExceptionProfile(); |
2405 |
| - throw throwBoundary(getMethod().getMeta().java_lang_IncompatibleClassChangeError, "Expected static method '%s.%s%s'", |
2406 |
| - resolved.getDeclaringKlass().getName(), |
2407 |
| - resolved.getName(), |
2408 |
| - resolved.getRawSignature()); |
2409 |
| - } |
2410 |
| - break; |
2411 |
| - case INVOKEINTERFACE: |
2412 |
| - // Otherwise, if the resolved method is static or (jdk8 or earlier) private, the |
2413 |
| - // invokeinterface instruction throws an IncompatibleClassChangeError. |
2414 |
| - if (resolved.isStatic() || |
2415 |
| - (getMethod().getContext().getJavaVersion().java8OrEarlier() && resolved.isPrivate())) { |
2416 |
| - enterLinkageExceptionProfile(); |
2417 |
| - throw throwBoundary(getMethod().getMeta().java_lang_IncompatibleClassChangeError, "Expected instance method '%s.%s%s'", |
2418 |
| - resolved.getDeclaringKlass().getName(), |
2419 |
| - resolved.getName(), |
2420 |
| - resolved.getRawSignature()); |
2421 |
| - } |
2422 |
| - if (resolved.getITableIndex() < 0) { |
2423 |
| - if (resolved.isPrivate()) { |
2424 |
| - assert getJavaVersion().java9OrLater(); |
2425 |
| - // Interface private methods do not appear in itables. |
2426 |
| - resolvedOpCode = INVOKESPECIAL; |
2427 |
| - } else { |
2428 |
| - // Can happen in old classfiles that calls j.l.Object on interfaces. |
2429 |
| - resolvedOpCode = INVOKEVIRTUAL; |
2430 |
| - } |
2431 |
| - } |
2432 |
| - break; |
2433 |
| - case INVOKEVIRTUAL: |
2434 |
| - // Otherwise, if the resolved method is a class (static) method, the invokevirtual |
2435 |
| - // instruction throws an IncompatibleClassChangeError. |
2436 |
| - if (resolved.isStatic()) { |
2437 |
| - enterLinkageExceptionProfile(); |
2438 |
| - throw throwBoundary(getMethod().getMeta().java_lang_IncompatibleClassChangeError, "Expected instance not static method '%s.%s%s'", |
2439 |
| - resolved.getDeclaringKlass().getName(), |
2440 |
| - resolved.getName(), |
2441 |
| - resolved.getRawSignature()); |
2442 |
| - } |
2443 |
| - if (resolved.isFinalFlagSet() || resolved.getDeclaringKlass().isFinalFlagSet() || resolved.isPrivate()) { |
2444 |
| - resolvedOpCode = INVOKESPECIAL; |
2445 |
| - } |
2446 |
| - break; |
2447 |
| - case INVOKESPECIAL: |
2448 |
| - // Otherwise, if the resolved method is an instance initialization method, and the |
2449 |
| - // class in which it is declared is not the class symbolically referenced by the |
2450 |
| - // instruction, a NoSuchMethodError is thrown. |
2451 |
| - if (resolved.isConstructor()) { |
2452 |
| - if (resolved.getDeclaringKlass().getName() != getConstantPool().methodAt(cpi).getHolderKlassName(getConstantPool())) { |
2453 |
| - enterLinkageExceptionProfile(); |
2454 |
| - throw throwBoundary(getMethod().getMeta().java_lang_NoSuchMethodError, |
2455 |
| - "%s.%s%s", |
2456 |
| - resolved.getDeclaringKlass().getName(), |
2457 |
| - resolved.getName(), |
2458 |
| - resolved.getRawSignature()); |
2459 |
| - } |
2460 |
| - } |
2461 |
| - // Otherwise, if the resolved method is a class (static) method, the invokespecial |
2462 |
| - // instruction throws an IncompatibleClassChangeError. |
2463 |
| - if (resolved.isStatic()) { |
2464 |
| - enterLinkageExceptionProfile(); |
2465 |
| - throw throwBoundary(getMethod().getMeta().java_lang_IncompatibleClassChangeError, "Expected instance not static method '%s.%s%s'", |
2466 |
| - resolved.getDeclaringKlass().getName(), |
2467 |
| - resolved.getName(), |
2468 |
| - resolved.getRawSignature()); |
2469 |
| - } |
2470 |
| - // If all of the following are true, let C be the direct superclass of the current |
2471 |
| - // class: |
2472 |
| - // |
2473 |
| - // * The resolved method is not an instance initialization method (§2.9). |
2474 |
| - // |
2475 |
| - // * If the symbolic reference names a class (not an interface), then that class is |
2476 |
| - // a superclass of the current class. |
2477 |
| - // |
2478 |
| - // * The ACC_SUPER flag is set for the class file (§4.1). In Java SE 8 and |
2479 |
| - // above, the Java Virtual Machine considers the ACC_SUPER flag to be set in every |
2480 |
| - // class file, regardless of the actual value of the flag in the class file and the |
2481 |
| - // version of the class file. |
2482 |
| - if (!resolved.isConstructor()) { |
2483 |
| - ObjectKlass declaringKlass = getMethod().getDeclaringKlass(); |
2484 |
| - Klass symbolicRef = ((MethodRefConstant.Indexes) getConstantPool().methodAt(cpi)).getResolvedHolderKlass(declaringKlass, getConstantPool()); |
2485 |
| - if (!symbolicRef.isInterface() && |
2486 |
| - symbolicRef != declaringKlass && |
2487 |
| - declaringKlass.getSuperKlass() != null && |
2488 |
| - symbolicRef != declaringKlass.getSuperKlass() && |
2489 |
| - symbolicRef.isAssignableFrom(declaringKlass)) { |
2490 |
| - resolved = declaringKlass.getSuperKlass().lookupMethod(resolved.getName(), resolved.getRawSignature(), Klass.LookupMode.INSTANCE_ONLY); |
2491 |
| - } |
2492 |
| - } |
2493 |
| - break; |
2494 |
| - default: |
2495 |
| - CompilerDirectives.transferToInterpreterAndInvalidate(); |
2496 |
| - throw EspressoError.unimplemented("Quickening for " + Bytecodes.nameOf(opcode)); |
2497 |
| - } |
| 2400 | + |
| 2401 | + Klass symbolicRef = ((MethodRefConstant.Indexes) getConstantPool().methodAt(cpi)).getResolvedHolderKlass(getDeclaringKlass(), getConstantPool()); |
| 2402 | + ResolvedCall resolvedCall = LinkResolver.resolveCallSite(getMeta(), getDeclaringKlass(), resolutionSeed, CallSiteType.fromOpCode(opcode), symbolicRef); |
| 2403 | + |
| 2404 | + Method resolved = resolvedCall.getResolvedMethod(); |
| 2405 | + CallKind callKind = resolvedCall.getCallKind(); |
2498 | 2406 |
|
2499 | 2407 | // Skip inlined nodes if instrumentation is live.
|
2500 | 2408 | // Lock must be owned for correctness.
|
2501 | 2409 | assert lockIsHeld();
|
2502 | 2410 | boolean tryBytecodeLevelInlining = this.instrumentation == null && allowBytecodeInlining;
|
2503 | 2411 | if (tryBytecodeLevelInlining) {
|
2504 |
| - var node = InlinedMethodNode.createFor(resolved, top, resolvedOpCode, curBCI, statementIndex); |
| 2412 | + InlinedMethodNode node = InlinedMethodNode.createFor(resolvedCall, top, opcode, curBCI, statementIndex); |
2505 | 2413 | if (node != null) {
|
2506 | 2414 | return node;
|
2507 | 2415 | }
|
2508 | 2416 | }
|
2509 | 2417 |
|
2510 |
| - InvokeQuickNode invoke; |
2511 | 2418 | if (resolved.isPolySignatureIntrinsic()) {
|
2512 |
| - MethodHandleInvoker invoker = null; |
2513 |
| - if ((resolvedOpCode == INVOKEVIRTUAL || resolvedOpCode == INVOKESPECIAL) && (getConstantPool().resolvedMethodRefAt(getDeclaringKlass(), cpi) instanceof ClassMethodRefConstant methodRef)) { |
2514 |
| - // There might be an invoker if it's an InvokeGeneric |
2515 |
| - invoker = methodRef.invoker(); |
2516 |
| - } |
2517 |
| - invoke = new InvokeHandleNode(resolved, invoker, top, curBCI); |
| 2419 | + MethodHandleInvoker invoker = getConstantPool().resolvedMethodRefAt(getDeclaringKlass(), cpi).invoker(); |
| 2420 | + assert invoker == null || ((opcode == INVOKEVIRTUAL || opcode == INVOKESPECIAL) && resolved.isInvokeIntrinsic()); |
| 2421 | + return new InvokeHandleNode(resolved, invoker, top, curBCI); |
2518 | 2422 | } else {
|
2519 | 2423 | // @formatter:off
|
2520 |
| - switch (resolvedOpCode) { |
2521 |
| - case INVOKESTATIC : invoke = new InvokeStaticQuickNode(resolved, top, curBCI); break; |
2522 |
| - case INVOKEINTERFACE : invoke = new InvokeInterfaceQuickNode(resolved, top, curBCI); break; |
2523 |
| - case INVOKEVIRTUAL : invoke = new InvokeVirtualQuickNode(resolved, top, curBCI); break; |
2524 |
| - case INVOKESPECIAL : invoke = new InvokeSpecialQuickNode(resolved, top, curBCI); break; |
2525 |
| - default : |
2526 |
| - CompilerDirectives.transferToInterpreterAndInvalidate(); |
2527 |
| - throw EspressoError.unimplemented("Quickening for " + Bytecodes.nameOf(resolvedOpCode)); |
2528 |
| - } |
| 2424 | + return switch (callKind) { |
| 2425 | + case STATIC -> new InvokeStaticQuickNode(resolved, top, curBCI); |
| 2426 | + case ITABLE_LOOKUP -> new InvokeInterfaceQuickNode(resolved, top, curBCI); |
| 2427 | + case VTABLE_LOOKUP -> new InvokeVirtualQuickNode(resolved, top, curBCI); |
| 2428 | + case DIRECT -> new InvokeSpecialQuickNode(resolved, top, curBCI); |
| 2429 | + }; |
2529 | 2430 | // @formatter:on
|
2530 | 2431 | }
|
2531 |
| - return invoke; |
2532 | 2432 | }
|
2533 | 2433 |
|
2534 | 2434 | @TruffleBoundary
|
|
0 commit comments