Skip to content

Commit

Permalink
8282191: Implementation of Foreign Function & Memory API (Preview)
Browse files Browse the repository at this point in the history
Reviewed-by: erikj, jvernee, psandoz, dholmes, mchung
  • Loading branch information
mcimadamore committed May 12, 2022
1 parent 3be394e commit 2c5d136
Show file tree
Hide file tree
Showing 303 changed files with 33,450 additions and 9,162 deletions.
3 changes: 1 addition & 2 deletions make/conf/docs-modules.conf
@@ -1,5 +1,5 @@
#
# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2014, 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
Expand Down Expand Up @@ -55,7 +55,6 @@ DOCS_MODULES= \
jdk.jsobject \
jdk.jshell \
jdk.jstatd \
jdk.incubator.foreign \
jdk.localedata \
jdk.management \
jdk.management.agent \
Expand Down
1 change: 0 additions & 1 deletion make/conf/module-loader-map.conf
Expand Up @@ -43,7 +43,6 @@ BOOT_MODULES= \
java.rmi \
java.security.sasl \
java.xml \
jdk.incubator.foreign \
jdk.incubator.vector \
jdk.internal.vm.ci \
jdk.jfr \
Expand Down
17 changes: 16 additions & 1 deletion make/modules/java.base/Lib.gmk
@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 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
Expand Down Expand Up @@ -203,3 +203,18 @@ ifeq ($(call isTargetOs, windows), true)
))
TARGETS += $(COPY_TZMAPPINGS)
endif

################################################################################
# Create system lookup

$(eval $(call SetupJdkLibrary, BUILD_SYSLOOKUPLIB, \
NAME := syslookup, \
CFLAGS := $(CFLAGS_JDKLIB), \
CXXFLAGS := $(CXXFLAGS_JDKLIB), \
LDFLAGS := $(LDFLAGS_JDKLIB), \
LDFLAGS_linux := -Wl$(COMMA)--no-as-needed, \
LIBS := $(LIBCXX), \
LIBS_linux := -lc -lm -ldl, \
))

TARGETS += $(BUILD_SYSLOOKUPLIB)
14 changes: 7 additions & 7 deletions make/modules/java.base/gensrc/GensrcVarHandles.gmk
Expand Up @@ -160,14 +160,14 @@ endef
################################################################################

################################################################################
# Setup a rule for generating a memory access var handle helper classes
# Setup a rule for generating a memory segment var handle view class
# Param 1 - Variable declaration prefix
# Param 2 - Type with first letter capitalized
define GenerateVarHandleMemoryAccess
define GenerateVarHandleMemorySegment

$1_Type := $2

$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/MemoryAccessVarHandle$$($1_Type)Helper.java
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleSegmentAs$$($1_Type)s.java

ifeq ($$($1_Type), Byte)
$1_type := byte
Expand Down Expand Up @@ -248,7 +248,7 @@ define GenerateVarHandleMemoryAccess
$1_ARGS += -KfloatingPoint
endif

$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandleMemoryAccess.java.template $(BUILD_TOOLS_JDK)
$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandleSegmentView.java.template $(BUILD_TOOLS_JDK)
$$(call MakeDir, $$(@D))
$(RM) $$@
$(TOOL_SPP) -nel -K$$($1_type) \
Expand All @@ -272,8 +272,8 @@ $(foreach t, $(VARHANDLES_BYTE_ARRAY_TYPES), \
$(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t)))

# List the types to generate source for, with capitalized first letter
VARHANDLES_MEMORY_ADDRESS_TYPES := Byte Short Char Int Long Float Double
$(foreach t, $(VARHANDLES_MEMORY_ADDRESS_TYPES), \
$(eval $(call GenerateVarHandleMemoryAccess,VAR_HANDLE_MEMORY_ADDRESS_$t,$t)))
VARHANDLES_MEMORY_SEGMENT_TYPES := Byte Short Char Int Long Float Double
$(foreach t, $(VARHANDLES_MEMORY_SEGMENT_TYPES), \
$(eval $(call GenerateVarHandleMemorySegment,VAR_HANDLE_MEMORY_SEGMENT_$t,$t)))

TARGETS += $(GENSRC_VARHANDLES)
62 changes: 0 additions & 62 deletions make/modules/jdk.incubator.foreign/Lib.gmk

This file was deleted.

