Skip to content

Commit

Permalink
8286669: Replace MethodHandle specialization with ASM in mainline
Browse files Browse the repository at this point in the history
Co-authored-by: Jorn Vernee <jvernee@openjdk.org>
Co-authored-by: Maurizio Cimadamore <mcimadamore@openjdk.org>
Reviewed-by: mcimadamore
  • Loading branch information
JornVernee and mcimadamore committed May 18, 2022
1 parent d8b0b32 commit ee45a0a
Show file tree
Hide file tree
Showing 24 changed files with 1,482 additions and 785 deletions.
16 changes: 10 additions & 6 deletions src/hotspot/share/code/codeBlob.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ struct CodeBlobType {

class CodeBlobLayout;
class OptimizedEntryBlob; // for as_optimized_entry_blob()
class RuntimeStub; // for as_runtime_stub()
class JavaFrameAnchor; // for OptimizedEntryBlob::jfa_for_frame

class CodeBlob {
Expand Down Expand Up @@ -164,12 +165,13 @@ class CodeBlob {
CompilerType compiler_type() const { return _type; }

// Casting
nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }
nmethod* as_nmethod() { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; }
CompiledMethod* as_compiled_method_or_null() { return is_compiled() ? (CompiledMethod*) this : NULL; }
CompiledMethod* as_compiled_method() { assert(is_compiled(), "must be compiled"); return (CompiledMethod*) this; }
CodeBlob* as_codeblob_or_null() const { return (CodeBlob*) this; }
OptimizedEntryBlob* as_optimized_entry_blob() const { assert(is_optimized_entry_blob(), "must be entry blob"); return (OptimizedEntryBlob*) this; }
nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }
nmethod* as_nmethod() { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; }
CompiledMethod* as_compiled_method_or_null() { return is_compiled() ? (CompiledMethod*) this : NULL; }
CompiledMethod* as_compiled_method() { assert(is_compiled(), "must be compiled"); return (CompiledMethod*) this; }
CodeBlob* as_codeblob_or_null() const { return (CodeBlob*) this; }
OptimizedEntryBlob* as_optimized_entry_blob() const { assert(is_optimized_entry_blob(), "must be entry blob"); return (OptimizedEntryBlob*) this; }
RuntimeStub* as_runtime_stub() const { assert(is_runtime_stub(), "must be runtime blob"); return (RuntimeStub*) this; }

// Boundaries
address header_begin() const { return (address) this; }
Expand Down Expand Up @@ -521,6 +523,8 @@ class RuntimeStub: public RuntimeBlob {
bool caller_must_gc_arguments
);

static void free(RuntimeStub* stub) { RuntimeBlob::free(stub); }

// Typing
bool is_runtime_stub() const { return true; }

Expand Down
11 changes: 11 additions & 0 deletions src/hotspot/share/prims/nativeEntryPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ JNI_ENTRY(jlong, NEP_makeInvoker(JNIEnv* env, jclass _unused, jobject method_typ
basic_type, pslots, ret_bt, abi, input_regs, output_regs, needs_return_buffer)->code_begin();
JNI_END

JNI_ENTRY(jboolean, NEP_freeInvoker(JNIEnv* env, jclass _unused, jlong invoker))
// safe to call without code cache lock, because stub is always alive
CodeBlob* cb = CodeCache::find_blob((char*) invoker);
if (cb == nullptr) {
return false;
}
RuntimeStub::free(cb->as_runtime_stub());
return true;
JNI_END

#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
#define METHOD_TYPE "Ljava/lang/invoke/MethodType;"
Expand All @@ -85,6 +95,7 @@ JNI_END

static JNINativeMethod NEP_methods[] = {
{CC "makeInvoker", CC "(" METHOD_TYPE ABI_DESC VM_STORAGE_ARR VM_STORAGE_ARR "Z)J", FN_PTR(NEP_makeInvoker)},
{CC "freeInvoker0", CC "(J)Z", FN_PTR(NEP_freeInvoker)},
};

#undef METHOD_TYPE
Expand Down
13 changes: 5 additions & 8 deletions src/java.base/share/classes/java/lang/foreign/Linker.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,15 @@
*/
package java.lang.foreign;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;

import jdk.internal.foreign.abi.AbstractLinker;
import jdk.internal.foreign.abi.SharedUtils;
import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker;
import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker;
import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker;
import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker;
import jdk.internal.javac.PreviewFeature;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;

/**
* A linker provides access to foreign functions from Java code, and access to Java code from foreign functions.
* <p>
Expand Down Expand Up @@ -148,7 +145,7 @@
* @since 19
*/
@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
public sealed interface Linker permits Windowsx64Linker, SysVx64Linker, LinuxAArch64Linker, MacOsAArch64Linker {
public sealed interface Linker permits AbstractLinker {

/**
* Returns a linker for the ABI associated with the underlying native platform. The underlying native platform
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.foreign.abi;

import jdk.internal.foreign.SystemLookup;
import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker;
import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker;
import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker;
import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker;

import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.MemorySession;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.util.Objects;

public abstract sealed class AbstractLinker implements Linker permits LinuxAArch64Linker, MacOsAArch64Linker,
SysVx64Linker, Windowsx64Linker {

private final SoftReferenceCache<FunctionDescriptor, MethodHandle> DOWNCALL_CACHE = new SoftReferenceCache<>();

@Override
public MethodHandle downcallHandle(FunctionDescriptor function) {
Objects.requireNonNull(function);

return DOWNCALL_CACHE.get(function, fd -> {
MethodType type = SharedUtils.inferMethodType(fd, false);
MethodHandle handle = arrangeDowncall(type, fd);
handle = SharedUtils.maybeInsertAllocator(handle);
return handle;
});
}
protected abstract MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function);

@Override
public MemorySegment upcallStub(MethodHandle target, FunctionDescriptor function, MemorySession scope) {
Objects.requireNonNull(scope);
Objects.requireNonNull(target);
Objects.requireNonNull(function);
SharedUtils.checkExceptions(target);

MethodType type = SharedUtils.inferMethodType(function, true);
if (!type.equals(target.type())) {
throw new IllegalArgumentException("Wrong method handle type: " + target.type());
}
return arrangeUpcall(target, target.type(), function, scope);
}

protected abstract MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType,
FunctionDescriptor function, MemorySession scope);

@Override
public SystemLookup defaultLookup() {
return SystemLookup.getInstance();
}
}
Loading

1 comment on commit ee45a0a

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.