JDK-8233920 : MethodHandles::tryFinally generates illegal bytecode for long/double return types
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: 11,13,14
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2019-11-11
  • Updated: 2020-07-23
  • Resolved: 2019-11-14
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 13 JDK 14
11.0.10-oracleFixed 13.0.4Fixed 14 b24Fixed
Related Reports
Relates :  
Description
Code to reproduce:

```
package main;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;

public class Main {
    public static void main(String[] args) {
        MethodHandle doubleIdentity = MethodHandles.identity(double.class);		
        MethodHandles.tryFinally(doubleIdentity,
                MethodHandles.dropArguments(doubleIdentity, 0, Throwable.class));
    }
}
```

Run with either `-XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles` to produce:

=============== DEBUG MESSAGE: receiver not on stack ================

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_PRIV_INSTRUCTION (0xc0000096) at pc=0x00000212a403d6e5, pid=26184, tid=20820
#
# JRE version: OpenJDK Runtime Environment (12.0+33) (build 12+33)
# Java VM: OpenJDK 64-Bit Server VM (12+33, mixed mode, sharing, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# v  ~BufferBlob::MethodHandles adapters
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# J:\WS\Oxygen-Stable-New\test\hs_err_pid26184.log
Could not load hsdis-amd64.dll; library not loadable; PrintAssembly is disabled
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#

Or with `-Xverify:all` to get:

Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    java/lang/invoke/LambdaForm$MH.tryFinally(Ljava/lang/Object;D)D @41: swap
  Reason:
    Type double_2nd (current frame, stack[1]) is not assignable to category1 type
  Current Frame:
    bci: @41
    flags: { }
    locals: { 'java/lang/invoke/BoundMethodHandle$Species_LLLL', double, double_2nd, 'java/lang/Object', 'java/lang/Object', 'java/lang/Object', 'java/lang/Object' }
    stack: { double, double_2nd, 'java/lang/invoke/MethodHandle' }
  Bytecode:
    0000000: 2ac0 000e 594b b400 124e 2ab4 0015 3a04
    0000010: 2ab4 0018 3a05 2ab4 001b 3a06 2dc0 001f
    0000020: 27b6 0023 1904 c000 1f5f 015f 27b6 0026
    0000030: a700 1159 1904 c000 1f5f 0e27 b600 2657
    0000040: bfaf                                   
  Exception Handler Table:
    bci [28, 36] => handler: 51
  Stackmap Table:
    full_frame(@51,{Object[#14],Double,Object[#4],Object[#4],Object[#4],Object[#4]},{Object[#29]})
    same_locals_1_stack_item_frame(@65,Double)

	at java.base/jdk.internal.misc.Unsafe.defineAnonymousClass0(Native Method)
	at java.base/jdk.internal.misc.Unsafe.defineAnonymousClass(Unsafe.java:1223)
	at java.base/java.lang.invoke.InvokerBytecodeGenerator.loadAndInitializeInvokerClass(InvokerBytecodeGenerator.java:295)
	at java.base/java.lang.invoke.InvokerBytecodeGenerator.loadMethod(InvokerBytecodeGenerator.java:287)
	at java.base/java.lang.invoke.InvokerBytecodeGenerator.generateCustomizedCode(InvokerBytecodeGenerator.java:693)
	at java.base/java.lang.invoke.LambdaForm.compileToBytecode(LambdaForm.java:871)
	at java.base/java.lang.invoke.LambdaForm.prepare(LambdaForm.java:829)
	at java.base/java.lang.invoke.MethodHandle.<init>(MethodHandle.java:468)
	at java.base/java.lang.invoke.BoundMethodHandle.<init>(BoundMethodHandle.java:54)
	at java.base/java.lang.invoke.BoundMethodHandle$Species_LLLL.<init>(java/lang/invoke/BoundMethodHandle$Species_LLLL)
	at java.base/java.lang.invoke.BoundMethodHandle$Species_LLLL.make(java/lang/invoke/BoundMethodHandle$Species_LLLL)
	at java.base/java.lang.invoke.MethodHandleImpl.makeTryFinally(MethodHandleImpl.java:2140)
	at java.base/java.lang.invoke.MethodHandles.tryFinally(MethodHandles.java:5950)
	at test/main.Main.main(Main.java:9)

See the spec for swap: https://docs.oracle.com/javase/specs/jvms/se13/html/jvms-4.html#jvms-4.10.1.9.swap "A swap instruction is type safe iff one can validly replace two category 1 types, Type1 and Type2, on the incoming operand stack with the types Type2 and Type1 yielding the outgoing type state."

Where:  "Category 1 types occupy a single stack entry" (so, it is not possible to use `swap` with a double or long operand)

Relevant bytecode does this however:

```
      28: aload_3
      29: checkcast     #31                 // class java/lang/invoke/MethodHandle
      32: dload_1
      33: invokevirtual #35                 // Method java/lang/invoke/MethodHandle.invokeBasic:(D)D
      36: aload         4
      38: checkcast     #31                 // class java/lang/invoke/MethodHandle
      41: swap
```
Comments
Fix Request (13u) Fixes the bad bytecode generation. Applies cleanly to 13u, new test fails without the patch, passes with it. Patched JDK passes tier1.
03-06-2020

Fix Request (11u) Fixes the bad bytecode generation. Applies cleanly to 11u, new test fails without the patch, passes with it. Patched JDK passes tier1.
18-03-2020

Introduced in 9 by JDK-8143211.
13-01-2020

URL: https://hg.openjdk.java.net/jdk/jdk/rev/355f4f42dda5 User: redestad Date: 2019-11-14 09:48:27 +0000
14-11-2019