2 changes: 1 addition & 1 deletion make/test/BuildMicrobenchmark.gmk
Expand Up @@ -91,7 +91,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \
SMALL_JAVA := false, \
CLASSPATH := $(MICROBENCHMARK_CLASSPATH), \
DISABLED_WARNINGS := processing rawtypes cast serial, \
DISABLED_WARNINGS := processing rawtypes cast serial preview, \
SRC := $(MICROBENCHMARK_SRC), \
BIN := $(MICROBENCHMARK_CLASSES), \
JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \
Expand Down
9 changes: 9 additions & 0 deletions make/test/JtregNativeJdk.gmk
Expand Up @@ -69,14 +69,23 @@ ifeq ($(call isTargetOs, windows), true)
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib
BUILD_JDK_JTREG_LIBRARIES_CFLAGS_libAsyncStackWalk := /EHsc
BUILD_JDK_JTREG_LIBRARIES_CFLAGS_libAsyncInvokers := /EHsc
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLinkerInvokerUnnamed := /EHsc
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLinkerInvokerModule := /EHsc
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLoaderLookupInvoker := /EHsc
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libAsyncStackWalk := $(LIBCXX)
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libAsyncInvokers := $(LIBCXX)
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLinkerInvokerUnnamed := $(LIBCXX)
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLinkerInvokerModule := $(LIBCXX)
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLoaderLookupInvoker := $(LIBCXX)
else
BUILD_JDK_JTREG_LIBRARIES_LIBS_libstringPlatformChars := -ljava
BUILD_JDK_JTREG_LIBRARIES_LIBS_libDirectIO := -ljava
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libNativeThread := -pthread
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libAsyncStackWalk := $(LIBCXX) -pthread
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libAsyncInvokers := $(LIBCXX) -pthread
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLinkerInvokerUnnamed := $(LIBCXX) -pthread
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLinkerInvokerModule := $(LIBCXX) -pthread
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLoaderLookupInvoker := $(LIBCXX) -pthread
BUILD_JDK_JTREG_EXCLUDE += exerevokeall.c
ifeq ($(call isTargetOs, linux), true)
BUILD_JDK_JTREG_LIBRARIES_LIBS_libInheritedChannel := -ljava
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/ci/ciField.cpp
Expand Up @@ -225,7 +225,7 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
// Even if general trusting is disabled, trust system-built closures in these packages.
if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke") ||
holder->is_in_package("java/lang/reflect") || holder->is_in_package("jdk/internal/reflect") ||
holder->is_in_package("jdk/internal/foreign") || holder->is_in_package("jdk/incubator/foreign") ||
holder->is_in_package("jdk/internal/foreign") || holder->is_in_package("java/lang/foreign") ||
holder->is_in_package("jdk/internal/vm/vector") || holder->is_in_package("jdk/incubator/vector") ||
holder->is_in_package("java/lang"))
return true;
Expand Down
1 change: 0 additions & 1 deletion src/hotspot/share/code/codeBlob.hpp
Expand Up @@ -764,7 +764,6 @@ class OptimizedEntryBlob: public BufferBlob {
JavaThread* thread;
JNIHandleBlock* old_handles;
JNIHandleBlock* new_handles;
bool should_detach;
};

// defined in frame_ARCH.cpp
Expand Down
25 changes: 11 additions & 14 deletions src/hotspot/share/prims/scopedMemoryAccess.cpp
Expand Up @@ -70,15 +70,13 @@ class CloseScopedMemoryFindOopClosure : public OopClosure {

class CloseScopedMemoryClosure : public HandshakeClosure {
jobject _deopt;
jobject _exception;

public:
jboolean _found;

CloseScopedMemoryClosure(jobject deopt, jobject exception)
: HandshakeClosure("CloseScopedMemory")
, _deopt(deopt)
, _exception(exception)
, _found(false) {}

void do_thread(Thread* thread) {
Expand Down Expand Up @@ -140,12 +138,11 @@ class CloseScopedMemoryClosure : public HandshakeClosure {
};

/*
* This function issues a global handshake operation with all
* Java threads. This is useful for implementing asymmetric
* dekker synchronization schemes, where expensive synchronization
* in performance sensitive common paths, may be shifted to
* a less common slow path instead.
* Top frames containing obj will be deoptimized.
* This function performs a thread-local handshake against all threads running at the time
* the given session (deopt) was closed. If the handshake for a given thread is processed while
* one or more threads is found inside a scoped method (that is, a method inside the ScopedMemoryAccess
* class annotated with the '@Scoped' annotation), and whose local variables mention the session being
* closed (deopt), this method returns false, signalling that the session cannot be closed safely.
*/
JVM_ENTRY(jboolean, ScopedMemoryAccess_closeScope(JNIEnv *env, jobject receiver, jobject deopt, jobject exception))
CloseScopedMemoryClosure cl(deopt, exception);
Expand All @@ -155,26 +152,26 @@ JVM_END

/// JVM_RegisterUnsafeMethods

#define PKG "Ljdk/internal/misc/"
#define PKG_MISC "Ljdk/internal/misc/"
#define PKG_FOREIGN "Ljdk/internal/foreign/"

#define MEMACCESS "ScopedMemoryAccess"
#define SCOPE PKG MEMACCESS "$Scope;"
#define SCOPED_ERR PKG MEMACCESS "$Scope$ScopedAccessError;"
#define SCOPE PKG_FOREIGN "MemorySessionImpl;"

#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)

static JNINativeMethod jdk_internal_misc_ScopedMemoryAccess_methods[] = {
{CC "closeScope0", CC "(" SCOPE SCOPED_ERR ")Z", FN_PTR(ScopedMemoryAccess_closeScope)},
{CC "closeScope0", CC "(" SCOPE ")Z", FN_PTR(ScopedMemoryAccess_closeScope)},
};

#undef CC
#undef FN_PTR

#undef PKG
#undef PKG_MISC
#undef PKG_FOREIGN
#undef MEMACCESS
#undef SCOPE
#undef SCOPED_EXC

// This function is exported, used by NativeLookup.

Expand Down
46 changes: 25 additions & 21 deletions src/hotspot/share/prims/universalUpcallHandler.cpp
Expand Up @@ -36,6 +36,26 @@

extern struct JavaVM_ main_vm;

// When an upcall is invoked from a thread that is not attached to the VM, we need to attach it,
// and then to detach it at some point later. Detaching a thread as soon as the upcall completes
// is suboptimal, as the same thread could later upcall to Java again, at which point the VM would
// create multiple Java views of the same native thread. For this reason, we use thread local storage
// to keep track of the fact that we have attached a native thread to the VM. When the thread local
// storage is destroyed (which happens when the native threads is terminated), we check if the
// storage has an attached thread and, if so, we detach it from the VM.
struct UpcallContext {
Thread* attachedThread;

~UpcallContext() {
if (attachedThread != NULL) {
JavaVM_ *vm = (JavaVM *)(&main_vm);
vm->functions->DetachCurrentThread(vm);
}
}
};

APPROVED_CPP_THREAD_LOCAL UpcallContext threadContext;

void ProgrammableUpcallHandler::upcall_helper(JavaThread* thread, jobject rec, address buff) {
JavaThread* THREAD = thread; // For exception macros.
ThreadInVMfromNative tiv(THREAD);
Expand All @@ -51,30 +71,23 @@ void ProgrammableUpcallHandler::upcall_helper(JavaThread* thread, jobject rec, a
JavaCalls::call_static(&result, upcall_method.klass, upcall_method.name, upcall_method.sig, &args, CATCH);
}

JavaThread* ProgrammableUpcallHandler::maybe_attach_and_get_thread(bool* should_detach) {
JavaThread* ProgrammableUpcallHandler::maybe_attach_and_get_thread() {
JavaThread* thread = JavaThread::current_or_null();
if (thread == nullptr) {
JavaVM_ *vm = (JavaVM *)(&main_vm);
JNIEnv* p_env = nullptr; // unused
jint result = vm->functions->AttachCurrentThread(vm, (void**) &p_env, nullptr);
jint result = vm->functions->AttachCurrentThreadAsDaemon(vm, (void**) &p_env, nullptr);
guarantee(result == JNI_OK, "Could not attach thread for upcall. JNI error code: %d", result);
*should_detach = true;
thread = JavaThread::current();
threadContext.attachedThread = thread;
assert(!thread->has_last_Java_frame(), "newly-attached thread not expected to have last Java frame");
} else {
*should_detach = false;
}
return thread;
}

void ProgrammableUpcallHandler::detach_current_thread() {
JavaVM_ *vm = (JavaVM *)(&main_vm);
vm->functions->DetachCurrentThread(vm);
}

// modelled after JavaCallWrapper::JavaCallWrapper
JavaThread* ProgrammableUpcallHandler::on_entry(OptimizedEntryBlob::FrameData* context) {
JavaThread* thread = maybe_attach_and_get_thread(&context->should_detach);
JavaThread* thread = maybe_attach_and_get_thread();
context->thread = thread;

assert(thread->can_call_java(), "must be able to call Java");
Expand Down Expand Up @@ -132,24 +145,15 @@ void ProgrammableUpcallHandler::on_exit(OptimizedEntryBlob::FrameData* context)
JNIHandleBlock::release_block(context->new_handles, thread);

assert(!thread->has_pending_exception(), "Upcall can not throw an exception");

if (context->should_detach) {
detach_current_thread();
}
}

void ProgrammableUpcallHandler::attach_thread_and_do_upcall(jobject rec, address buff) {
bool should_detach = false;
JavaThread* thread = maybe_attach_and_get_thread(&should_detach);
JavaThread* thread = maybe_attach_and_get_thread();

{
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, thread));
upcall_helper(thread, rec, buff);
}

if (should_detach) {
detach_current_thread();
}
}

const ProgrammableUpcallHandler& ProgrammableUpcallHandler::instance() {
Expand Down
3 changes: 1 addition & 2 deletions src/hotspot/share/prims/universalUpcallHandler.hpp
Expand Up @@ -48,8 +48,7 @@ class ProgrammableUpcallHandler {
static void attach_thread_and_do_upcall(jobject rec, address buff);

static void handle_uncaught_exception(oop exception);
static JavaThread* maybe_attach_and_get_thread(bool* should_detach);
static void detach_current_thread();
static JavaThread* maybe_attach_and_get_thread();

static JavaThread* on_entry(OptimizedEntryBlob::FrameData* context);
static void on_exit(OptimizedEntryBlob::FrameData* context);
Expand Down

0 comments on commit 2c5d136

Please sign in to comment.