From cb7b514c9d453c91605152fa76eea0e6682ee837 Mon Sep 17 00:00:00 2001 From: Filip Jeremic Date: Thu, 12 Mar 2020 11:44:21 -0400 Subject: [PATCH 01/61] Add java/lang/StringUTF16.newBytesFor to alwaysWorthInlining list As part of #8830 we started using this API in several String constructors which are quite performance sensitive. Rather than relying on frequency information always being correct we simply force the inlining of this small method which will exposed the allocation of the array which we will store into the String object. Closes: #8831 Signed-off-by: Filip Jeremic --- runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp | 1 + runtime/compiler/env/j9method.cpp | 1 + runtime/compiler/optimizer/InlinerTempForJ9.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp b/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp index 095e84bc16c..4f09713c732 100644 --- a/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp +++ b/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp @@ -205,6 +205,7 @@ java_lang_StringUTF16_getChar, java_lang_StringUTF16_indexOf, + java_lang_StringUTF16_newBytesFor, java_lang_StringUTF16_toBytes, java_lang_StringBuffer_append, diff --git a/runtime/compiler/env/j9method.cpp b/runtime/compiler/env/j9method.cpp index c526a3bfb8a..cb0c94f792b 100644 --- a/runtime/compiler/env/j9method.cpp +++ b/runtime/compiler/env/j9method.cpp @@ -3526,6 +3526,7 @@ void TR_ResolvedJ9Method::construct() { { x(TR::java_lang_StringUTF16_getChar, "getChar", "([BI)C")}, { x(TR::java_lang_StringUTF16_indexOf, "indexOf", "([BI[BII)I")}, + { x(TR::java_lang_StringUTF16_newBytesFor, "newBytesFor", "(I)[B")}, { x(TR::java_lang_StringUTF16_toBytes, "toBytes", "([CII)[B")}, { TR::unknownMethod } }; diff --git a/runtime/compiler/optimizer/InlinerTempForJ9.cpp b/runtime/compiler/optimizer/InlinerTempForJ9.cpp index f7b0cd2c00e..8d01902a097 100644 --- a/runtime/compiler/optimizer/InlinerTempForJ9.cpp +++ b/runtime/compiler/optimizer/InlinerTempForJ9.cpp @@ -375,6 +375,7 @@ TR_J9InlinerPolicy::alwaysWorthInlining(TR_ResolvedMethod * calleeMethod, TR::No case TR::java_lang_StringBuffer_lengthInternalUnsynchronized: case TR::java_lang_StringBuilder_capacityInternal: case TR::java_lang_StringBuilder_lengthInternal: + case TR::java_lang_StringUTF16_newBytesFor: case TR::java_util_HashMap_get: case TR::java_util_HashMap_getNode: case TR::java_lang_String_getChars_charArray: From 3f904def64874be1f75ae0d2c553fb169ea36ee9 Mon Sep 17 00:00:00 2001 From: Younes Manton Date: Tue, 25 Feb 2020 10:50:07 -0500 Subject: [PATCH 02/61] Improve JITServer test diagnostic messages This patch prints more details when things fail and makes it easier to distinguish client and server log dumps in the output. Signed-off-by: Younes Manton --- .../src/jit/test/jitserver/JITServerTest.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/test/functional/JIT_Test/src/jit/test/jitserver/JITServerTest.java b/test/functional/JIT_Test/src/jit/test/jitserver/JITServerTest.java index 32fdddfed20..72b2c4419ea 100644 --- a/test/functional/JIT_Test/src/jit/test/jitserver/JITServerTest.java +++ b/test/functional/JIT_Test/src/jit/test/jitserver/JITServerTest.java @@ -92,11 +92,13 @@ public class JITServerTest { private static void dumpProcessLog(final ProcessBuilder b) { File log = b.redirectOutput().file(); try { + final String topAndBottom = "////////////////////////////////////////////////////////////////////////"; + final String leftMargin = "//// "; Scanner s = new Scanner(log); - System.err.println("Dumping the contents of log file: " + log.getAbsolutePath() + "\n"); + System.err.println("Dumping the contents of log file: " + log.getAbsolutePath() + "\n" + topAndBottom); while (s.hasNextLine()) - System.err.println(s.nextLine()); - System.err.println(""); + System.err.println(leftMargin + s.nextLine()); + System.err.println(topAndBottom); } catch (FileNotFoundException e) { System.err.println("Attempted to dump the log file '" + log.getAbsolutePath() + "' but it was not found.\n" + e.getMessage()); @@ -117,9 +119,10 @@ private static void destroyAndCheckProcess(final Process p, final ProcessBuilder // The process may exit normally before we can destroy it so we have to accept two possible return values. if ((exitValue != SUCCESS_RETURN_VALUE) && (exitValue != SIGTERM_RETURN_VALUE)) { - System.err.println("Expected a return value of " + SUCCESS_RETURN_VALUE + " or " + SIGTERM_RETURN_VALUE + ", got " + exitValue + " instead."); + final String errorText = "Expected an exit value of " + SUCCESS_RETURN_VALUE + " or " + SIGTERM_RETURN_VALUE + ", got " + exitValue + " instead."; + System.err.println(errorText); dumpProcessLog(builder); - AssertJUnit.fail(); + AssertJUnit.fail(errorText); } } @@ -129,9 +132,10 @@ private static Process startProcess(final ProcessBuilder builder, final String n final Process p = builder.start(); // We expect these processes to be fairly long running; if they exit almost immediately abort the test. if (p.waitFor(PROCESS_START_WAIT_TIME_MS, TimeUnit.MILLISECONDS)) { - System.err.println("Failed to start " + name); + final String errorText = "Failed to properly start " + name + ", it terminated prematurely with exit value: " + p.exitValue(); + System.err.println(errorText); dumpProcessLog(builder); - AssertJUnit.fail(); + AssertJUnit.fail(errorText); } return p; } From b93c66bb9072c792af35130697e2385eb3919360 Mon Sep 17 00:00:00 2001 From: Younes Manton Date: Fri, 6 Mar 2020 10:50:18 -0500 Subject: [PATCH 03/61] Handle quoted strings for JITServer test sub-procs Signed-off-by: Younes Manton --- .../src/jit/test/jitserver/JITServerTest.java | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/test/functional/JIT_Test/src/jit/test/jitserver/JITServerTest.java b/test/functional/JIT_Test/src/jit/test/jitserver/JITServerTest.java index 72b2c4419ea..650c9deef55 100644 --- a/test/functional/JIT_Test/src/jit/test/jitserver/JITServerTest.java +++ b/test/functional/JIT_Test/src/jit/test/jitserver/JITServerTest.java @@ -25,6 +25,7 @@ import java.util.Random; import java.util.concurrent.TimeUnit; import java.util.Scanner; +import java.util.ArrayList; import java.io.File; import java.io.IOException; import java.io.FileNotFoundException; @@ -79,8 +80,15 @@ public class JITServerTest { logger.info("Chose random port for server: " + randomPort + ", set " + SERVER_PORT_ENV_VAR_NAME + " in your env to override."); } - clientBuilder = new ProcessBuilder(String.join(" ", CLIENT_EXE, "-XX:+UseJITServer", portOption, CLIENT_PROGRAM).split(" +")); - serverBuilder = new ProcessBuilder(String.join(" ", SERVER_EXE, portOption).split(" +")); + // This handy regex pattern uses positive lookahead to match a string containing either zero or an even number of " (double quote) characters. + // If a character is followed by this pattern it means that the character itself is not in a quoted string, otherwise it would be followed by + // an odd number of " characters. Note that this doesn't handle ' (single quote) characters. + final String QUOTES_LOOKAHEAD_PATTERN = "(?=([^\"]*\"[^\"]*\")*[^\"]*$)"; + // We want to split the client program string on whitespace, unless the space appears in a quoted string. + final String SPLIT_ARGS_PATTERN = "\\s+" + QUOTES_LOOKAHEAD_PATTERN; + clientBuilder = new ProcessBuilder(stripQuotesFromEachArg(String.join(" ", CLIENT_EXE, "-XX:+UseJITServer", portOption, CLIENT_PROGRAM).split(SPLIT_ARGS_PATTERN))); + serverBuilder = new ProcessBuilder(stripQuotesFromEachArg(String.join(" ", SERVER_EXE, portOption).split(SPLIT_ARGS_PATTERN))); + // Redirect stderr to stdout, one log for each of the client and server is sufficient. clientBuilder.redirectErrorStream(true); serverBuilder.redirectErrorStream(true); @@ -89,6 +97,13 @@ public class JITServerTest { serverBuilder.environment().compute("TR_Options", (k, v) -> v != null && !v.isEmpty() ? String.join(",", v, JIT_LOG_ENV_OPTION) : JIT_LOG_ENV_OPTION); } + private static String[] stripQuotesFromEachArg(String[] args) { + for (int i = 0; i < args.length; ++i) { + args[i] = args[i].replaceAll("\"", ""); + } + return args; + } + private static void dumpProcessLog(final ProcessBuilder b) { File log = b.redirectOutput().file(); try { @@ -127,7 +142,10 @@ private static void destroyAndCheckProcess(final Process p, final ProcessBuilder } private static Process startProcess(final ProcessBuilder builder, final String name) throws IOException, InterruptedException { - logger.info("Starting " + name + " with command line:\n" + String.join(" ", builder.command())); + // Wrap any arguments containing whitespace in quotes for display (we have to make a copy of ProcessBuilder.command() to avoid modifying our PB's commands). + ArrayList command = new ArrayList(builder.command()); + command.replaceAll(s -> s.matches("\\S+") ? s : "\"" + s + "\""); + logger.info("Starting " + name + " with command line:\n" + String.join(" ", command)); logger.info("With stdout/stderr redirected to:\n" + builder.redirectOutput().file().getAbsolutePath()); final Process p = builder.start(); // We expect these processes to be fairly long running; if they exit almost immediately abort the test. From 8339fd3981eae52e81cdc90f98590a26e9a5a39b Mon Sep 17 00:00:00 2001 From: Younes Manton Date: Sat, 22 Feb 2020 10:35:23 -0500 Subject: [PATCH 04/61] Loop compilation activity in JITServer tests These JITServer tests are somewhat sensitive to timing because once the client finishes its work it will exit, but some tests need a long running client that keeps generating compilation activity while they start/stop/manipulate the server. This patch modifies JarTester (the app the client runs) to loop forever. JarTester loads and compiles a list of classes via short-lived classloader instances, so simply wrapping that code in a loop will allow it to keep generating compilation activity. Signed-off-by: Younes Manton --- test/functional/JIT_Test/playlist.xml | 2 +- .../JIT_Test/src/jit/test/jar/ZipTester.java | 34 +++++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/test/functional/JIT_Test/playlist.xml b/test/functional/JIT_Test/playlist.xml index 8a25b29267a..15d063f21fc 100644 --- a/test/functional/JIT_Test/playlist.xml +++ b/test/functional/JIT_Test/playlist.xml @@ -511,7 +511,7 @@ -cp $(Q)$(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(TEST_RESROOT)$(D)jitt.jar$(Q) \ -DSERVER_EXE=$(Q)$(TEST_JDK_BIN)$(D)jitserver$(Q) \ -DCLIENT_EXE=$(JAVA_COMMAND) \ - -DCLIENT_PROGRAM=$(SQ)$(JVM_OPTIONS) -cp $(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(TEST_RESROOT)$(D)jitt.jar -DjarTesterArgs=$(TEST_RESROOT)$(D)jitt.jar org.testng.TestNG -d $(REPORTDIR)$(D)client $(TEST_RESROOT)$(D)testng.xml -testnames JarTesterTest -groups $(TEST_GROUP) -excludegroups $(DEFAULT_EXCLUDE)$(SQ) \ + -DCLIENT_PROGRAM=$(SQ)$(JVM_OPTIONS) -cp $(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(TEST_RESROOT)$(D)jitt.jar -DjarTesterArgs=$(Q)-loopforever $(TEST_RESROOT)$(D)jitt.jar$(Q) org.testng.TestNG -d $(REPORTDIR)$(D)client $(TEST_RESROOT)$(D)testng.xml -testnames JarTesterTest -groups $(TEST_GROUP) -excludegroups $(DEFAULT_EXCLUDE)$(SQ) \ org.testng.TestNG \ -d $(REPORTDIR) \ $(Q)$(TEST_RESROOT)$(D)testng.xml$(Q) \ diff --git a/test/functional/JIT_Test/src/jit/test/jar/ZipTester.java b/test/functional/JIT_Test/src/jit/test/jar/ZipTester.java index 99ada9e786c..5049be8c8ee 100644 --- a/test/functional/JIT_Test/src/jit/test/jar/ZipTester.java +++ b/test/functional/JIT_Test/src/jit/test/jar/ZipTester.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2001, 2018 IBM Corp. and others + * Copyright (c) 2001, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -37,11 +37,16 @@ */ public class ZipTester { private static Logger logger = Logger.getLogger(ZipTester.class); - public static final String CLASS_FILTER_TAG = "-class:"; + public static final String TAG_PREFIX = "-"; + public static final String LOOP_FOREVER_TAG = TAG_PREFIX + "loopforever"; + public static final String CLASS_FILTER_TAG = TAG_PREFIX + "class:"; public static final String CLASS_FILTER_SUBSTRING = "substring"; public static final String CLASS_FILTER = CLASS_FILTER_TAG + CLASS_FILTER_SUBSTRING; public static final String ZIP_NAMES = "zip1 zip2 ..."; + public static final String LOOP_FOREVER_HELPER = + LOOP_FOREVER_TAG + + " --> loop forever (until the JVM is terminated)"; public static final String CLASS_FILTER_HELPER = CLASS_FILTER + " --> load classes whose names contain " @@ -53,23 +58,31 @@ public class ZipTester { public static void main(String args[]) { new ZipTester().run(args); } - + public void run(String args[]) { if (args.length < 1 || args[0].isEmpty()) { printUsageText(); Assert.fail(); } - String classFilter = args[0]; + String classFilter = ""; + boolean loopForever = false; int zipFilenameIndex = 0; - if (!classFilter.startsWith(CLASS_FILTER_TAG)) - classFilter = ""; - else { - classFilter = classFilter.substring(CLASS_FILTER_TAG.length()); - zipFilenameIndex = 1; + + while (args[zipFilenameIndex].startsWith(TAG_PREFIX)) { + if (args[zipFilenameIndex].startsWith(CLASS_FILTER_TAG)) + classFilter = classFilter.substring(CLASS_FILTER_TAG.length()); + else if (args[zipFilenameIndex].equals(LOOP_FOREVER_TAG)) + loopForever = true; + zipFilenameIndex++; } - process(classFilter, args, zipFilenameIndex); + if (loopForever) + logger.info(LOOP_FOREVER_TAG + " was specified; test will run continuously until the JVM is terminated."); + + do { + process(classFilter, args, zipFilenameIndex); + } while (loopForever); } public String getClassName() { @@ -123,6 +136,7 @@ protected String getGenericCommandline() { } protected void printGenericCommandlineExplanation() { + logger.debug("\t" + LOOP_FOREVER_HELPER); logger.debug("\t" + CLASS_FILTER_HELPER); logger.debug("\t" + JAR_NAMES_HELPER); } From 5116404df610618f90feed284df375bfdeb564d7 Mon Sep 17 00:00:00 2001 From: Younes Manton Date: Thu, 19 Mar 2020 10:25:30 -0400 Subject: [PATCH 05/61] Re-enable JITServer functional tests These tests were disabled temporarily while a large number of failures were investigated. The suspected bug has since been fixed. Signed-off-by: Younes Manton --- test/functional/JIT_Test/playlist.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/test/functional/JIT_Test/playlist.xml b/test/functional/JIT_Test/playlist.xml index 15d063f21fc..4fe5fb9f7a8 100644 --- a/test/functional/JIT_Test/playlist.xml +++ b/test/functional/JIT_Test/playlist.xml @@ -523,7 +523,6 @@ echo $(Q)$(TEST_JDK_BIN)$(D)jitserver doesn't exist; assuming this JDK does not support JITServer and trivially passing the test.$(Q); \ fi; \ $(TEST_STATUS) - https://github.com/eclipse/openj9/issues/8806 os.linux,arch.x86,bits.64 sanity From 8fdc25aeadd134f5721efaad19ecdb866d948d71 Mon Sep 17 00:00:00 2001 From: Peter Shipton Date: Fri, 20 Mar 2020 12:32:42 -0400 Subject: [PATCH 06/61] Enable --enable-jitserver for all xlinux and plinux Adds --enable-jitserver for jdk14+ Signed-off-by: Peter Shipton --- buildenv/jenkins/variables/defaults.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/buildenv/jenkins/variables/defaults.yml b/buildenv/jenkins/variables/defaults.yml index 3c4d9d9b4dc..5e61f507ce8 100644 --- a/buildenv/jenkins/variables/defaults.yml +++ b/buildenv/jenkins/variables/defaults.yml @@ -164,8 +164,7 @@ ppc64le_linux: node_labels: build: 'ci.role.build && hw.arch.ppc64le && sw.os.ubuntu' extra_configure_options: - 8: '--enable-jitserver' - 11: '--enable-jitserver' + all: '--enable-jitserver' build_env: vars: 'PATH+GCC7=/usr/local/gcc-7.5.0/bin LD_LIBRARY_PATH=/usr/local/gcc-7.5.0/lib64:$LD_LIBRARY_PATH' #========================================# @@ -279,8 +278,7 @@ x86-64_linux: node_labels: build: 'ci.role.build && hw.arch.x86 && sw.os.cent.6' extra_configure_options: - 8: '--enable-jitserver' - 11: '--enable-jitserver' + all: '--enable-jitserver' build_env: cmd: 'source /home/jenkins/set_gcc7.5.0_env' vars: 'OPENJ9_JAVA_OPTIONS=-Xdump:system+java:events=systhrow,filter=java/lang/ClassCastException,request=exclusive+prepwalk+preempt' From 70176717775b47ce15dc16ae1e1a32da14e1c3bd Mon Sep 17 00:00:00 2001 From: Babneet Singh Date: Fri, 20 Mar 2020 13:46:30 -0400 Subject: [PATCH 07/61] Remove final from fields being set in native methods A final field should not be modified after initialization. The two final fields mentioned below are modified after initialization in native code so they no longer satisfy the conditions of the final keyword. Hence, the final keyword is removed for the two fields. MethodHandle.kind is set in the following native method: 1. Java_java_lang_invoke_PrimitiveHandle_lookupMethod VarHandle.modifiers is set in the following native methods: 1. Java_java_lang_invoke_FieldVarHandle_lookupField 2. Java_java_lang_invoke_FieldVarHandle_unreflectField Signed-off-by: Babneet Singh --- .../share/classes/java/lang/invoke/MethodHandle.java | 6 +++--- .../java.base/share/classes/java/lang/invoke/VarHandle.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index 32027d2d4f6..ce37e73a463 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar17]*/ /******************************************************************************* - * Copyright (c) 2009, 2019 IBM Corp. and others + * Copyright (c) 2009, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -198,9 +198,9 @@ final void requestCustomThunk() { private native void requestCustomThunkFromJit(ThunkTuple tt); @VMCONSTANTPOOL_FIELD - final MethodType type; /* Type of the MethodHandle */ + final MethodType type; /* Type of the MethodHandle */ @VMCONSTANTPOOL_FIELD - final byte kind; /* The kind (STATIC/SPECIAL/etc) of this MethodHandle */ + byte kind; /* The kind (STATIC/SPECIAL/etc) of this MethodHandle */ @VMCONSTANTPOOL_FIELD int invocationCount; /* used to determine how many times the MH has been invoked*/ diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java index 2189f1694bc..b0605c67707 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -340,7 +340,7 @@ MethodType accessModeType(Class receiver, Class type, Class... args) { private final MethodHandle[] handleTable; final Class fieldType; final Class[] coordinateTypes; - final int modifiers; + int modifiers; /*[IF Java12]*/ private int hashCode = 0; /*[ENDIF] Java12 */ From 16fbbc239b50f279d764e49d4993fc314d290159 Mon Sep 17 00:00:00 2001 From: XuechunHou Date: Thu, 23 Jan 2020 16:40:40 -0700 Subject: [PATCH 08/61] added if clause for persistent logging, retrieved clientUID info fixed namespace error retrieved method signiture a new way of retrieving method full name changed to an easier way to retrieve compiled method signature attempted to add -XX:persistentLoggingDatabasePort flag, hit segmentation fault.. added if clause for persistent logging, retrieved clientUID info fixed namespace error retrieved method signiture Attempt to add logger to openj9. make Changes and stuff Add conditionals to check for mongo and cassandra support -XX flags needed for persistent logging completed Fix an issue with my previous merge IMplement environment variable ifdef wrapper thing port initialization on different DBMS added if clause for persistent logging, retrieved clientUID info a new way of retrieving method full name changed to an easier way to retrieve compiled method signature attempted to add -XX:persistentLoggingDatabasePort flag, hit segmentation fault.. retrieved method signiture Attempt to add logger to openj9. Add conditionals to check for mongo and cassandra support -XX flags needed for persistent logging completed IMplement environment variable ifdef wrapper thing add general persistent logging support flag for checking if persistent logging is enabled regardless of dbms fix more merge conflicts I forgot Add more env variable processing Add fix that allows you to enable the cassandra logger debug TR_PersistLogging flag Bring in changes by Ida for persistentLogger spec, dynamically load mongoc library addressed code review feedback addressed code review feedback addressed code review feedback added if clause for persistent logging, retrieved clientUID info fixed namespace error retrieved method signiture a new way of retrieving method full name changed to an easier way to retrieve compiled method signature attempted to add -XX:persistentLoggingDatabasePort flag, hit segmentation fault.. added if clause for persistent logging, retrieved clientUID info fixed namespace error retrieved method signiture Attempt to add logger to openj9. make Changes and stuff Add conditionals to check for mongo and cassandra support -XX flags needed for persistent logging completed Fix an issue with my previous merge IMplement environment variable ifdef wrapper thing port initialization on different DBMS added if clause for persistent logging, retrieved clientUID info a new way of retrieving method full name changed to an easier way to retrieve compiled method signature attempted to add -XX:persistentLoggingDatabasePort flag, hit segmentation fault.. retrieved method signiture Attempt to add logger to openj9. Add conditionals to check for mongo and cassandra support -XX flags needed for persistent logging completed IMplement environment variable ifdef wrapper thing add general persistent logging support flag for checking if persistent logging is enabled regardless of dbms fix more merge conflicts I forgot Add more env variable processing Add fix that allows you to enable the cassandra logger debug TR_PersistLogging flag Bring in changes by Ida for persistentLogger spec, dynamically load mongoc library addressed code review feedback addressed code review feedback addressed code review feedback Begin conversion of mongo to c strings and reformat to code conventions re-enable flags Reformat mongologger addressed code review feedback addressed code review feedback addressed code review feedback Address Feedback. Convert to C Strings. Cleanup Mongoc Finish making c style changes Re-add client UID setter and getter in J9PersistentInfo.cpp Dynamic Load Cassandra --- runtime/compiler/CMakeLists.txt | 12 +- runtime/compiler/build/files/common.mk | 10 + runtime/compiler/build/toolcfg/gnu/common.mk | 14 ++ .../compiler/control/BasePersistentLogger.hpp | 38 +++ runtime/compiler/control/CMakeLists.txt | 12 + runtime/compiler/control/CassandraLogger.cpp | 229 +++++++++++++++++ runtime/compiler/control/CassandraLogger.hpp | 28 +++ runtime/compiler/control/HookedByTheJit.cpp | 6 + runtime/compiler/control/J9Options.cpp | 51 +++- .../control/JITServerCompilationThread.cpp | 62 +++++ runtime/compiler/control/LoadDBLibs.cpp | 238 ++++++++++++++++++ runtime/compiler/control/LoadDBLibs.hpp | 217 ++++++++++++++++ runtime/compiler/control/MongoLogger.cpp | 160 ++++++++++++ runtime/compiler/control/MongoLogger.hpp | 37 +++ runtime/compiler/control/rossa.cpp | 22 ++ runtime/compiler/env/J9PersistentInfo.hpp | 33 +++ runtime/compiler/env/j9methodServer.cpp | 20 +- runtime/compiler/env/j9methodServer.hpp | 2 +- 18 files changed, 1175 insertions(+), 16 deletions(-) create mode 100644 runtime/compiler/control/BasePersistentLogger.hpp create mode 100644 runtime/compiler/control/CassandraLogger.cpp create mode 100644 runtime/compiler/control/CassandraLogger.hpp create mode 100644 runtime/compiler/control/LoadDBLibs.cpp create mode 100644 runtime/compiler/control/LoadDBLibs.hpp create mode 100644 runtime/compiler/control/MongoLogger.cpp create mode 100644 runtime/compiler/control/MongoLogger.hpp diff --git a/runtime/compiler/CMakeLists.txt b/runtime/compiler/CMakeLists.txt index b690cb7412d..7ee66009bcd 100644 --- a/runtime/compiler/CMakeLists.txt +++ b/runtime/compiler/CMakeLists.txt @@ -80,7 +80,7 @@ add_custom_command( ) add_custom_target(j9jit_tracegen DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/env/ut_j9jit.h) -# J9VM_OPT_JITSERVER +# J9VM_OPT_JITSERVER and protobuf and Persistent Loggers if(J9VM_OPT_JITSERVER) message(STATUS "JITServer is supported") @@ -99,6 +99,16 @@ if(J9VM_OPT_JITSERVER) include(FindOpenSSL) find_package(OpenSSL REQUIRED) include_directories(${OPENSSL_INCLUDE_DIR}) + + #Check for environment variable enabling the persistent logger + if(${PERSISTENT_LOGGER} STREQUAL "MONGODB") + add_definitions(-DMONGO_LOGGER) + add_definitions(-DPERSISTENT_LOGGING_SUPPORT) + endif() + if(${PERSISTENT_LOGGER} STREQUAL "CASSANDRA") + add_definitions(-DCASSANDRA_LOGGER) + add_definitions(-DPERSISTENT_LOGGING_SUPPORT) + endif() endif() #TODO We should get rid of this, but its still required by the compiler_support module in omr diff --git a/runtime/compiler/build/files/common.mk b/runtime/compiler/build/files/common.mk index 202576522b5..d7839d41fa2 100644 --- a/runtime/compiler/build/files/common.mk +++ b/runtime/compiler/build/files/common.mk @@ -383,6 +383,16 @@ JIT_PRODUCT_SOURCE_FILES+=\ omr/compiler/runtime/OMRRuntimeAssumptions.cpp ifneq ($(J9VM_OPT_JITSERVER),) +ifeq ($(PERSISTENT_LOGGER),MONGODB) + JIT_PRODUCT_SOURCE_FILES+=\ + compiler/control/MongoLogger.cpp \ + compiler/control/LoadDBLibs.cpp + endif +ifeq ($(PERSISTENT_LOGGER),CASSANDRA) + JIT_PRODUCT_SOURCE_FILES+=\ + compiler/control/CassandraLogger.cpp \ + compiler/control/LoadDBLibs.cpp +endif JIT_PRODUCT_SOURCE_FILES+=\ compiler/control/JITClientCompilationThread.cpp \ compiler/control/JITServerCompilationThread.cpp \ diff --git a/runtime/compiler/build/toolcfg/gnu/common.mk b/runtime/compiler/build/toolcfg/gnu/common.mk index 38c1763e06d..fad81af25ce 100644 --- a/runtime/compiler/build/toolcfg/gnu/common.mk +++ b/runtime/compiler/build/toolcfg/gnu/common.mk @@ -534,4 +534,18 @@ ifneq ($(J9VM_OPT_JITSERVER),) C_INCLUDES+=$(OPENSSL_DIR) CXX_INCLUDES+=$(OPENSSL_DIR) endif + + ifeq ($(PERSISTENT_LOGGER),CASSANDRA) + SOLINK_SLINK+=cassandra + CXX_DEFINES+=CASSANDRA_LOGGER + CXX_DEFINES+=PERSISTENT_LOGGING_SUPPORT + endif + ifeq ($(PERSISTENT_LOGGER),MONGODB) + SOLINK_SLINK+=bsoncxx + SOLINK_SLINK+=mongocxx + CXX_DEFINES+=MONGO_LOGGER + CXX_DEFINES+=PERSISTENT_LOGGING_SUPPORT + CXX_INCLUDES+=/usr/include/mongocxx/v_noabi + CXX_INCLUDES+=/usr/include/bsoncxx/v_noabi + endif endif # J9VM_OPT_JITSERVER diff --git a/runtime/compiler/control/BasePersistentLogger.hpp b/runtime/compiler/control/BasePersistentLogger.hpp new file mode 100644 index 00000000000..1e6f4eb73c6 --- /dev/null +++ b/runtime/compiler/control/BasePersistentLogger.hpp @@ -0,0 +1,38 @@ +#ifndef JITSERVERLOGGER_BASEPERSISTENTLOGGER_H +#define JITSERVERLOGGER_BASEPERSISTENTLOGGER_H +#include + +class BasePersistentLogger + { + protected: + const char * _databaseIP; + uint32_t _databasePort; + const char* _databaseUsername; + const char* _databasePassword; + const char* _databaseName; + + public: + virtual bool connect() = 0; + virtual void disconnect() = 0; + + BasePersistentLogger( const char * databaseIP, uint32_t databasePort, const char * databaseName) + { + _databaseIP = databaseIP; + _databasePort = databasePort; + _databaseName = databaseName; + _databaseUsername = ""; + _databasePassword = ""; + } + BasePersistentLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName, + const char *databaseUsername, const char *databasePassword) + { + _databaseIP = databaseIP; + _databasePort = databasePort; + _databaseName = databaseName; + _databaseUsername = databaseUsername; + _databasePassword = databasePassword; + } + virtual bool logMethod(const char* method, uint64_t clientID, const char *logContent) = 0; + }; + +#endif //JITSERVERLOGGER_BASEPERSISTENTLOGGER_H diff --git a/runtime/compiler/control/CMakeLists.txt b/runtime/compiler/control/CMakeLists.txt index 9f7632920d6..e67497fd3fc 100644 --- a/runtime/compiler/control/CMakeLists.txt +++ b/runtime/compiler/control/CMakeLists.txt @@ -32,6 +32,18 @@ j9jit_files( ) if(J9VM_OPT_JITSERVER) + if(${PERSISTENT_LOGGER} STREQUAL "MONGODB") + j9jit_files( + control/MongoLogger.cpp + control/LoadDBLibs.cpp + ) + endif() + if(${PERSISTENT_LOGGER} STREQUAL "CASSANDRA") + j9jit_files( + control/CassandraLogger.cpp + control/LoadDBLibs.cpp + ) + endif() j9jit_files( control/JITClientCompilationThread.cpp control/JITServerCompilationThread.cpp diff --git a/runtime/compiler/control/CassandraLogger.cpp b/runtime/compiler/control/CassandraLogger.cpp new file mode 100644 index 00000000000..b2b3a52b003 --- /dev/null +++ b/runtime/compiler/control/CassandraLogger.cpp @@ -0,0 +1,229 @@ +#include +#include + +#include "CassandraLogger.hpp" +#include "LoadDBLibs.hpp" +CassandraLogger::CassandraLogger(const char *databaseIP, +uint32_t databasePort, +const char *databaseName): BasePersistentLogger(databaseIP, databasePort, databaseName) + { + _session = NULL; + _connectFuture = NULL; + _cluster = NULL; + } + +CassandraLogger::CassandraLogger(const char *databaseIP, uint32_t databasePort, + const char *databaseName, const char *databaseUsername, const char *databasePassword) + : BasePersistentLogger(databaseIP, databasePort, databaseName, databaseUsername, databasePassword) + { + _session = NULL; + _connectFuture = NULL; + _cluster = NULL; + } + +bool CassandraLogger::createKeySpace() + { + char queryString[1024]; + sprintf(queryString, "CREATE KEYSPACE IF NOT EXISTS %s WITH REPLICATION = {'class':'SimpleStrategy','replication_factor':1};", _databaseName); + OCassStatement* statement = Ocass_statement_new(queryString, 0); + + OCassFuture* queryFuture = Ocass_session_execute(_session, statement); + Ocass_statement_free(statement); + if (Ocass_future_error_code(queryFuture) != 0) + { + /* Display connection error message */ + const char* message; + size_t messageLength; + Ocass_future_error_message(queryFuture, &message, &messageLength); + fprintf(stderr, "PersistentLogging: Cassandra Database Keyspace Creation Error: '%.*s'\n", (int)messageLength, message); + + Ocass_future_free(queryFuture); + return false; + } + + Ocass_future_free(queryFuture); + return true; + +} +bool CassandraLogger::createTable(const char *tableName) + { + char queryString[1024]; + sprintf(queryString, "CREATE TABLE IF NOT EXISTS %s.%s (clientID text, methodName text, logContent text, insertionDate date,insertionTime time, primary key (clientID, methodName, insertionDate, insertionTime));", _databaseName, tableName); + OCassStatement* statement = Ocass_statement_new(queryString, 0); + OCassFuture* queryFuture = Ocass_session_execute(_session, statement); + Ocass_statement_free(statement); + if (Ocass_future_error_code(queryFuture) != 0) + { + /* Display connection error message */ + const char* message; + size_t messageLength; + Ocass_future_error_message(queryFuture, &message, &messageLength); + fprintf(stderr, "Persistent Logging: Cassandra Database Table Creation Error: '%.*s'\n", (int)messageLength, message); + + Ocass_future_free(queryFuture); + return false; + } + + Ocass_future_free(queryFuture); + return true; + } +bool CassandraLogger::connect() + { + /* Setup and connect to cluster */ + _cluster = Ocass_cluster_new(); + _session = Ocass_session_new(); + /*authenticate using databaseUsername and databasePassword*/ + Ocass_cluster_set_credentials(_cluster, _databaseUsername, _databasePassword); + /*Set protocol version */ + int rc_set_protocol = Ocass_cluster_set_protocol_version(_cluster, 4); + if (rc_set_protocol != 0) + { + printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_protocol)); + Ocass_session_free(_session); + Ocass_cluster_free(_cluster); + return false; + + } + + /* Add contact points */ + int rc_set_ip = Ocass_cluster_set_contact_points(_cluster, _databaseIP); + if (rc_set_ip != 0) + { + printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_ip)); + Ocass_session_free(_session); + Ocass_cluster_free(_cluster); + return false; + + } + + /*Set port number*/ + int rc_set_port = Ocass_cluster_set_port(_cluster, _databasePort); + if (rc_set_port != 0) + { + printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_port)); + Ocass_session_free(_session); + Ocass_cluster_free(_cluster); + + return false; + + } + + /* Provide the cluster object as configuration to connect the session */ + _connectFuture = Ocass_session_connect(_session, _cluster); + + if (Ocass_future_error_code(_connectFuture) != 0) + { + /* Display connection error message */ + const char* message; + size_t messageLength; + Ocass_future_error_message(_connectFuture, &message, &messageLength); + fprintf(stderr, "Persistent Logging: Cassandra Database Connection Error: '%.*s'\n", (int)messageLength, message); + Ocass_session_free(_session); + Ocass_cluster_free(_cluster); + Ocass_future_free(_connectFuture); + return false; + } + return true; + + } + + +bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const char *logContent) + { + + // create table space and table first + if (!createKeySpace()) return false; + const char* tableName = "logs"; + if (!createTable(tableName)) return false; + char queryString[1024]; + + sprintf(queryString, "INSERT INTO %s.%s (clientID, methodName, logContent, insertionDate, insertionTime) VALUES (?, ?, ?, ?, ?)", _databaseName,tableName); + OCassStatement* statement + = Ocass_statement_new(queryString, 5); + + /* Bind the values using the indices of the bind variables */ + char strClientID[64]; + sprintf(strClientID, "%lu", clientID); + int rc_set_bind_pk = Ocass_statement_bind_string(statement, 0, strClientID); + if (rc_set_bind_pk != 0) + { + printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_pk)); + Ocass_statement_free(statement); + return false; + } + + int rc_set_bind_method = Ocass_statement_bind_string(statement, 1, method); + if (rc_set_bind_pk != 0) + { + printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_method)); + Ocass_statement_free(statement); + return false; + } + int rc_set_bind_log_content = Ocass_statement_bind_string(statement, 2, logContent); + + if (rc_set_bind_log_content != 0) + { + printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_log_content)); + Ocass_statement_free(statement); + return false; + } + + time_t now = time(NULL); /* Time in seconds from Epoch */ + /* Converts the time since the Epoch in seconds to the 'date' type */ + Ocass_uint32_t year_month_day_of_insertion = Ocass_date_from_epoch(now); + /* Converts the time since the Epoch in seconds to the 'time' type */ + Ocass_int64_t time_of_insertion = Ocass_time_from_epoch(now); + + /* 'date' uses an unsigned 32-bit integer */ + int rc_set_bind_insertion_date = Ocass_statement_bind_uint32(statement, 3, year_month_day_of_insertion); + + if (rc_set_bind_insertion_date != 0) + { + printf("Persistent Logging - Cassandra Database Error: %s\n", Ocass_error_desc(rc_set_bind_insertion_date)); + Ocass_statement_free(statement); + return false; + } + /* 'time' uses a signed 64-bit integer */ + int rc_set_bind_insertion_time = Ocass_statement_bind_int64(statement, 4, time_of_insertion); + if (rc_set_bind_insertion_time != 0) + { + printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_insertion_time)); + Ocass_statement_free(statement); + return false; + } + + OCassFuture* queryFuture = Ocass_session_execute(_session, statement); + + /* Statement objects can be freed immediately after being executed */ + Ocass_statement_free(statement); + if (Ocass_future_error_code(queryFuture) != 0) + { + /* Display connection error message */ + const char* message; + size_t messageLength; + Ocass_future_error_message(queryFuture, &message, &messageLength); + fprintf(stderr, "query execution error: '%.*s'\n", (int)messageLength, message); + Ocass_future_free(queryFuture); + return false; + } + + Ocass_future_free(queryFuture); + return true; + } + + +void CassandraLogger::disconnect() + { + Ocass_future_free(_connectFuture); + Ocass_session_free(_session); + Ocass_cluster_free(_cluster); + } + + + + + + + + + diff --git a/runtime/compiler/control/CassandraLogger.hpp b/runtime/compiler/control/CassandraLogger.hpp new file mode 100644 index 00000000000..358028eb74f --- /dev/null +++ b/runtime/compiler/control/CassandraLogger.hpp @@ -0,0 +1,28 @@ +#ifndef CASSANDRALOGGER_H +#define CASSANDRALOGGER_H + +#include "LoadDBLibs.hpp" +#include "BasePersistentLogger.hpp" +class CassandraLogger : public BasePersistentLogger + { + + private: + OCassCluster* _cluster; + OCassSession* _session; + OCassFuture* _connectFuture; + bool createKeySpace(); + bool createTable(const char *tableName); + + + public: + + bool connect() override; + void disconnect() override; + CassandraLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName, + const char *databaseUsername, const char *databasePassword); + CassandraLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName); + bool logMethod(const char *method, uint64_t clientID, const char *logContent) override; + + }; + +#endif // CASSANDRALOGGER_H \ No newline at end of file diff --git a/runtime/compiler/control/HookedByTheJit.cpp b/runtime/compiler/control/HookedByTheJit.cpp index 018f9d87f6e..ce640a25f53 100644 --- a/runtime/compiler/control/HookedByTheJit.cpp +++ b/runtime/compiler/control/HookedByTheJit.cpp @@ -83,6 +83,9 @@ #include "runtime/JITServerIProfiler.hpp" #include "runtime/JITServerStatisticsThread.hpp" #include "runtime/Listener.hpp" +#if defined(MONGO_LOGGER) +#include "control/LoadDBLibs.hpp" +#endif // defined(MONGO_LOGGER) #endif extern "C" { @@ -4760,6 +4763,9 @@ void JitShutdown(J9JITConfig * jitConfig) { statsThreadObj->stopStatisticsThread(jitConfig); } +#if defined(MONGO_LOGGER) + Omongoc_cleanup(); +#endif // defined(MONGOLOGGER) #endif TR_DebuggingCounters::report(); diff --git a/runtime/compiler/control/J9Options.cpp b/runtime/compiler/control/J9Options.cpp index 9300c9ac68b..a2138b2b605 100644 --- a/runtime/compiler/control/J9Options.cpp +++ b/runtime/compiler/control/J9Options.cpp @@ -1074,13 +1074,26 @@ static void JITServerParseCommonOptions(J9JavaVM *vm, TR::CompilationInfo *compI const char *xxJITServerSSLKeyOption = "-XX:JITServerSSLKey="; const char *xxJITServerSSLCertOption = "-XX:JITServerSSLCert="; const char *xxJITServerSSLRootCertsOption = "-XX:JITServerSSLRootCerts="; - + #ifdef PERSISTENT_LOGGING_SUPPORT + const char *xxJITServerPersistentLoggingDatabasePortOption = "-XX:JITServerPersistentLoggingDatabasePort="; + const char *xxJITServerPersistentLoggingDatabaseAddressOption = "-XX:JITServerPersistentLoggingDatabaseAddress="; + const char *xxJITServerPersistentLoggingDatabaseNameOption = "-XX:JITServerPersistentLoggingDatabaseName="; + const char *xxJITServerPersistentLoggingDatabaseUsernameOption = "-XX:JITServerPersistentLoggingDatabaseUsername="; + const char *xxJITServerPersistentLoggingDatabasePasswordOption = "-XX:JITServerPersistentLoggingDatabasePassword="; + #endif // PERSISTENT_LOGGING_SUPPORT int32_t xxJITServerPortArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPortOption, 0); int32_t xxJITServerTimeoutArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerTimeoutOption, 0); int32_t xxJITServerSSLKeyArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerSSLKeyOption, 0); int32_t xxJITServerSSLCertArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerSSLCertOption, 0); int32_t xxJITServerSSLRootCertsArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerSSLRootCertsOption, 0); - + #ifdef PERSISTENT_LOGGING_SUPPORT + int32_t xxJITServerPersistentLoggingDatabasePortArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabasePortOption, 0); + int32_t xxJITServerPersistentLoggingDatabaseAddressArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseAddressOption, 0); + int32_t xxJITServerPersistentLoggingDatabaseNameArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseNameOption, 0); + int32_t xxJITServerPersistentLoggingDatabaseUsernameArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseUsernameOption, 0); + int32_t xxJITServerPersistentLoggingDatabasePasswordArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabasePasswordOption, 0); + #endif // PERSISTENT_LOGGING_SUPPORT + if (xxJITServerPortArgIndex >= 0) { uint32_t port=0; @@ -1088,7 +1101,41 @@ static void JITServerParseCommonOptions(J9JavaVM *vm, TR::CompilationInfo *compI if (ret == OPTION_OK) compInfo->getPersistentInfo()->setJITServerPort(port); } + #ifdef PERSISTENT_LOGGING_SUPPORT + if (xxJITServerPersistentLoggingDatabasePortArgIndex >= 0) + { + uint32_t port=0; + IDATA ret = GET_INTEGER_VALUE(xxJITServerPersistentLoggingDatabasePortArgIndex, xxJITServerPersistentLoggingDatabasePortOption, port); + if (ret == OPTION_OK) + compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabasePort(port); + } + if (xxJITServerPersistentLoggingDatabaseUsernameArgIndex >= 0) + { + char *username = NULL; + GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabaseUsernameArgIndex, '=', &username); + compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabaseUsername(username); + } + if (xxJITServerPersistentLoggingDatabaseNameArgIndex >= 0) + { + char *name = NULL; + GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabaseNameArgIndex, '=', &name); + compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabaseName(name); + } + if (xxJITServerPersistentLoggingDatabasePasswordArgIndex >= 0) + { + char *password = NULL; + GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabasePasswordArgIndex, '=', &password); + compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabasePassword(password); + } + + if (xxJITServerPersistentLoggingDatabaseAddressArgIndex >= 0) + { + char *address = NULL; + GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabaseAddressArgIndex, '=', &address); + compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabaseAddress(address); + } + #endif // PERSISTENT_LOGGING_SUPPORT if (xxJITServerTimeoutArgIndex >= 0) { uint32_t timeoutMs=0; diff --git a/runtime/compiler/control/JITServerCompilationThread.cpp b/runtime/compiler/control/JITServerCompilationThread.cpp index 3b21855c7c0..b81b5fb2355 100644 --- a/runtime/compiler/control/JITServerCompilationThread.cpp +++ b/runtime/compiler/control/JITServerCompilationThread.cpp @@ -26,6 +26,14 @@ #include "control/CompilationRuntime.hpp" #include "control/MethodToBeCompiled.hpp" #include "control/JITServerHelpers.hpp" +#ifdef CASSANDRA_LOGGER +#include "control/CassandraLogger.hpp" +#include +#endif // CASSANDRA_LOGGER +#ifdef MONGO_LOGGER +#include "control/MongoLogger.hpp" +#include +#endif // MONGO_LOGGER #include "env/ClassTableCriticalSection.hpp" #include "env/VMAccessCriticalSection.hpp" #include "env/JITServerPersistentCHTable.hpp" @@ -38,6 +46,7 @@ #include "jitprotos.h" #include "vmaccess.h" + /** * @brief Method executed by JITServer to process the end of a compilation. */ @@ -82,6 +91,59 @@ outOfProcessCompilationEnd( // Pack log file to send to client std::string logFileStr = TR::Options::packLogFile(comp->getOutFile()); + std::cout << "Pre Persistent Logging Section" << std::endl; + std::cout << comp->getOption(TR_PersistentLogging) << std::endl; +#ifdef PERSISTENT_LOGGING_SUPPORT + if (comp->getOption(TR_PersistentLogging)) + { + uint64_t clientUID = entry->getClientUID(); + const char* methodSignature = compInfoPT->getCompilation()->signature(); + TR::PersistentInfo* persistentInfo = compInfoPT->getCompilationInfo()->getPersistentInfo(); + printf("Persistent Logging enabled\n"); + printf("Found Client ID %llu\n", clientUID); + printf("potential method full name: %s\n",methodSignature); + uint32_t persistentLoggingDatabasePort = persistentInfo->getJITServerPersistentLoggingDatabasePort(); + printf("what is the persistent logging database port ? %lu\n",persistentLoggingDatabasePort); + const char* persistentLoggingDatabaseAddress = persistentInfo->getJITServerPersistentLoggingDatabaseAddress(); + std::cout << "what is the persistent logging database Address ? " << persistentLoggingDatabaseAddress << std::endl; + + const char* persistentLoggingDatabaseUsername = persistentInfo->getJITServerPersistentLoggingDatabaseUsername(); + std::cout << "what is the persistent logging database Username ? " << persistentLoggingDatabaseUsername << std::endl; + + const char* persistentLoggingDatabasePassword = persistentInfo->getJITServerPersistentLoggingDatabasePassword(); + std::cout <<"what is the persistent logging database Password ? "<< persistentLoggingDatabasePassword << std::endl; + + const char* persistentLoggingDatabaseName = persistentInfo->getJITServerPersistentLoggingDatabaseName(); + std::cout << "what is the persistent logging database Name ? " << persistentLoggingDatabaseName << std::endl; +#ifdef CASSANDRA_LOGGER + CassandraLogger logger(persistentLoggingDatabaseAddress, + persistentLoggingDatabasePort, + persistentLoggingDatabaseName, + persistentLoggingDatabaseUsername, + persistentLoggingDatabasePassword); + std::cout << "Im Cassandra" << std::endl; +#endif // CASSANDRA_LOGGER + +#ifdef MONGO_LOGGER + MongoLogger logger(persistentLoggingDatabaseAddress, + persistentLoggingDatabasePort, + persistentLoggingDatabaseName, + persistentLoggingDatabaseUsername, + persistentLoggingDatabasePassword); + std::cout << "Im mongo" << std::endl; +#endif // MONGO_LOGGER + bool isConnected = logger.connect(); + if (isConnected) + { + logger.logMethod(methodSignature, clientUID, logFileStr.c_str()); + logger.disconnect(); + } + else + { + printf("Persistent Logging Error: Database Connection Failed\n"); + } + } +#endif // PERSISTENT_LOGGING_SUPPORT std::string svmSymbolToIdStr; if (comp->getOption(TR_UseSymbolValidationManager)) diff --git a/runtime/compiler/control/LoadDBLibs.cpp b/runtime/compiler/control/LoadDBLibs.cpp new file mode 100644 index 00000000000..a99cda622cc --- /dev/null +++ b/runtime/compiler/control/LoadDBLibs.cpp @@ -0,0 +1,238 @@ +// +// Created by cmbuhler on 2020-03-11. +// +#include "LoadDBLibs.hpp" + +#include +#include +#include + +/* + * MONGOC and BSON Library functions and strcuts + */ +Obson_new_t *Obson_new = NULL; +Obson_append_utf8_t *Obson_append_utf8 = NULL; +Obson_append_date_time_t *Obson_append_date_time = NULL; +Obson_destroy_t *Obson_destroy = NULL; + +Omongoc_init_t *Omongoc_init = NULL; +Omongoc_cleanup_t *Omongoc_cleanup = NULL; +Omongoc_uri_new_with_error_t *Omongoc_uri_new_with_error = NULL; +Omongoc_client_new_from_uri_t *Omongoc_client_new_from_uri = NULL; +Omongoc_client_set_appname_t *Omongoc_client_set_appname = NULL; +Omongoc_client_get_database_t *Omongoc_client_get_database = NULL; +Omongoc_client_get_collection_t *Omongoc_client_get_collection = NULL; +Omongoc_collection_insert_one_t *Omongoc_collection_insert_one = NULL; +Omongoc_collection_destroy_t *Omongoc_collection_destroy = NULL; +Omongoc_database_destroy_t *Omongoc_database_destroy = NULL; +Omongoc_uri_destroy_t *Omongoc_uri_destroy = NULL; +Omongoc_client_destroy_t *Omongoc_client_destroy = NULL; + +/* + * CASSANDRA functions and structs + */ +Ocass_statement_new_t *Ocass_statement_new = NULL; +Ocass_statement_free_t *Ocass_statement_free = NULL; +Ocass_session_execute_t *Ocass_session_execute = NULL; +Ocass_future_error_code_t *Ocass_future_error_code = NULL; +Ocass_future_error_message_t *Ocass_future_error_message = NULL; +Ocass_future_free_t *Ocass_future_free = NULL; +Ocass_cluster_new_t *Ocass_cluster_new = NULL; +Ocass_session_new_t *Ocass_session_new = NULL; +Ocass_cluster_set_credentials_t *Ocass_cluster_set_credentials = NULL; +Ocass_cluster_set_protocol_version_t *Ocass_cluster_set_protocol_version = NULL; +Ocass_session_free_t *Ocass_session_free = NULL; +Ocass_cluster_free_t *Ocass_cluster_free = NULL; +Ocass_cluster_set_contact_points_t *Ocass_cluster_set_contact_points = NULL; +Ocass_cluster_set_port_t *Ocass_cluster_set_port = NULL; +Ocass_session_connect_t *Ocass_session_connect = NULL; +Ocass_statement_bind_string_t *Ocass_statement_bind_string = NULL; +Ocass_error_desc_t *Ocass_error_desc = NULL; +Ocass_time_from_epoch_t *Ocass_time_from_epoch = NULL; +Ocass_date_from_epoch_t *Ocass_date_from_epoch = NULL; +Ocass_statement_bind_int64_t *Ocass_statement_bind_int64 = NULL; +Ocass_statement_bind_uint32_t *Ocass_statement_bind_uint32 = NULL; + + +namespace JITServer + { + void *loadLibmongoc() + { + void *result = NULL; + result = dlopen("libmongoc-1.0.so", RTLD_NOW); + return result; + } + + void *loadLibbson() + { + void *result = NULL; + result = dlopen("libbson-1.0.so", RTLD_NOW); + return result; + } + + void *loadLibcassandra() + { + void *result = NULL; + result = dlopen("libcassandra.so", RTLD_NOW); + return result; + } + + void unloadDBLib(void *handle) + { + (void) dlclose(handle); + } + + void *findDBLibSymbol(void *handle, const char *sym) + { + return dlsym(handle, sym); + } + + bool loadLibmongocAndSymbols() + { + void *handle = NULL; + + handle = loadLibmongoc(); + if (!handle) + { + printf("#JITServer: Failed to load libmongoc\n"); + return false; + } + + Omongoc_init = (Omongoc_init_t *) findDBLibSymbol(handle, "mongoc_init"); + Omongoc_cleanup = (Omongoc_cleanup_t *) findDBLibSymbol(handle, "mongoc_cleanup"); + Omongoc_uri_new_with_error = (Omongoc_uri_new_with_error_t *) findDBLibSymbol(handle, + "mongoc_uri_new_with_error"); + Omongoc_client_new_from_uri = (Omongoc_client_new_from_uri_t *) findDBLibSymbol(handle, + "mongoc_client_new_from_uri"); + Omongoc_client_set_appname = (Omongoc_client_set_appname_t *) findDBLibSymbol(handle, + "mongoc_client_set_appname"); + Omongoc_client_get_database = (Omongoc_client_get_database_t *) findDBLibSymbol(handle, + "mongoc_client_get_database"); + Omongoc_client_get_collection = (Omongoc_client_get_collection_t *) findDBLibSymbol(handle, + "mongoc_client_get_collection"); + Omongoc_collection_insert_one = (Omongoc_collection_insert_one_t *) findDBLibSymbol(handle, + "mongoc_collection_insert_one"); + Omongoc_collection_destroy = (Omongoc_collection_destroy_t *) findDBLibSymbol(handle, + "mongoc_collection_destroy"); + Omongoc_database_destroy = (Omongoc_database_destroy_t *) findDBLibSymbol(handle, "mongoc_database_destroy"); + Omongoc_uri_destroy = (Omongoc_uri_destroy_t *) findDBLibSymbol(handle, "mongoc_uri_destroy"); + Omongoc_client_destroy = (Omongoc_client_destroy_t *) findDBLibSymbol(handle, "mongoc_client_destroy"); + + if ( + (Omongoc_init == NULL) || + (Omongoc_cleanup == NULL) || + (Omongoc_uri_new_with_error == NULL) || + (Omongoc_client_new_from_uri == NULL) || + (Omongoc_client_set_appname == NULL) || + (Omongoc_client_get_database == NULL) || + (Omongoc_client_get_collection == NULL) || + (Omongoc_collection_insert_one == NULL) || + (Omongoc_collection_destroy == NULL) || + (Omongoc_database_destroy == NULL) || + (Omongoc_uri_destroy == NULL) || + (Omongoc_client_destroy == NULL) + ) + { + printf("#JITServer: Failed to load all the required Mongoc symbols\n"); + unloadDBLib(handle); + return false; + } + + return true; + } + + bool loadLibbsonAndSymbols() + { + void *handle = NULL; + + handle = loadLibbson(); + if (!handle) + { + printf("#JITServer: Failed to load libbson\n"); + return false; + } + + Obson_new = (Obson_new_t *) findDBLibSymbol(handle, "bson_new"); + Obson_append_utf8 = (Obson_append_utf8_t *) findDBLibSymbol(handle, "bson_append_utf8"); + Obson_append_date_time = (Obson_append_date_time_t *) findDBLibSymbol(handle, "bson_append_date_time"); + Obson_destroy = (Obson_destroy_t *) findDBLibSymbol(handle, "bson_destroy"); + + if ( + (Obson_new == NULL) || + (Obson_append_utf8 == NULL) || + (Obson_append_date_time == NULL) || + (Obson_destroy == NULL) + ) + { + printf("#JITServer: Failed to load all the required bson symbols\n"); + unloadDBLib(handle); + return false; + } + + return true; + } + + bool loadLibcassandraAndSymbols() + { + void *handle = NULL; + + handle = loadLibcassandra(); + if (!handle) + { + printf("#JITServer: Failed to load libcassandra.\n"); + return false; + } + + Ocass_statement_new = (Ocass_statement_new_t *) findDBLibSymbol(handle, "cass_statement_new"); + Ocass_statement_free = (Ocass_statement_free_t *) findDBLibSymbol(handle, "cass_statement_free"); + Ocass_session_execute = (Ocass_session_execute_t *) findDBLibSymbol(handle, "cass_session_execute"); + Ocass_future_error_code = (Ocass_future_error_code_t *) findDBLibSymbol(handle, "cass_future_error_code"); + Ocass_future_error_message = (Ocass_future_error_message_t *) findDBLibSymbol(handle, "cass_future_error_message"); + Ocass_future_free = (Ocass_future_free_t *) findDBLibSymbol(handle, "cass_future_free"); + Ocass_cluster_new = (Ocass_cluster_new_t *) findDBLibSymbol(handle, "cass_cluster_new"); + Ocass_session_new = (Ocass_session_new_t *) findDBLibSymbol(handle, "cass_session_new"); + Ocass_cluster_set_credentials = (Ocass_cluster_set_credentials_t *) findDBLibSymbol(handle, "cass_cluster_set_credentials"); + Ocass_cluster_set_protocol_version = (Ocass_cluster_set_protocol_version_t *) findDBLibSymbol(handle, "cass_cluster_set_protocol_version"); + Ocass_session_free = (Ocass_session_free_t *) findDBLibSymbol(handle, "cass_session_free"); + Ocass_cluster_free = (Ocass_cluster_free_t *) findDBLibSymbol(handle, "cass_cluster_free"); + Ocass_cluster_set_contact_points = (Ocass_cluster_set_contact_points_t *) findDBLibSymbol(handle, "cass_cluster_set_contact_points"); + Ocass_cluster_set_port = (Ocass_cluster_set_port_t *) findDBLibSymbol(handle, "cass_cluster_set_port"); + Ocass_session_connect = (Ocass_session_connect_t *) findDBLibSymbol(handle, "cass_session_connect"); + Ocass_statement_bind_string = (Ocass_statement_bind_string_t *) findDBLibSymbol(handle, "cass_statement_bind_string"); + Ocass_error_desc = (Ocass_error_desc_t *) findDBLibSymbol(handle, "cass_error_desc"); + Ocass_time_from_epoch = (Ocass_time_from_epoch_t *) findDBLibSymbol(handle, "cass_time_from_epoch"); + Ocass_date_from_epoch = (Ocass_date_from_epoch_t *) findDBLibSymbol(handle, "cass_date_from_epoch"); + Ocass_statement_bind_int64 = (Ocass_statement_bind_int64_t *) findDBLibSymbol(handle, "cass_statement_bind_int64"); + Ocass_statement_bind_uint32 = (Ocass_statement_bind_uint32_t *)findDBLibSymbol(handle, "cass_statement_bind_uint32"); + + + if ((Ocass_statement_free == NULL ) || + (Ocass_statement_new == NULL) || + (Ocass_session_execute == NULL) || + (Ocass_future_error_code == NULL) || + (Ocass_future_error_message == NULL) || + (Ocass_future_free == NULL) || + (Ocass_cluster_new == NULL) || + (Ocass_session_new == NULL) || + (Ocass_cluster_set_credentials == NULL) || + (Ocass_cluster_set_protocol_version == NULL) || + (Ocass_session_free == NULL) || + (Ocass_cluster_free == NULL) || + (Ocass_cluster_set_contact_points == NULL) || + (Ocass_cluster_set_port == NULL) || + (Ocass_session_connect == NULL) || + (Ocass_statement_bind_string == NULL) || + (Ocass_error_desc == NULL) || + (Ocass_time_from_epoch == NULL) || + (Ocass_date_from_epoch == NULL) || + (Ocass_statement_bind_int64 == NULL) || + (Ocass_statement_bind_uint32 == NULL) + ) + { + printf("#JITServer: Failed to load all the required cassandra symbols\n"); + unloadDBLib(handle); + return false; + } + return true; + } + } diff --git a/runtime/compiler/control/LoadDBLibs.hpp b/runtime/compiler/control/LoadDBLibs.hpp new file mode 100644 index 00000000000..d8acf80cd6d --- /dev/null +++ b/runtime/compiler/control/LoadDBLibs.hpp @@ -0,0 +1,217 @@ +// +// Created by cmbuhler on 2020-03-11. +// + +#ifndef JITSERVER_LOADDBLIBS_HPP +#define JITSERVER_LOADDBLIBS_HPP + +#include +#include + +/* + * libbson function pointers and typedefs + */ +typedef struct Obson_t Obson_t; + +typedef struct + { + uint32_t domain; + uint32_t code; + char message[504]; + } Obson_error_t; + +typedef Obson_t *Obson_new_t(void); + +typedef bool + Obson_append_utf8_t(Obson_t *bson_client, + const char *key, + int key_length, + const char *value, + int length); + +typedef bool + Obson_append_date_time_t(Obson_t *bson, + const char *key, + int key_length, + int64_t value); + +typedef void + Obson_destroy_t(Obson_t *bson); + +/* + * libmongoc Function Pointers and typedefs + */ +typedef void Omongoc_init_t(void); + +typedef void Omongoc_cleanup_t(void); + +typedef struct Omongoc_uri_t Omongoc_uri_t; + +typedef struct Omongoc_client_t Omongoc_client_t; + +typedef struct Omongoc_database_t Omongoc_database_t; + +typedef struct Omongoc_collection_t Omongoc_collection_t; + +typedef Omongoc_uri_t * + Omongoc_uri_new_with_error_t(const char *uri_string, + Obson_error_t *error); + +typedef Omongoc_client_t * + Omongoc_client_new_from_uri_t(const Omongoc_uri_t *uri); + +typedef bool + Omongoc_client_set_appname_t(const Omongoc_client_t *client, + const char *name); + +typedef Omongoc_database_t * + Omongoc_client_get_database_t(const Omongoc_client_t *client, + const char *database_name); + +typedef Omongoc_collection_t * + Omongoc_client_get_collection_t(const Omongoc_client_t *client, + const char *database_name, + const char *collection_name); + +typedef bool + Omongoc_collection_insert_one_t(Omongoc_collection_t *collection, + const Obson_t *document, + const Obson_t *opts, + Obson_t *reply, + Obson_error_t *error); + +typedef void Omongoc_collection_destroy_t(Omongoc_collection_t *collection); + +typedef void Omongoc_database_destroy_t(Omongoc_database_t *database); + +typedef void Omongoc_uri_destroy_t(Omongoc_uri_t *uri); + +typedef void Omongoc_client_destroy_t(Omongoc_client_t *client); + +/* + * libcassandra function pointers and typedefs + */ +#define OCASS_OK 0; +typedef int64_t Ocass_int64_t; + +typedef uint32_t Ocass_uint32_t; + +typedef struct OCassCluster OCassCluster; + +typedef struct OCassSession OCassSession; + +typedef struct OCassStatement OCassStatement; + +typedef struct OCassFuture OCassFuture; + +typedef int OCassError; + +typedef OCassStatement * + Ocass_statement_new_t(const char *query, size_t parameter_count); + +typedef void Ocass_statement_free_t(OCassStatement *statement); + +typedef OCassFuture * Ocass_session_execute_t(OCassSession *session, OCassStatement * statement); + +typedef int Ocass_future_error_code_t(OCassFuture *future); + +typedef void Ocass_future_error_message_t(OCassFuture * future, const char ** message, size_t * message_length); + +typedef void Ocass_future_free_t(OCassFuture *future); + +typedef OCassCluster * Ocass_cluster_new_t(); + +typedef OCassSession * Ocass_session_new_t(); + +typedef void Ocass_cluster_set_credentials_t(OCassCluster * cluster, const char * username, const char * password); + +typedef int Ocass_cluster_set_protocol_version_t(OCassCluster *cluster, int version); + +typedef void Ocass_session_free_t(OCassSession *session); + +typedef void Ocass_cluster_free_t(OCassCluster *cluster); + +typedef int Ocass_cluster_set_contact_points_t(OCassCluster *cluster, const char * contact_points); + +typedef int Ocass_cluster_set_port_t(OCassCluster *cluster, int port); + +typedef OCassFuture * Ocass_session_connect_t(OCassSession *session, OCassCluster *cluster); + +typedef int Ocass_statement_bind_string_t(OCassStatement *statement, size_t index, const char * value); + +typedef const char * Ocass_error_desc_t(int error); + +typedef Ocass_int64_t Ocass_time_from_epoch_t(Ocass_int64_t epoch_secs); + +typedef Ocass_uint32_t Ocass_date_from_epoch_t(Ocass_int64_t epoch_secs); + +typedef int Ocass_statement_bind_uint32_t(OCassStatement *statement, size_t index, Ocass_uint32_t value); + +typedef int Ocass_statement_bind_int64_t(OCassStatement *statement, size_t index, Ocass_int64_t value); + +/* + * Function pointer definitions. + */ +// mongoc and bson: +extern "C" Obson_new_t *Obson_new; +extern "C" Obson_append_utf8_t *Obson_append_utf8; +extern "C" Obson_append_date_time_t *Obson_append_date_time; +extern "C" Obson_destroy_t *Obson_destroy; + +extern "C" Omongoc_init_t *Omongoc_init; +extern "C" Omongoc_cleanup_t *Omongoc_cleanup; +extern "C" Omongoc_uri_new_with_error_t *Omongoc_uri_new_with_error; +extern "C" Omongoc_client_new_from_uri_t *Omongoc_client_new_from_uri; +extern "C" Omongoc_client_set_appname_t *Omongoc_client_set_appname; +extern "C" Omongoc_client_get_database_t *Omongoc_client_get_database; +extern "C" Omongoc_client_get_collection_t *Omongoc_client_get_collection; +extern "C" Omongoc_collection_insert_one_t *Omongoc_collection_insert_one; +extern "C" Omongoc_collection_destroy_t *Omongoc_collection_destroy; +extern "C" Omongoc_database_destroy_t *Omongoc_database_destroy; +extern "C" Omongoc_uri_destroy_t *Omongoc_uri_destroy; +extern "C" Omongoc_client_destroy_t *Omongoc_client_destroy; + +// Cassandra: +extern "C" Ocass_statement_new_t *Ocass_statement_new; +extern "C" Ocass_statement_free_t *Ocass_statement_free; +extern "C" Ocass_session_execute_t *Ocass_session_execute; +extern "C" Ocass_future_error_code_t *Ocass_future_error_code; +extern "C" Ocass_future_error_message_t *Ocass_future_error_message; +extern "C" Ocass_future_free_t *Ocass_future_free; +extern "C" Ocass_cluster_new_t *Ocass_cluster_new; +extern "C" Ocass_session_new_t *Ocass_session_new; +extern "C" Ocass_cluster_set_credentials_t *Ocass_cluster_set_credentials; +extern "C" Ocass_cluster_set_protocol_version_t *Ocass_cluster_set_protocol_version; +extern "C" Ocass_session_free_t *Ocass_session_free; +extern "C" Ocass_cluster_free_t *Ocass_cluster_free; +extern "C" Ocass_cluster_set_contact_points_t *Ocass_cluster_set_contact_points; +extern "C" Ocass_cluster_set_port_t *Ocass_cluster_set_port; +extern "C" Ocass_session_connect_t *Ocass_session_connect; +extern "C" Ocass_statement_bind_string_t *Ocass_statement_bind_string; +extern "C" Ocass_error_desc_t *Ocass_error_desc; +extern "C" Ocass_time_from_epoch_t *Ocass_time_from_epoch; +extern "C" Ocass_date_from_epoch_t *Ocass_date_from_epoch; +extern "C" Ocass_statement_bind_int64_t *Ocass_statement_bind_int64; +extern "C" Ocass_statement_bind_uint32_t *Ocass_statement_bind_uint32; + +namespace JITServer + { + static bool is_mongoc_init = 0; + + void *loadLibmongoc(); + + void *loadLibbson(); + + void *loadLibcassandra(); + + void unloadDBLib(void *handle); + + void *findDBLibSymbol(void *handle, const char *sym); + + bool loadLibmongocAndSymbols(); + + bool loadLibbsonAndSymbols(); + + bool loadLibcassandraAndSymbols(); + } +#endif //JITSERVER_LOADDBLIBS_HPP diff --git a/runtime/compiler/control/MongoLogger.cpp b/runtime/compiler/control/MongoLogger.cpp new file mode 100644 index 00000000000..c08ecf4e871 --- /dev/null +++ b/runtime/compiler/control/MongoLogger.cpp @@ -0,0 +1,160 @@ +#include "MongoLogger.hpp" +#include +#include +#include +#include +#include +#include "LoadDBLibs.hpp" + +MongoLogger::MongoLogger(const char* databaseIP, uint32_t databasePort, const char* databaseName) + : BasePersistentLogger(databaseIP, databasePort, databaseName) + { + init(); + } + +MongoLogger::MongoLogger(const char* databaseIP, uint32_t databasePort, const char* databaseName, + const char* databaseUsername, const char* databasePassword) + : BasePersistentLogger(databaseIP, databasePort, databaseName, databaseUsername, databasePassword) + { + init(); + } + +MongoLogger::~MongoLogger() + { + //Clean up this mongoc logger. + Omongoc_collection_destroy(_collection); + Omongoc_database_destroy(_db); + Omongoc_client_destroy(_client); + Omongoc_uri_destroy(_uri); + } + +void MongoLogger::init() + { + _uri = NULL; + _collection = NULL; + _db = NULL; + _client = NULL; + } + +char * MongoLogger::constructURI() + { + // Check if we have the database name + if (strcmp(_databaseName,"") == 0) + { + return "jitserver_logs"; + } + + // Check if we have db IP and Port + if (strcmp(_databaseIP,"") == 0) + { + // No IP try localhost + _databaseIP = "127.0.0.1"; + } + if (!_databasePort) + { + // No Port try default MongoDB port + _databasePort = 27017; + } + + // Check if we have credentials + if (strcmp(_databaseUsername,"") != 0) + { + if (strcmp(_databasePassword,"") != 0) + { + sprintf(_uri_string, "mongodb://%s:%s@%s:%u/?authSource=%s", _databaseUsername, _databasePassword, + _databaseIP, _databasePort, _databaseName); + } + else + { + sprintf(_uri_string, "mongodb://%s@%s:%u/?authSource=%s", _databaseUsername, _databaseIP, _databasePort, + _databaseName); + } + } + else + { + sprintf(_uri_string, "mongodb://%s:%u/?authSource=%s", _databaseIP, _databasePort, _databaseName); + } + + return _uri_string; + } + +bool MongoLogger::connect() + { + Obson_error_t error; + + //Validate URI. + _uri = Omongoc_uri_new_with_error(constructURI(), &error); + if (!_uri) + { + fprintf (stderr, + "JITServer: Persistent Logger failed to parse URI: %s\n"\ + "error message: %s\n", + constructURI(), + error.message); + return false; + } + + //Create a client + _client = Omongoc_client_new_from_uri(_uri); + if(!_client) + { + Omongoc_uri_destroy(_uri); + fprintf (stderr, + "JITServer: Persistent Logger failed to create client.\n"\ + "error message: %s\n", + error.message); + return false; + } + + //Register the application name so we can track it in the profile logs + //on the server if we want. + Omongoc_client_set_appname(_client, "jitserver"); + + //Get a handle on the database and collection. + _db = Omongoc_client_get_database(_client, _databaseName); + _collection = Omongoc_client_get_collection (_client, _databaseName, "logs"); + + //Mongo is designed to be always available. Thus there is no "Connection" object + //and you will find that the "Connection" is tested on every read/write. + return true; + } + +void MongoLogger::disconnect() + { + //Does not actually do anything for Mongo as noted in connect() + return; + } + +bool MongoLogger::logMethod(const char* method, uint64_t clientID, const char* logContent) + { + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + int64_t timestamp = t.tv_sec * INT64_C(1000) + t.tv_nsec / 1000000; + /* + * The following constructs and inserts the following JSON structure: + * { + * "method" : "method/package/methodName()", + * "client_id" : "clientid", + * "log" : "big_log", + * "timestamp" : ISODate + * } + */ + Obson_t *insert = Obson_new(); + Obson_error_t error; + Obson_append_utf8(insert, "method", -1, method, -1); + Obson_append_utf8(insert, "client_id", -1, std::to_string(clientID).c_str(), -1); +//TODO: CONVER CLIENTID to CHAR * without using STRING. + Obson_append_utf8(insert, "log", -1, logContent, -1); + Obson_append_date_time(insert, "timestamp", -1, timestamp); + + if (!Omongoc_collection_insert_one(_collection, insert, NULL, NULL, &error)) + { + fprintf(stderr, "JITServer: Mongo Logger failed to insert log.\n" + "error message: %s\n", error.message); + } + + Obson_destroy(insert); + + return true; + } + diff --git a/runtime/compiler/control/MongoLogger.hpp b/runtime/compiler/control/MongoLogger.hpp new file mode 100644 index 00000000000..f1ea794f6a2 --- /dev/null +++ b/runtime/compiler/control/MongoLogger.hpp @@ -0,0 +1,37 @@ +#ifndef MONGOLOGGER_HPP +#define MONGOLOGGER_HPP + +#include "BasePersistentLogger.hpp" +#include "LoadDBLibs.hpp" + +class MongoLogger : public BasePersistentLogger + { +private: + //TODO: Allocate this with OpenJ9 Allocators. + char _uri_string[512]; + Omongoc_uri_t *_uri; + Omongoc_client_t *_client; + Omongoc_database_t *_db; + Omongoc_collection_t *_collection; + + void init(); + char* constructURI(); + +public: + bool connect() override; + + void disconnect() override; + + MongoLogger(const char* databaseIP, uint32_t databasePort, const char* databaseName); + + MongoLogger(const char* databaseIP, uint32_t databasePort, const char* databaseName, + const char* databaseUsername, const char* databasePassword); + + MongoLogger(); + + ~MongoLogger(); + + bool logMethod(const char* method, uint64_t clientID, const char* logContent) override; + }; + +#endif //MONGOLOGGER_HPP diff --git a/runtime/compiler/control/rossa.cpp b/runtime/compiler/control/rossa.cpp index 72a546cdf9a..a7e0a2eae9d 100644 --- a/runtime/compiler/control/rossa.cpp +++ b/runtime/compiler/control/rossa.cpp @@ -111,6 +111,9 @@ #include "net/CommunicationStream.hpp" #include "net/ClientStream.hpp" #include "net/LoadSSLLibs.hpp" +#if defined(PERSISTENT_LOGGING_SUPPORT) +#include "control/LoadDBLibs.hpp" +#endif //defined(PERSISTENT_LOGGING_SUPPORT) #include "runtime/JITClientSession.hpp" #include "runtime/Listener.hpp" #include "runtime/JITServerStatisticsThread.hpp" @@ -1654,6 +1657,25 @@ onLoadInternal( if (!JITServer::loadLibsslAndFindSymbols()) return -1; } +#if defined(PERSISTENT_LOGGING_SUPPORT) +// TODO: Get Flag from CLIENT command line. +// if(TR::Options::getCmdLineOptions()->getOption(TR_PersistentLogging)) +// { +#if defined(MONGO_LOGGER) + if(!JITServer::loadLibmongocAndSymbols() || !JITServer::loadLibbsonAndSymbols() ) + return -1; + if(!JITServer::is_mongoc_init) + { + Omongoc_init(); + JITServer::is_mongoc_init = 1; + } +#endif //defined(MONGO_LOGGER) +#if defined(CASSANDRA_LOGGER) + if(!JITServer::loadLibcassandraAndSymbols()) + return -1; +#endif //defined(CASSANDRA_LOGGER) +// } +#endif //defined(PERSISTENT_LOGGING_SUPPORT) if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER) { diff --git a/runtime/compiler/env/J9PersistentInfo.hpp b/runtime/compiler/env/J9PersistentInfo.hpp index 053a042684c..c5dded0d581 100644 --- a/runtime/compiler/env/J9PersistentInfo.hpp +++ b/runtime/compiler/env/J9PersistentInfo.hpp @@ -133,6 +133,19 @@ class PersistentInfo : public OMR::PersistentInfoConnector _remoteCompilationMode(JITServer::NONE), _JITServerAddress("localhost"), _JITServerPort(38400), +#if defined(PERSISTENT_LOGGING_SUPPORT) + #ifdef CASSANDRA_LOGGER + _JITServerPersistentLoggingDatabasePort(9042), + #endif //CASSANDRA_LOGGER + + #ifdef MONGO_LOGGER + _JITServerPersistentLoggingDatabasePort(27017), + #endif //MONGO_LOGGER + _JITServerPersistentLoggingDatabaseAddress("127.0.0.1"), + _JITServerPersistentLoggingDatabaseUsername("admin"), + _JITServerPersistentLoggingDatabaseName("jitserver_logs"), + _JITServerPersistentLoggingDatabasePassword("password"), +#endif /* defined(PERSISTENT_LOGGING_SUPPORT) */ _socketTimeoutMs(2000), _clientUID(0), #endif /* defined(J9VM_OPT_JITSERVER) */ @@ -307,6 +320,21 @@ class PersistentInfo : public OMR::PersistentInfoConnector void setJITServerPort(uint32_t port) { _JITServerPort = port; } uint64_t getClientUID() const { return _clientUID; } void setClientUID(uint64_t val) { _clientUID = val; } + #if defined(PERSISTENT_LOGGING_SUPPORT) + void setJITServerPersistentLoggingDatabasePort(uint32_t port) {_JITServerPersistentLoggingDatabasePort = port;} + uint32_t getJITServerPersistentLoggingDatabasePort() const { return _JITServerPersistentLoggingDatabasePort; } + void setJITServerPersistentLoggingDatabaseAddress(char *addr) {_JITServerPersistentLoggingDatabaseAddress = addr;} + const char *getJITServerPersistentLoggingDatabaseAddress() const { return _JITServerPersistentLoggingDatabaseAddress; } + + void setJITServerPersistentLoggingDatabaseUsername(char *username) {_JITServerPersistentLoggingDatabaseUsername = username;} + const char *getJITServerPersistentLoggingDatabaseUsername() const { return _JITServerPersistentLoggingDatabaseUsername; } + + void setJITServerPersistentLoggingDatabasePassword(char *password) {_JITServerPersistentLoggingDatabasePassword = password;} + const char *getJITServerPersistentLoggingDatabasePassword() const { return _JITServerPersistentLoggingDatabasePassword; } + + void setJITServerPersistentLoggingDatabaseName(char *name) {_JITServerPersistentLoggingDatabaseName = name;} + const char *getJITServerPersistentLoggingDatabaseName() const { return _JITServerPersistentLoggingDatabaseName; } + # endif /* defined(PERSISTENT_LOGGING_SUPPORT) */ #endif /* defined(J9VM_OPT_JITSERVER) */ private: @@ -394,7 +422,12 @@ class PersistentInfo : public OMR::PersistentInfoConnector #if defined(J9VM_OPT_JITSERVER) JITServer::RemoteCompilationModes _remoteCompilationMode; // JITServer::NONE, JITServer::CLIENT, JITServer::SERVER std::string _JITServerAddress; + const char* _JITServerPersistentLoggingDatabaseAddress; + const char* _JITServerPersistentLoggingDatabaseUsername; + const char* _JITServerPersistentLoggingDatabasePassword; + const char* _JITServerPersistentLoggingDatabaseName; uint32_t _JITServerPort; + uint32_t _JITServerPersistentLoggingDatabasePort; uint32_t _socketTimeoutMs; // timeout for communication sockets used in out-of-process JIT compilation uint64_t _clientUID; #endif /* defined(J9VM_OPT_JITSERVER) */ diff --git a/runtime/compiler/env/j9methodServer.cpp b/runtime/compiler/env/j9methodServer.cpp index 74ed985b811..3166b59e7d7 100644 --- a/runtime/compiler/env/j9methodServer.cpp +++ b/runtime/compiler/env/j9methodServer.cpp @@ -172,7 +172,6 @@ TR_ResolvedJ9JITServerMethod::definingClassFromCPFieldRef(TR::Compilation *comp, auto &cache = getJ9ClassInfo(compInfoPT, _ramClass)._fieldOrStaticDefiningClassCache; cache.insert({cpIndex, resolvedClass}); } - return resolvedClass; } @@ -2292,22 +2291,19 @@ TR_ResolvedRelocatableJ9JITServerMethod::startAddressForInterpreterOfJittedMetho { return ((J9Method *)getNonPersistentIdentifier())->extra; } - TR_OpaqueClassBlock * TR_ResolvedRelocatableJ9JITServerMethod::definingClassFromCPFieldRef(TR::Compilation *comp, int32_t cpIndex, bool isStatic) { TR_OpaqueClassBlock *resolvedClass = TR_ResolvedJ9JITServerMethod::definingClassFromCPFieldRef(comp, cpIndex, isStatic); - if (resolvedClass) - { - bool valid = false; - if (comp->getOption(TR_UseSymbolValidationManager)) - valid = comp->getSymbolValidationManager()->addDefiningClassFromCPRecord(resolvedClass, cp(), cpIndex, isStatic); - else - valid = storeValidationRecordIfNecessary(comp, cp(), cpIndex, isStatic ? TR_ValidateStaticField : TR_ValidateInstanceField, ramMethod()); - if (!valid) - resolvedClass = NULL; - } + bool valid = false; + if (comp->getOption(TR_UseSymbolValidationManager)) + valid = comp->getSymbolValidationManager()->addDefiningClassFromCPRecord(resolvedClass, cp(), cpIndex, isStatic); + else + valid = storeValidationRecordIfNecessary(comp, cp(), cpIndex, isStatic ? TR_ValidateStaticField : TR_ValidateInstanceField, ramMethod()); + + if (!valid) + resolvedClass = NULL; return resolvedClass; } diff --git a/runtime/compiler/env/j9methodServer.hpp b/runtime/compiler/env/j9methodServer.hpp index 73626ca3b60..b1df7e83850 100644 --- a/runtime/compiler/env/j9methodServer.hpp +++ b/runtime/compiler/env/j9methodServer.hpp @@ -319,4 +319,4 @@ class TR_J9ServerMethod : public TR_J9Method public: TR_J9ServerMethod(TR_FrontEnd *trvm, TR_Memory *, J9Class * aClazz, uintptr_t cpIndex); }; -#endif // J9METHODSERVER_H +#endif // J9METHODSERVER_H \ No newline at end of file From 1024582276da3ea16765289a11b13c5918c553b6 Mon Sep 17 00:00:00 2001 From: Ashutosh Mehra Date: Mon, 23 Mar 2020 17:34:33 +0000 Subject: [PATCH 09/61] Add code for terminating JITServer Added new API destroyJITServer to shutdown the JITServer. Also added code to gracefully terminate the Listener thread. Signed-off-by: Ashutosh Mehra --- runtime/compiler/control/DLLMain.cpp | 13 +- runtime/compiler/control/rossa.cpp | 19 +- runtime/compiler/net/ServerStream.cpp | 246 --------------- runtime/compiler/net/ServerStream.hpp | 32 +- runtime/compiler/runtime/CompileService.hpp | 5 +- runtime/compiler/runtime/Listener.cpp | 318 +++++++++++++++++++- runtime/compiler/runtime/Listener.hpp | 40 ++- runtime/j9vm/jvm.c | 36 ++- runtime/jitserver_launcher/jitserver.c | 2 + runtime/oti/jitserver_api.h | 24 ++ runtime/oti/jitserver_error.h | 1 + 11 files changed, 440 insertions(+), 296 deletions(-) diff --git a/runtime/compiler/control/DLLMain.cpp b/runtime/compiler/control/DLLMain.cpp index 7ddf55433dc..53f9a690b75 100644 --- a/runtime/compiler/control/DLLMain.cpp +++ b/runtime/compiler/control/DLLMain.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corp. and others + * Copyright (c) 2000, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -30,6 +30,7 @@ #include "env/VMJ9.h" #include "runtime/IProfiler.hpp" #include "runtime/J9Profiler.hpp" +#include "runtime/Listener.hpp" #include "runtime/codertinit.hpp" #include "rossa.h" @@ -589,6 +590,16 @@ IDATA J9VMDllMain(J9JavaVM* vm, IDATA stage, void * reserved) TR_J9VMBase *trvm = TR_J9VMBase::get(vm->jitConfig, 0); if (!trvm->isAOT_DEPRECATED_DO_NOT_USE() && trvm->_compInfo) { +#if defined(J9VM_OPT_JITSERVER) + if (trvm->_compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER) + { + TR_Listener *listener = ((TR_JitPrivateConfig*)(vm->jitConfig->privateConfig))->listener; + if (listener) + { + listener->stop(); + } + } +#endif /* defined(J9VM_OPT_JITSERVER) */ trvm->_compInfo->stopCompilationThreads(); } JitShutdown(vm->jitConfig); diff --git a/runtime/compiler/control/rossa.cpp b/runtime/compiler/control/rossa.cpp index 72a546cdf9a..2e335caf8a3 100644 --- a/runtime/compiler/control/rossa.cpp +++ b/runtime/compiler/control/rossa.cpp @@ -634,9 +634,22 @@ freeJITConfig(J9JITConfig * jitConfig) extern "C" void jitExclusiveVMShutdownPending(J9VMThread * vmThread) { - #ifndef SMALL_APPTHREAD - getCompilationInfo(vmThread->javaVM->jitConfig)->stopCompilationThreads(); - #endif +#ifndef SMALL_APPTHREAD + J9JavaVM *javaVM = vmThread->javaVM; +#if defined(J9VM_OPT_JITSERVER) + TR::CompilationInfo * compInfo = getCompilationInfo(javaVM->jitConfig); + if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER) + { + TR_Listener *listener = ((TR_JitPrivateConfig*)(javaVM->jitConfig->privateConfig))->listener; + if (listener) + { + listener->stop(); + } + } +#endif /* defined(J9VM_OPT_JITSERVER) */ + + getCompilationInfo(javaVM->jitConfig)->stopCompilationThreads(); +#endif } // Code cache callbacks to be used by the VM diff --git a/runtime/compiler/net/ServerStream.cpp b/runtime/compiler/net/ServerStream.cpp index ead55c56c2c..b60fd6270cf 100644 --- a/runtime/compiler/net/ServerStream.cpp +++ b/runtime/compiler/net/ServerStream.cpp @@ -20,23 +20,7 @@ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception *******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include /* for TCP_NODELAY option */ -#include -#include -#include -#include -#include /// gethostname, read, write -#include #include "ServerStream.hpp" -#include "control/CompilationRuntime.hpp" -#include "env/TRMemory.hpp" -#include "net/LoadSSLLibs.hpp" namespace JITServer { @@ -49,234 +33,4 @@ ServerStream::ServerStream(int connfd, BIO *ssl) initStream(connfd, ssl); _numConnectionsOpened++; } - -SSL_CTX *createSSLContext(TR::PersistentInfo *info) - { - SSL_CTX *ctx = (*OSSL_CTX_new)((*OSSLv23_server_method)()); - - if (!ctx) - { - perror("can't create SSL context"); - (*OERR_print_errors_fp)(stderr); - exit(1); - } - - const char *sessionIDContext = "JITServer"; - (*OSSL_CTX_set_session_id_context)(ctx, (const unsigned char*)sessionIDContext, strlen(sessionIDContext)); - - if ((*OSSL_CTX_set_ecdh_auto)(ctx, 1) != 1) - { - perror("failed to configure SSL ecdh"); - (*OERR_print_errors_fp)(stderr); - exit(1); - } - - TR::CompilationInfo *compInfo = TR::CompilationInfo::get(); - auto &sslKeys = compInfo->getJITServerSslKeys(); - auto &sslCerts = compInfo->getJITServerSslCerts(); - auto &sslRootCerts = compInfo->getJITServerSslRootCerts(); - - TR_ASSERT_FATAL(sslKeys.size() == 1 && sslCerts.size() == 1, "only one key and cert is supported for now"); - TR_ASSERT_FATAL(sslRootCerts.size() == 0, "server does not understand root certs yet"); - - // Parse and set private key - BIO *keyMem = (*OBIO_new_mem_buf)(&sslKeys[0][0], sslKeys[0].size()); - if (!keyMem) - { - perror("cannot create memory buffer for private key (OOM?)"); - (*OERR_print_errors_fp)(stderr); - exit(1); - } - EVP_PKEY *privKey = (*OPEM_read_bio_PrivateKey)(keyMem, NULL, NULL, NULL); - if (!privKey) - { - perror("cannot parse private key"); - (*OERR_print_errors_fp)(stderr); - exit(1); - } - if ((*OSSL_CTX_use_PrivateKey)(ctx, privKey) != 1) - { - perror("cannot use private key"); - (*OERR_print_errors_fp)(stderr); - exit(1); - } - - // Parse and set certificate - BIO *certMem = (*OBIO_new_mem_buf)(&sslCerts[0][0], sslCerts[0].size()); - if (!certMem) - { - perror("cannot create memory buffer for cert (OOM?)"); - (*OERR_print_errors_fp)(stderr); - exit(1); - } - X509 *certificate = (*OPEM_read_bio_X509)(certMem, NULL, NULL, NULL); - if (!certificate) - { - perror("cannot parse cert"); - (*OERR_print_errors_fp)(stderr); - exit(1); - } - if ((*OSSL_CTX_use_certificate)(ctx, certificate) != 1) - { - perror("cannot use cert"); - (*OERR_print_errors_fp)(stderr); - exit(1); - } - - // Verify key and cert are valid - if ((*OSSL_CTX_check_private_key)(ctx) != 1) - { - perror("private key check failed"); - (*OERR_print_errors_fp)(stderr); - exit(1); - } - - // verify server identity using standard method - (*OSSL_CTX_set_verify)(ctx, SSL_VERIFY_PEER, NULL); - - if (TR::Options::getVerboseOption(TR_VerboseJITServer)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Successfully initialized SSL context (%s)\n", (*OOpenSSL_version)(0)); - - return ctx; - } - -static bool -handleOpenSSLConnectionError(int connfd, SSL *&ssl, BIO *&bio, const char *errMsg) -{ - if (TR::Options::getVerboseOption(TR_VerboseJITServer)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "%s: errno=%d", errMsg, errno); - (*OERR_print_errors_fp)(stderr); - - close(connfd); - if (bio) - { - (*OBIO_free_all)(bio); - bio = NULL; - } - if (ssl) - { - (*OSSL_free)(ssl); - ssl = NULL; - } - return false; -} - -static bool -acceptOpenSSLConnection(SSL_CTX *sslCtx, int connfd, BIO *&bio) - { - SSL *ssl = (*OSSL_new)(sslCtx); - if (!ssl) - return handleOpenSSLConnectionError(connfd, ssl, bio, "Error creating SSL connection"); - - (*OSSL_set_accept_state)(ssl); - - if ((*OSSL_set_fd)(ssl, connfd) != 1) - return handleOpenSSLConnectionError(connfd, ssl, bio, "Error setting SSL file descriptor"); - - if ((*OSSL_accept)(ssl) <= 0) - return handleOpenSSLConnectionError(connfd, ssl, bio, "Error accepting SSL connection"); - - bio = (*OBIO_new_ssl)(sslCtx, false); - if (!bio) - return handleOpenSSLConnectionError(connfd, ssl, bio, "Error creating new BIO"); - - if ((*OBIO_ctrl)(bio, BIO_C_SET_SSL, true, (char *)ssl) != 1) // BIO_set_ssl(bio, ssl, true) - return handleOpenSSLConnectionError(connfd, ssl, bio, "Error setting BIO SSL"); - - if (TR::Options::getVerboseOption(TR_VerboseJITServer)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "SSL connection on socket 0x%x, Version: %s, Cipher: %s\n", - connfd, (*OSSL_get_version)(ssl), (*OSSL_get_cipher)(ssl)); - return true; - } - -void -ServerStream::serveRemoteCompilationRequests(BaseCompileDispatcher *compiler, TR::PersistentInfo *info) - { - SSL_CTX *sslCtx = NULL; - if (CommunicationStream::useSSL()) - { - CommunicationStream::initSSL(); - sslCtx = createSSLContext(info); - } - - uint32_t port = info->getJITServerPort(); - uint32_t timeoutMs = info->getSocketTimeout(); - int sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd < 0) - { - perror("can't open server socket"); - exit(1); - } - - // see `man 7 socket` for option explanations - int flag = true; - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flag, sizeof(flag)) < 0) - { - perror("Can't set SO_REUSEADDR"); - exit(-1); - } - if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flag, sizeof(flag)) < 0) - { - perror("Can't set SO_KEEPALIVE"); - exit(-1); - } - - struct sockaddr_in serv_addr; - memset((char *)&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); - serv_addr.sin_port = htons(port); - - if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) - { - perror("can't bind server address"); - exit(1); - } - if (listen(sockfd, SOMAXCONN) < 0) - { - perror("listen failed"); - exit(1); - } - - while (true) - { - struct sockaddr_in cli_addr; - socklen_t clilen = sizeof(cli_addr); - - int connfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); - if (connfd < 0) - { - if (TR::Options::getVerboseOption(TR_VerboseJITServer)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Error accepting connection: errno=%d", errno); - continue; - } - - struct timeval timeoutMsForConnection = {(timeoutMs / 1000), ((timeoutMs % 1000) * 1000)}; - if (setsockopt(connfd, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeoutMsForConnection, sizeof(timeoutMsForConnection)) < 0) - { - perror("Can't set option SO_RCVTIMEO on connfd socket"); - exit(-1); - } - if (setsockopt(connfd, SOL_SOCKET, SO_SNDTIMEO, (void *)&timeoutMsForConnection, sizeof(timeoutMsForConnection)) < 0) - { - perror("Can't set option SO_SNDTIMEO on connfd socket"); - exit(-1); - } - - BIO *bio = NULL; - if (sslCtx && !acceptOpenSSLConnection(sslCtx, connfd, bio)) - continue; - - ServerStream *stream = new (PERSISTENT_NEW) ServerStream(connfd, bio); - - compiler->compile(stream); - } - - // The following piece of code will be executed only if the server shuts down properly - if (sslCtx) - { - (*OSSL_CTX_free)(sslCtx); - (*OEVP_cleanup)(); - } - } } diff --git a/runtime/compiler/net/ServerStream.hpp b/runtime/compiler/net/ServerStream.hpp index c9468a527c4..cbf41bd8910 100644 --- a/runtime/compiler/net/ServerStream.hpp +++ b/runtime/compiler/net/ServerStream.hpp @@ -34,7 +34,6 @@ class SSLInputStream; namespace JITServer { -class BaseCompileDispatcher; /** @class ServerStream @@ -47,7 +46,7 @@ class BaseCompileDispatcher; 2) Create a dedicated thread that will listen for incoming connection requests 3) In this thread, instantiate a CompileDispatcher from a class defined in step (1) E.g.: J9CompileDispatcher handler(jitConfig); - 4) Call "ServerStream::serveRemoteCompilationRequests(&handler, persistentInfo);" + 4) Call "TR_Listener::serveRemoteCompilationRequests(&handler);" which will wait for a connection, accept the connection, create a ServerStream and call handler->compile(stream) for further processing, e.g. add the stream to a compilation queue @@ -227,21 +226,6 @@ class ServerStream : public CommunicationStream return _clientId; } - /** - @brief Function called to deal with incoming connection requests - - This function opens a socket, binds it and then waits for incoming connection - requests by using `accept()` in an infinite loop. Once a connection is accepted - a ServerStream object is created (receiving the newly opened socket descriptor as - a parameter) and passed to the compilation handler. Typically, the compilation - handler places the ServerStream object in a queue and returns immediately so that - other connection requests can be accepted. - Note: because the function does not return, it must be executed on a separate thread. - - @param [in] compiler Object that defines the behavior when a new connection is accepted - @param [in] info Pointer to PersistentInfo which contains the port and the timeout value for the connection - */ - static void serveRemoteCompilationRequests(BaseCompileDispatcher *compiler, TR::PersistentInfo *info); // Statistics static int getNumConnectionsOpened() { return _numConnectionsOpened; } @@ -254,20 +238,6 @@ class ServerStream : public CommunicationStream }; -/** - @class BaseCompileDispatcher - @brief Abstract class defining the interface for the compilation handler - - Typically, an user would derive this class and provide an implementation for "compile()" - An instance of the derived class needs to be passed to serveRemoteCompilationRequests - which internally calls "compile()" - */ -class BaseCompileDispatcher - { -public: - virtual void compile(ServerStream *stream) = 0; - }; - } #endif // SERVER_STREAM_H diff --git a/runtime/compiler/runtime/CompileService.hpp b/runtime/compiler/runtime/CompileService.hpp index da9d884784b..4c2812030e5 100644 --- a/runtime/compiler/runtime/CompileService.hpp +++ b/runtime/compiler/runtime/CompileService.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2019 IBM Corp. and others + * Copyright (c) 2018, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -25,6 +25,7 @@ #include "vmaccess.h" // for acquireVMAccess and releaseVMAccess #include "net/ServerStream.hpp" // for JITServer::BaseCompileDispatcher +#include "runtime/Listener.hpp" struct J9JITConfig; struct J9VMThread; @@ -53,7 +54,7 @@ class VMAccessHolder This handler, 'compile(ServerStream *)', is executed by the listener thread when a new connection request has been received by JITServer */ -class J9CompileDispatcher : public JITServer::BaseCompileDispatcher +class J9CompileDispatcher : public BaseCompileDispatcher { public: J9CompileDispatcher(J9JITConfig *jitConfig) : _jitConfig(jitConfig) { } diff --git a/runtime/compiler/runtime/Listener.cpp b/runtime/compiler/runtime/Listener.cpp index a75b141cb1a..7e371a13c29 100644 --- a/runtime/compiler/runtime/Listener.cpp +++ b/runtime/compiler/runtime/Listener.cpp @@ -20,11 +20,168 @@ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception *******************************************************************************/ -#include "runtime/Listener.hpp" -#include "net/ServerStream.hpp" +#include +#include +#include +#include +#include +#include /* for TCP_NODELAY option */ +#include +#include +#include +#include +#include +#include +#include +#include /// gethostname, read, write +#include "control/CompilationRuntime.hpp" +#include "env/TRMemory.hpp" #include "env/VMJ9.h" +#include "net/CommunicationStream.hpp" +#include "net/LoadSSLLibs.hpp" +#include "net/ServerStream.hpp" #include "runtime/CompileService.hpp" -#include "control/CompilationRuntime.hpp" +#include "runtime/Listener.hpp" + +static SSL_CTX * +createSSLContext(TR::PersistentInfo *info) + { + SSL_CTX *ctx = (*OSSL_CTX_new)((*OSSLv23_server_method)()); + + if (!ctx) + { + perror("can't create SSL context"); + (*OERR_print_errors_fp)(stderr); + exit(1); + } + + const char *sessionIDContext = "JITServer"; + (*OSSL_CTX_set_session_id_context)(ctx, (const unsigned char*)sessionIDContext, strlen(sessionIDContext)); + + if ((*OSSL_CTX_set_ecdh_auto)(ctx, 1) != 1) + { + perror("failed to configure SSL ecdh"); + (*OERR_print_errors_fp)(stderr); + exit(1); + } + + TR::CompilationInfo *compInfo = TR::CompilationInfo::get(); + auto &sslKeys = compInfo->getJITServerSslKeys(); + auto &sslCerts = compInfo->getJITServerSslCerts(); + auto &sslRootCerts = compInfo->getJITServerSslRootCerts(); + + TR_ASSERT_FATAL(sslKeys.size() == 1 && sslCerts.size() == 1, "only one key and cert is supported for now"); + TR_ASSERT_FATAL(sslRootCerts.size() == 0, "server does not understand root certs yet"); + + // Parse and set private key + BIO *keyMem = (*OBIO_new_mem_buf)(&sslKeys[0][0], sslKeys[0].size()); + if (!keyMem) + { + perror("cannot create memory buffer for private key (OOM?)"); + (*OERR_print_errors_fp)(stderr); + exit(1); + } + EVP_PKEY *privKey = (*OPEM_read_bio_PrivateKey)(keyMem, NULL, NULL, NULL); + if (!privKey) + { + perror("cannot parse private key"); + (*OERR_print_errors_fp)(stderr); + exit(1); + } + if ((*OSSL_CTX_use_PrivateKey)(ctx, privKey) != 1) + { + perror("cannot use private key"); + (*OERR_print_errors_fp)(stderr); + exit(1); + } + + // Parse and set certificate + BIO *certMem = (*OBIO_new_mem_buf)(&sslCerts[0][0], sslCerts[0].size()); + if (!certMem) + { + perror("cannot create memory buffer for cert (OOM?)"); + (*OERR_print_errors_fp)(stderr); + exit(1); + } + X509 *certificate = (*OPEM_read_bio_X509)(certMem, NULL, NULL, NULL); + if (!certificate) + { + perror("cannot parse cert"); + (*OERR_print_errors_fp)(stderr); + exit(1); + } + if ((*OSSL_CTX_use_certificate)(ctx, certificate) != 1) + { + perror("cannot use cert"); + (*OERR_print_errors_fp)(stderr); + exit(1); + } + + // Verify key and cert are valid + if ((*OSSL_CTX_check_private_key)(ctx) != 1) + { + perror("private key check failed"); + (*OERR_print_errors_fp)(stderr); + exit(1); + } + + // verify server identity using standard method + (*OSSL_CTX_set_verify)(ctx, SSL_VERIFY_PEER, NULL); + + if (TR::Options::getVerboseOption(TR_VerboseJITServer)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Successfully initialized SSL context (%s)\n", (*OOpenSSL_version)(0)); + + return ctx; + } + +static bool +handleOpenSSLConnectionError(int connfd, SSL *&ssl, BIO *&bio, const char *errMsg) + { + if (TR::Options::getVerboseOption(TR_VerboseJITServer)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "%s: errno=%d", errMsg, errno); + (*OERR_print_errors_fp)(stderr); + + close(connfd); + if (bio) + { + (*OBIO_free_all)(bio); + bio = NULL; + } + if (ssl) + { + (*OSSL_free)(ssl); + ssl = NULL; + } + return false; + } + +static bool +acceptOpenSSLConnection(SSL_CTX *sslCtx, int connfd, BIO *&bio) + { + SSL *ssl = (*OSSL_new)(sslCtx); + if (!ssl) + return handleOpenSSLConnectionError(connfd, ssl, bio, "Error creating SSL connection"); + + (*OSSL_set_accept_state)(ssl); + + if ((*OSSL_set_fd)(ssl, connfd) != 1) + return handleOpenSSLConnectionError(connfd, ssl, bio, "Error setting SSL file descriptor"); + + if ((*OSSL_accept)(ssl) <= 0) + return handleOpenSSLConnectionError(connfd, ssl, bio, "Error accepting SSL connection"); + + bio = (*OBIO_new_ssl)(sslCtx, false); + if (!bio) + return handleOpenSSLConnectionError(connfd, ssl, bio, "Error creating new BIO"); + + if ((*OBIO_ctrl)(bio, BIO_C_SET_SSL, true, (char *)ssl) != 1) // BIO_set_ssl(bio, ssl, true) + return handleOpenSSLConnectionError(connfd, ssl, bio, "Error setting BIO SSL"); + + if (TR::Options::getVerboseOption(TR_VerboseJITServer)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "SSL connection on socket 0x%x, Version: %s, Cipher: %s\n", + connfd, (*OSSL_get_version)(ssl), (*OSSL_get_cipher)(ssl)); + return true; + } TR_Listener::TR_Listener() : _listenerThread(NULL), _listenerMonitor(NULL), _listenerOSThread(NULL), @@ -32,6 +189,139 @@ TR_Listener::TR_Listener() { } +void +TR_Listener::serveRemoteCompilationRequests(BaseCompileDispatcher *compiler) + { + TR::PersistentInfo *info = getCompilationInfo(jitConfig)->getPersistentInfo(); + SSL_CTX *sslCtx = NULL; + if (JITServer::CommunicationStream::useSSL()) + { + JITServer::CommunicationStream::initSSL(); + sslCtx = createSSLContext(info); + } + + uint32_t port = info->getJITServerPort(); + uint32_t timeoutMs = info->getSocketTimeout(); + struct pollfd pfd = {0}; + int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + if (sockfd < 0) + { + perror("can't open server socket"); + exit(1); + } + + // see `man 7 socket` for option explanations + int flag = true; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flag, sizeof(flag)) < 0) + { + perror("Can't set SO_REUSEADDR"); + exit(-1); + } + if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flag, sizeof(flag)) < 0) + { + perror("Can't set SO_KEEPALIVE"); + exit(-1); + } + + struct sockaddr_in serv_addr; + memset((char *)&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(port); + + if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + { + perror("can't bind server address"); + exit(1); + } + if (listen(sockfd, SOMAXCONN) < 0) + { + perror("listen failed"); + exit(1); + } + + pfd.fd = sockfd; + pfd.events = POLLIN; + + while (!getListenerThreadExitFlag()) + { + int32_t rc = 0; + struct sockaddr_in cli_addr; + socklen_t clilen = sizeof(cli_addr); + int connfd = -1; + + rc = poll(&pfd, 1, OPENJ9_LISTENER_POLL_TIMEOUT); + if (getListenerThreadExitFlag()) // if we are exiting, no need to check poll() status + { + break; + } + else if (0 == rc) // poll() timed out and no fd is ready + { + continue; + } + else if (rc < 0) + { + if (errno == EINTR) + { + continue; + } + else + { + perror("error in polling listening socket"); + exit(1); + } + } + else if (pfd.revents != POLLIN) + { + fprintf(stderr, "Unexpected event occurred during poll for new connection: revents=%d\n", pfd.revents); + exit(1); + } + do + { + /* at this stage we should have a valid request for new connection */ + connfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); + if (connfd < 0) + { + if ((EAGAIN != errno) && (EWOULDBLOCK != errno)) + { + if (TR::Options::getVerboseOption(TR_VerboseJITServer)) + { + TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Error accepting connection: errno=%d", errno); + } + } + } + else + { + struct timeval timeoutMsForConnection = {(timeoutMs / 1000), ((timeoutMs % 1000) * 1000)}; + if (setsockopt(connfd, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeoutMsForConnection, sizeof(timeoutMsForConnection)) < 0) + { + perror("Can't set option SO_RCVTIMEO on connfd socket"); + exit(-1); + } + if (setsockopt(connfd, SOL_SOCKET, SO_SNDTIMEO, (void *)&timeoutMsForConnection, sizeof(timeoutMsForConnection)) < 0) + { + perror("Can't set option SO_SNDTIMEO on connfd socket"); + exit(-1); + } + + BIO *bio = NULL; + if (sslCtx && !acceptOpenSSLConnection(sslCtx, connfd, bio)) + continue; + + JITServer::ServerStream *stream = new (PERSISTENT_NEW) JITServer::ServerStream(connfd, bio); + compiler->compile(stream); + } + } while ((-1 != connfd) && !getListenerThreadExitFlag()); + } + + // The following piece of code will be executed only if the server shuts down properly + if (sslCtx) + { + (*OSSL_CTX_free)(sslCtx); + (*OEVP_cleanup)(); + } + } + TR_Listener * TR_Listener::allocate() { TR_Listener * listener = new (PERSISTENT_NEW) TR_Listener(); @@ -63,11 +353,8 @@ static int32_t J9THREAD_PROC listenerThreadProc(void * entryarg) j9thread_set_name(j9thread_self(), "JITServer Listener"); J9CompileDispatcher handler(jitConfig); - TR::PersistentInfo *info = getCompilationInfo(jitConfig)->getPersistentInfo(); - JITServer::ServerStream::serveRemoteCompilationRequests(&handler, info); + listener->serveRemoteCompilationRequests(&handler); - // Note: the following code will never be executed, because - // serveRemoteCompilationRequests() is executed "forever" if (TR::Options::getVerboseOption(TR_VerboseJITServer)) TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Detaching JITServer listening thread"); @@ -123,10 +410,25 @@ void TR_Listener::startListenerThread(J9JavaVM *javaVM) } } -int32_t TR_Listener::waitForListenerThreadExit(J9JavaVM *javaVM) +int32_t +TR_Listener::waitForListenerThreadExit(J9JavaVM *javaVM) { if (NULL != _listenerOSThread) return omrthread_join(_listenerOSThread); else return 0; } + +void +TR_Listener::stop() + { + if (getListenerThread()) + { + _listenerMonitor->enter(); + setListenerThreadExitFlag(); + _listenerMonitor->wait(); + _listenerMonitor->exit(); + TR::Monitor::destroy(_listenerMonitor); + _listenerMonitor = NULL; + } + } diff --git a/runtime/compiler/runtime/Listener.hpp b/runtime/compiler/runtime/Listener.hpp index d82377f6d3c..18e129388af 100644 --- a/runtime/compiler/runtime/Listener.hpp +++ b/runtime/compiler/runtime/Listener.hpp @@ -25,6 +25,7 @@ #include "j9.h" #include "infra/Monitor.hpp" // TR::Monitor +#include "net/ServerStream.hpp" /** @class TR_Listener @@ -34,15 +35,36 @@ Typical sequence executed by a JITServer is: (1) Create a TR_Listener object with "allocate()" function (2) Start a listener thread with listener->startListenerThread(javaVM); - - The current implementation does not provide code for nicely terminating the listener thread. */ + +#define OPENJ9_LISTENER_POLL_TIMEOUT 100 // in milliseconds + +class BaseCompileDispatcher; + class TR_Listener { public: TR_Listener(); static TR_Listener* allocate(); void startListenerThread(J9JavaVM *javaVM); + void stop(); + /** + @brief Function called to deal with incoming connection requests + + This function opens a socket (non-blocking), binds it and then waits for incoming + connection by polling on it with a timeout (see OPENJ9_LISTENER_POLL_TIMEOUT). + If it ever comes out of polling (due to timeout or a new connection request), + it checks the exit flag. If the flag is set, then the thread exits. + Otherwise, it establishes the connection using accept(). + Once a connection is accepted a ServerStream object is created (receiving the newly + opened socket descriptor as a parameter) and passed to the compilation handler. + Typically, the compilation handler places the ServerStream object in a queue and + returns immediately so that other connection requests can be accepted. + Note: it must be executed on a separate thread as it needs to keep listening for new connections. + + @param [in] compiler Object that defines the behavior when a new connection is accepted + */ + void serveRemoteCompilationRequests(BaseCompileDispatcher *compiler); int32_t waitForListenerThreadExit(J9JavaVM *javaVM); void setAttachAttempted(bool b) { _listenerThreadAttachAttempted = b; } bool getAttachAttempted() const { return _listenerThreadAttachAttempted; } @@ -63,4 +85,18 @@ class TR_Listener volatile bool _listenerThreadExitFlag; }; +/** + @class BaseCompileDispatcher + @brief Abstract class defining the interface for the compilation handler + + Typically, an user would derive this class and provide an implementation for "compile()" + An instance of the derived class needs to be passed to serveRemoteCompilationRequests + which internally calls "compile()" + */ +class BaseCompileDispatcher + { +public: + virtual void compile(JITServer::ServerStream *stream) = 0; + }; + #endif diff --git a/runtime/j9vm/jvm.c b/runtime/j9vm/jvm.c index 9f5b56802a3..99d0c01a620 100644 --- a/runtime/j9vm/jvm.c +++ b/runtime/j9vm/jvm.c @@ -294,6 +294,7 @@ static jint formatErrorMessage(int errorCode, char *inBuffer, jint inBufferLengt #if defined(J9VM_OPT_JITSERVER) static int32_t startJITServer(struct JITServer *); static int32_t waitForJITServerTermination(struct JITServer *); +static int32_t destroyJITServer(struct JITServer **); #endif /* J9VM_OPT_JITSERVER */ /** @@ -1473,7 +1474,9 @@ static jint initializeReflectionGlobals(JNIEnv * env, BOOLEAN includeAccessors) * * DLL: jvm */ -jint JNICALL JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *vm_args) { +jint JNICALL +JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *vm_args) +{ return JNI_CreateJavaVM_impl(pvm, penv, vm_args, FALSE); } @@ -1492,6 +1495,7 @@ JITServer_CreateServer(JITServer **jitServer, void *serverArgs) } server->startJITServer = startJITServer; server->waitForJITServerTermination = waitForJITServerTermination; + server->destroyJITServer = destroyJITServer; rc = JNI_CreateJavaVM_impl(&server->jvm, (void **)&env, serverArgs, TRUE); if (JNI_OK != rc) { @@ -1504,6 +1508,7 @@ JITServer_CreateServer(JITServer **jitServer, void *serverArgs) _end: if ((JITSERVER_OK != rc) && (NULL != server)) { free(server); + *jitServer = NULL; } return rc; } @@ -1513,7 +1518,7 @@ JITServer_CreateServer(JITServer **jitServer, void *serverArgs) * * @param jitServer pointer to the JITServer interface * - * @returns zero on success, else negative error code + * @returns JITSERVER_OK on success, else negative error code */ static int32_t startJITServer(JITServer *jitServer) @@ -1543,7 +1548,7 @@ startJITServer(JITServer *jitServer) * * @param jitServer pointer to the JITServer interface * - * @returns zero on success, else negative error code + * @returns JITSERVER_OK on success, else negative error code */ static int32_t waitForJITServerTermination(JITServer *jitServer) @@ -1567,6 +1572,31 @@ waitForJITServerTermination(JITServer *jitServer) } return rc; } + +/** + * Frees the resources allocated by JITServer_CreateServer. + * + * @param jitServer double pointer to the JITServer interface. Must not be NULL + * + * @returns JITSERVER_OK on success, else negative error code + * + * @note on return *jitServer is set to NULL + */ +static int32_t +destroyJITServer(JITServer **jitServer) +{ + JavaVM *vm = (*jitServer)->jvm; + jint rc = (*vm)->DestroyJavaVM(vm); + free(*jitServer); + *jitServer = NULL; + if (JNI_OK == rc) { + rc = JITSERVER_OK; + } else { + rc = JITSERVER_DESTROY_ERROR; + } + return rc; +} + #endif /* J9VM_OPT_JITSERVER */ /* diff --git a/runtime/jitserver_launcher/jitserver.c b/runtime/jitserver_launcher/jitserver.c index a7990b2b9c1..f9a170133be 100644 --- a/runtime/jitserver_launcher/jitserver.c +++ b/runtime/jitserver_launcher/jitserver.c @@ -360,6 +360,8 @@ main(int argc, char *argv[]) goto _end; } + server->destroyJITServer(&server); + free(jvmLibPath); free(options); diff --git a/runtime/oti/jitserver_api.h b/runtime/oti/jitserver_api.h index 7f6f20b016c..11cc2770180 100644 --- a/runtime/oti/jitserver_api.h +++ b/runtime/oti/jitserver_api.h @@ -32,8 +32,32 @@ extern "C" { struct JITServer; /* Forward declaration */ typedef struct JITServer { + /** + * Starts an instance of JITServer. + * + * @param jitServer pointer to the JITServer interface + * + * @returns JITSERVER_OK on success, else negative error code + */ int32_t (* startJITServer)(struct JITServer *); + /** + * Wait for JITServer to terminate. + * + * @param jitServer pointer to the JITServer interface + * + * @returns JITSERVER_OK on success, else negative error code + */ int32_t (* waitForJITServerTermination)(struct JITServer *); + /** + * Frees the resources allocated by JITServer_CreateServer. + * + * @param jitServer double pointer to the JITServer interface. Must not be NULL + * + * @returns JITSERVER_OK on success, else negative error code + * + * @note on return *jitServer is set to NULL + */ + int32_t (* destroyJITServer)(struct JITServer **); JavaVM *jvm; } JITServer; diff --git a/runtime/oti/jitserver_error.h b/runtime/oti/jitserver_error.h index 135d0b90041..87e77cb1632 100644 --- a/runtime/oti/jitserver_error.h +++ b/runtime/oti/jitserver_error.h @@ -30,4 +30,5 @@ #define JITSERVER_STARTUP_FAILED -3 #define JITSERVER_THREAD_ATTACH_FAILED -4 #define JITSERVER_WAIT_TERM_FAILED -5 +#define JITSERVER_DESTROY_ERROR -6 #endif /* jitserver_error_h */ From 3cb5801bd89fcd18af8a94e96443616bea4c16b9 Mon Sep 17 00:00:00 2001 From: Henry Zongaro Date: Thu, 26 Mar 2020 13:29:20 -0400 Subject: [PATCH 10/61] Add query method for class whose instances are zero initializable Define an isZeroInitializable method that indicates whether a class's instances have fields that can be trivially initialized by zeroing memory. For prototype support of value types, a class with a value type field that has not been inlined into the class must have that value type field of its instances initialized with the default value for the value type. The implementation of isZeroInitializable is introduced to detect that case. Signed-off-by: Henry Zongaro --- runtime/compiler/env/J9ClassEnv.cpp | 6 ++++++ runtime/compiler/env/J9ClassEnv.hpp | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/runtime/compiler/env/J9ClassEnv.cpp b/runtime/compiler/env/J9ClassEnv.cpp index ad918d0cd9b..5cb032f3c68 100644 --- a/runtime/compiler/env/J9ClassEnv.cpp +++ b/runtime/compiler/env/J9ClassEnv.cpp @@ -626,3 +626,9 @@ J9::ClassEnv::isValueTypeClass(TR_OpaqueClassBlock *clazz) J9Class *j9class = reinterpret_cast(clazz); return J9_IS_J9CLASS_VALUETYPE(j9class); } + +bool +J9::ClassEnv::isZeroInitializable(TR_OpaqueClassBlock *clazz) + { + return (self()->classFlagsValue(clazz) & J9ClassContainsUnflattenedFlattenables) == 0; + } diff --git a/runtime/compiler/env/J9ClassEnv.hpp b/runtime/compiler/env/J9ClassEnv.hpp index 68b743623c8..7b03702dcd9 100644 --- a/runtime/compiler/env/J9ClassEnv.hpp +++ b/runtime/compiler/env/J9ClassEnv.hpp @@ -89,6 +89,24 @@ class OMR_EXTENSIBLE ClassEnv : public OMR::ClassEnvConnector bool isAbstractClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazzPointer); bool isInterfaceClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazzPointer); bool isValueTypeClass(TR_OpaqueClassBlock *); + + /** + * \brief + * Checks whether instances of the specified class can be trivially initialized by + * "zeroing" their fields. + * In the case of OpenJ9, this tests whether any field is of a value type that has not been + * "flattened" (that is, had the value type's fields inlined into this class). Such a value + * type field must be initialized with the default value of the type. + * + * \param clazz + * The class that is to be checked + * + * \return + * `true` if instances of the specified class can be initialized by zeroing their fields; + * `false` otherwise (that is, if the class has value type fields whose fields have not + * been inlined) + */ + bool isZeroInitializable(TR_OpaqueClassBlock *clazz); bool isEnumClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazzPointer, TR_ResolvedMethod *method); bool isPrimitiveClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazz); bool isAnonymousClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazz); From 6f5db47352fe68f6d064b87ffc4d9677f0852650 Mon Sep 17 00:00:00 2001 From: Marius Pirvu Date: Thu, 2 Apr 2020 09:15:14 -0400 Subject: [PATCH 11/61] Prevent increasing the scratchSpaceLimit on low virtual memory When low virtual memory is detected, the JIT will decrease the `scratchSpaceLimit` (i.e. maximum amount of memory a compilation thread is allowed to use) to 64 MB. This is done only if the current scratchSpaceLimit is still at the default value of 256 MB. However, a recent commit has changed the default scratchSpaceLimit under `-Xtune:virtualized` option to 30 MB. Thus, we may actually increase the scratchSpaceLimit from 30 MB to 64 MB when low virtual memory is detected. This commit adds a check that prevents the increase of the scratchSpaceLimit under low virtual memory conditions. Signed-off-by: Marius Pirvu --- runtime/compiler/control/HookedByTheJit.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/runtime/compiler/control/HookedByTheJit.cpp b/runtime/compiler/control/HookedByTheJit.cpp index 018f9d87f6e..ec208a44e7e 100644 --- a/runtime/compiler/control/HookedByTheJit.cpp +++ b/runtime/compiler/control/HookedByTheJit.cpp @@ -3944,10 +3944,9 @@ void lowerCompilationLimitsOnLowVirtualMemory(TR::CompilationInfo *compInfo, J9V } } - // If the scratch space limit is still the default value, then change it now - if (TR::Options::getScratchSpaceLimit() == (DEFAULT_SCRATCH_SPACE_LIMIT_KB * 1024)) + // Decrease the scratch space limit + if (TR::Options::getScratchSpaceLimit() > TR::Options::getScratchSpaceLimitKBWhenLowVirtualMemory()*1024) { - TR_ASSERT(DEFAULT_SCRATCH_SPACE_LIMIT_KB > TR::Options::getScratchSpaceLimitKBWhenLowVirtualMemory(), "assertion failure"); TR::Options::setScratchSpaceLimit(TR::Options::getScratchSpaceLimitKBWhenLowVirtualMemory() * 1024); if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance)) { From aa5bcee1db39c93b2a7b2113e2851e875a1be755 Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Wed, 1 Apr 2020 11:16:22 -0400 Subject: [PATCH 12/61] Add new AOT not supported exceptions Signed-off-by: Irwin D'Souza --- runtime/compiler/exceptions/AOTFailure.hpp | 32 +++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/runtime/compiler/exceptions/AOTFailure.hpp b/runtime/compiler/exceptions/AOTFailure.hpp index b5ef1b8d3fa..46b3b49b71b 100644 --- a/runtime/compiler/exceptions/AOTFailure.hpp +++ b/runtime/compiler/exceptions/AOTFailure.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2019 IBM Corp. and others + * Copyright (c) 2000, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -60,6 +60,36 @@ class AOTHasInvokeSpecialInInterface : public virtual TR::RecoverableILGenExcept virtual const char* what() const throw() { return "AOT Has Invoke Special in Interface"; } }; +/** + * AOT Has Constant Dynamic exception type. + * + * Thrown when a method that has a constant dynamic is AOT Compiled. + */ +class AOTHasConstantDynamic : public virtual TR::RecoverableILGenException + { + virtual const char* what() const throw() { return "AOT Has Constant Dynamic"; } + }; + +/** + * AOT Has Method Handle Constant exception type. + * + * Thrown when a method that has a method handle constant is AOT Compiled. + */ +class AOTHasMethodHandleConstant : public virtual TR::RecoverableILGenException + { + virtual const char* what() const throw() { return "AOT Has Method Handle Constant"; } + }; + +/** + * AOT Has Method Type Constant exception type. + * + * Thrown when a method that has a method type constant is AOT Compiled. + */ +class AOTHasMethodTypeConstant : public virtual TR::RecoverableILGenException + { + virtual const char* what() const throw() { return "AOT Has Method Type Constant"; } + }; + /** * AOT Relocation Failure exception type. * From c33a12076bddcf0a2c13b00d8800fe817f7169ae Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Wed, 1 Apr 2020 11:16:33 -0400 Subject: [PATCH 13/61] Abort ILGen for non supported features in AOT Constant Dynamic, Method Handle Constant, and Method Type Constant is not currently supported in AOT. Therefore, this commit throws the appropriate exception in ILGen if this condition is met. However, because all of these exceptions are a TR::RecoverableILGenException, if the compiler is generating IL for an inlined method, it will not abort the compile, but simply refuse to inline that particular method. Signed-off-by: Irwin D'Souza --- runtime/compiler/ilgen/Walker.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/runtime/compiler/ilgen/Walker.cpp b/runtime/compiler/ilgen/Walker.cpp index 0ab6f77e688..5b7d0390d04 100644 --- a/runtime/compiler/ilgen/Walker.cpp +++ b/runtime/compiler/ilgen/Walker.cpp @@ -5456,6 +5456,13 @@ TR_J9ByteCodeIlGenerator::loadFromCP(TR::DataType type, int32_t cpIndex) case TR::Address: if (method()->isConstantDynamic(cpIndex)) { + if (comp()->compileRelocatableCode()) + { + if (comp()->getOption(TR_TraceILGen)) + traceMsg(comp(), " Constant Dynamic not supported in AOT.\n"); + comp()->failCompilation("Constant Dynamic not supported in AOT."); + } + bool isCondyUnresolved = _methodSymbol->getResolvedMethod()->isUnresolvedConstantDynamic(cpIndex); J9UTF8 *returnTypeUtf8 = (J9UTF8 *)_methodSymbol->getResolvedMethod()->getConstantDynamicTypeFromCP(cpIndex); int returnTypeUtf8Length = J9UTF8_LENGTH(returnTypeUtf8); @@ -5678,11 +5685,23 @@ TR_J9ByteCodeIlGenerator::loadFromCP(TR::DataType type, int32_t cpIndex) } else if (method()->isMethodHandleConstant(cpIndex)) { + if (comp()->compileRelocatableCode()) + { + if (comp()->getOption(TR_TraceILGen)) + traceMsg(comp(), " Method Handle Constant not supported in AOT.\n"); + comp()->failCompilation("Method Handle Constant not supported in AOT."); + } loadSymbol(TR::aload, symRefTab()->findOrCreateMethodHandleSymbol(_methodSymbol, cpIndex)); } else { TR_ASSERT(method()->isMethodTypeConstant(cpIndex), "Address-type CP entry %d must be class, string, methodHandle, or methodType", cpIndex); + if (comp()->compileRelocatableCode()) + { + if (comp()->getOption(TR_TraceILGen)) + traceMsg(comp(), " Method Type Constant not supported in AOT.\n"); + comp()->failCompilation("Method Type Constant not supported in AOT."); + } loadSymbol(TR::aload, symRefTab()->findOrCreateMethodTypeSymbol(_methodSymbol, cpIndex)); } break; From b61f2c8f2ce36ba3db652d4a557a3cac24de2e2a Mon Sep 17 00:00:00 2001 From: Harry Yu Date: Thu, 2 Apr 2020 11:32:13 -0400 Subject: [PATCH 14/61] Use _binaryBufferStart as reference for offset calculations JITServer has been using getCodeStart() as the reference for offset calculations when dealing with the patching involved in runtime assumptions. However, this reference is dependent not only on the startPC but also on the size of preprologue. This will create problems if we use the reference before we generate the preprologue or have determined the preprologue size. We use _binaryBufferStart to remove the preprologue size depedency. Issue: #8786 Signed-off-by: Harry Yu --- runtime/compiler/codegen/J9CodeGenerator.cpp | 10 +++++----- .../compiler/control/JITClientCompilationThread.cpp | 2 +- runtime/compiler/runtime/RuntimeAssumptions.hpp | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/runtime/compiler/codegen/J9CodeGenerator.cpp b/runtime/compiler/codegen/J9CodeGenerator.cpp index 971b8c2cf27..c55bf65fb72 100644 --- a/runtime/compiler/codegen/J9CodeGenerator.cpp +++ b/runtime/compiler/codegen/J9CodeGenerator.cpp @@ -4654,7 +4654,7 @@ J9::CodeGenerator::registerAssumptions() if (self()->comp()->isOutOfProcessCompilation()) { // For JITServer we need to build a list of assumptions that will be sent to client at end of compilation - intptr_t offset = i->getBinaryEncoding() - self()->getCodeStart(); + intptr_t offset = i->getBinaryEncoding() - self()->getBinaryBufferStart(); SerializedRuntimeAssumption* sar = new (self()->trHeapMemory()) SerializedRuntimeAssumption(RuntimeAssumptionOnRegisterNative, (uintptr_t)method, offset); self()->comp()->getSerializedRuntimeAssumptions().push_front(sar); @@ -4673,7 +4673,7 @@ J9::CodeGenerator::jitAddPicToPatchOnClassUnload(void *classPointer, void *addre #ifdef J9VM_OPT_JITSERVER if (self()->comp()->isOutOfProcessCompilation()) { - intptr_t offset = (uint8_t*)addressToBePatched - self()->getCodeStart(); + intptr_t offset = (uint8_t*)addressToBePatched - self()->getBinaryBufferStart(); SerializedRuntimeAssumption* sar = new (self()->trHeapMemory()) SerializedRuntimeAssumption(RuntimeAssumptionOnClassUnload, (uintptr_t)classPointer, offset, sizeof(uintptr_t)); self()->comp()->getSerializedRuntimeAssumptions().push_front(sar); @@ -4692,7 +4692,7 @@ J9::CodeGenerator::jitAdd32BitPicToPatchOnClassUnload(void *classPointer, void * #ifdef J9VM_OPT_JITSERVER if (self()->comp()->isOutOfProcessCompilation()) { - intptr_t offset = (uint8_t*)addressToBePatched - self()->getCodeStart(); + intptr_t offset = (uint8_t*)addressToBePatched - self()->getBinaryBufferStart(); SerializedRuntimeAssumption* sar = new (self()->trHeapMemory()) SerializedRuntimeAssumption(RuntimeAssumptionOnClassUnload, (uintptr_t)classPointer, offset, 4); self()->comp()->getSerializedRuntimeAssumptions().push_front(sar); @@ -4715,7 +4715,7 @@ J9::CodeGenerator::jitAddPicToPatchOnClassRedefinition(void *classPointer, void { TR_RuntimeAssumptionKind kind = unresolved ? RuntimeAssumptionOnClassRedefinitionUPIC : RuntimeAssumptionOnClassRedefinitionPIC; uintptr_t key = unresolved ? (uintptr_t)-1 : (uintptr_t)classPointer; - intptr_t offset = (uint8_t*)addressToBePatched - self()->getCodeStart(); + intptr_t offset = (uint8_t*)addressToBePatched - self()->getBinaryBufferStart(); SerializedRuntimeAssumption* sar = new (self()->trHeapMemory()) SerializedRuntimeAssumption(kind, key, offset, sizeof(uintptr_t)); self()->comp()->getSerializedRuntimeAssumptions().push_front(sar); @@ -4739,7 +4739,7 @@ J9::CodeGenerator::jitAdd32BitPicToPatchOnClassRedefinition(void *classPointer, { TR_RuntimeAssumptionKind kind = unresolved ? RuntimeAssumptionOnClassRedefinitionUPIC : RuntimeAssumptionOnClassRedefinitionPIC; uintptr_t key = unresolved ? (uintptr_t)-1 : (uintptr_t)classPointer; - intptr_t offset = (uint8_t*)addressToBePatched - self()->getCodeStart(); + intptr_t offset = (uint8_t*)addressToBePatched - self()->getBinaryBufferStart(); SerializedRuntimeAssumption* sar = new (self()->trHeapMemory()) SerializedRuntimeAssumption(kind, key, offset, 4); self()->comp()->getSerializedRuntimeAssumptions().push_front(sar); diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index d62d62935a4..c7aae3c14be 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -3288,7 +3288,7 @@ remoteCompile( // this list will be copied into the metadata for (auto& it : serializedRuntimeAssumptions) { - uint8_t *addrToPatch = (uint8_t*)(metaData->startPC + it.getOffsetFromStartPC()); + uint8_t *addrToPatch = (uint8_t*)(metaData->codeCacheAlloc + it.getOffsetFromBinaryBufferStart()); switch (it.getKind()) { case RuntimeAssumptionOnRegisterNative: diff --git a/runtime/compiler/runtime/RuntimeAssumptions.hpp b/runtime/compiler/runtime/RuntimeAssumptions.hpp index 6c7caf4c7bc..27fd09dd29b 100644 --- a/runtime/compiler/runtime/RuntimeAssumptions.hpp +++ b/runtime/compiler/runtime/RuntimeAssumptions.hpp @@ -293,16 +293,16 @@ class TR_UnloadedClassPicSite : public OMR::ValueModifyRuntimeAssumption struct SerializedRuntimeAssumption { SerializedRuntimeAssumption(TR_RuntimeAssumptionKind kind, uintptr_t key, intptr_t offset, uint32_t size = 0) - : _kind(kind), _key(key), _offsetFromStartPC(offset), _size(size) {} + : _kind(kind), _key(key), _offsetFromBinaryBufferStart(offset), _size(size) {} TR_RuntimeAssumptionKind getKind() const { return _kind; } uintptr_t getKey() const { return _key; } - intptr_t getOffsetFromStartPC() const { return _offsetFromStartPC; } + intptr_t getOffsetFromBinaryBufferStart() const { return _offsetFromBinaryBufferStart; } uint32_t getSize() const { return _size; } TR_RuntimeAssumptionKind _kind; uint32_t _size; uintptr_t _key; - intptr_t _offsetFromStartPC; // can be negative + intptr_t _offsetFromBinaryBufferStart; }; #endif // J9VM_OPT_JITSERVER From 5b2b56e4af8d8779b5c7d7a4949d9b1a33a24d5b Mon Sep 17 00:00:00 2001 From: Annabelle Huo Date: Thu, 2 Apr 2020 12:35:14 -0400 Subject: [PATCH 15/61] Fix known object table update at the server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When getIndexAt() is called, the passed-in parameter objectReferenceLocation is not necessarily the reference that’s stored in the known object table. It should not be used to pass into updateKnownObjectTableAtServer() to update the table at the server. Pass the reference object location from the client to updateKnownObjectTableAtServer() in getOrCreateIndexAt() instead of the one passed in from the caller of getOrCreateIndexAt(). Fixes #8952 Signed-off-by: Annabelle Huo --- .../control/JITClientCompilationThread.cpp | 5 +++-- runtime/compiler/env/J9KnownObjectTable.cpp | 20 +++++++++++-------- runtime/compiler/env/J9KnownObjectTable.hpp | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index d62d62935a4..9f5cfc5adc6 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -2652,8 +2652,9 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes break; case MessageType::KnownObjectTable_getOrCreateIndexAt: { - uintptr_t *objectPointerReference = std::get<0>(client->getRecvData()); - client->write(response, knot->getOrCreateIndexAt(objectPointerReference)); + uintptr_t *objectPointerReferenceServerQuery = std::get<0>(client->getRecvData()); + TR::KnownObjectTable::Index index = knot->getOrCreateIndexAt(objectPointerReferenceServerQuery); + client->write(response, index, knot->getPointerLocation(index)); } break; case MessageType::KnownObjectTable_getPointer: diff --git a/runtime/compiler/env/J9KnownObjectTable.cpp b/runtime/compiler/env/J9KnownObjectTable.cpp index 2d12016bfdc..b16f76c3c3a 100644 --- a/runtime/compiler/env/J9KnownObjectTable.cpp +++ b/runtime/compiler/env/J9KnownObjectTable.cpp @@ -232,9 +232,12 @@ J9::KnownObjectTable::getOrCreateIndexAt(uintptr_t *objectReferenceLocation) { auto stream = TR::CompilationInfo::getStream(); stream->write(JITServer::MessageType::KnownObjectTable_getOrCreateIndexAt, objectReferenceLocation); - result = std::get<0>(stream->read()); + auto recv = stream->read(); - updateKnownObjectTableAtServer(result, objectReferenceLocation); + result = std::get<0>(recv); + uintptr_t *objectReferenceLocationClient = std::get<1>(recv); + + updateKnownObjectTableAtServer(result, objectReferenceLocationClient); } else #endif /* defined(J9VM_OPT_JITSERVER) */ @@ -324,10 +327,10 @@ J9::KnownObjectTable::getPointerLocation(Index index) #if defined(J9VM_OPT_JITSERVER) void -J9::KnownObjectTable::updateKnownObjectTableAtServer(Index index, uintptr_t *objectReferenceLocation) +J9::KnownObjectTable::updateKnownObjectTableAtServer(Index index, uintptr_t *objectReferenceLocationClient) { TR_ASSERT_FATAL(self()->comp()->isOutOfProcessCompilation(), "updateKnownObjectTableAtServer should only be called at the server"); - TR_ASSERT(objectReferenceLocation, "objectReferenceLocation should not be NULL"); + TR_ASSERT(objectReferenceLocationClient, "objectReferenceLocationClient should not be NULL"); if (index == TR::KnownObjectTable::UNKNOWN) return; @@ -337,13 +340,14 @@ J9::KnownObjectTable::updateKnownObjectTableAtServer(Index index, uintptr_t *obj if (index == nextIndex) { _references.setSize(nextIndex+1); - _references[nextIndex] = objectReferenceLocation; + _references[nextIndex] = objectReferenceLocationClient; } else if (index < nextIndex) { - TR_ASSERT((objectReferenceLocation == _references[index]), "_references[%d]=%p is not the same as the client KOT[%d]=%p. _references.size()=%u", - index, _references[index], index, objectReferenceLocation, nextIndex); - _references[index] = objectReferenceLocation; + TR_ASSERT((objectReferenceLocationClient == _references[index]), + "comp %p: server _references[%d]=%p is not the same as the client _references[%d]=%p (total size = %u)", + self()->comp(), index, _references[index], index, objectReferenceLocationClient, nextIndex); + _references[index] = objectReferenceLocationClient; } else { diff --git a/runtime/compiler/env/J9KnownObjectTable.hpp b/runtime/compiler/env/J9KnownObjectTable.hpp index e4c193c116d..d870ba4b4d4 100644 --- a/runtime/compiler/env/J9KnownObjectTable.hpp +++ b/runtime/compiler/env/J9KnownObjectTable.hpp @@ -104,7 +104,7 @@ class OMR_EXTENSIBLE KnownObjectTable : public OMR::KnownObjectTableConnector uintptr_t getPointer(Index index); #if defined(J9VM_OPT_JITSERVER) - void updateKnownObjectTableAtServer(Index index, uintptr_t *objectReferenceLocation); + void updateKnownObjectTableAtServer(Index index, uintptr_t *objectReferenceLocationClient); void getKnownObjectTableDumpInfo(std::vector &knotDumpInfoList); #endif /* defined(J9VM_OPT_JITSERVER) */ From 161bf2aa5f64102ff1a3946a1f9d2d7544bb8f6f Mon Sep 17 00:00:00 2001 From: Pushkar Bettadpur Date: Tue, 31 Mar 2020 17:31:45 -0400 Subject: [PATCH 16/61] Enable if present, the miscellaneous-instruction-extention facility 2 z14 systems have a multiple facilities for miscellaneous-instruction-extensions (MIE). This commit looks for the presence of the MIE-2 facility and if available, sets the associated flag. Signed-off-by: Pushkar Bettadpur --- runtime/compiler/z/env/J9CPU.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/runtime/compiler/z/env/J9CPU.cpp b/runtime/compiler/z/env/J9CPU.cpp index 1ba0c868f5c..bfffb606baa 100644 --- a/runtime/compiler/z/env/J9CPU.cpp +++ b/runtime/compiler/z/env/J9CPU.cpp @@ -269,6 +269,11 @@ CPU::initializeS390ProcessorFeatures() if (TR::Compiler->target.cpu.getSupportsArch(TR::CPU::z14)) { + if (j9sysinfo_processor_has_feature(processorDesc, J9PORT_S390_FEATURE_MISCELLANEOUS_INSTRUCTION_EXTENSION_2)) + { + TR::Compiler->target.cpu.setSupportsMiscellaneousInstructionExtensions2Facility(true); + } + if (j9sysinfo_processor_has_feature(processorDesc, J9PORT_S390_FEATURE_VECTOR_PACKED_DECIMAL)) { TR::Compiler->target.cpu.setSupportsVectorPackedDecimalFacility(true); From 06545b9a59f7416c73347bc9f64dc5e48c4e4f09 Mon Sep 17 00:00:00 2001 From: Chase Buhler Date: Thu, 2 Apr 2020 14:44:42 -0600 Subject: [PATCH 17/61] Fist address freedback stuff --- .../compiler/control/BasePersistentLogger.hpp | 2 +- runtime/compiler/control/HookedByTheJit.cpp | 14 +-- runtime/compiler/control/J9Options.cpp | 105 ++++++++++-------- .../control/JITServerCompilationThread.cpp | 75 ++++++------- runtime/compiler/control/LoadDBLibs.cpp | 14 ++- runtime/compiler/control/LoadDBLibs.hpp | 28 ++++- runtime/compiler/control/MongoLogger.cpp | 2 +- runtime/compiler/control/MongoLogger.hpp | 2 +- runtime/compiler/control/rossa.cpp | 43 +++---- runtime/compiler/env/J9PersistentInfo.hpp | 53 ++++----- 10 files changed, 185 insertions(+), 153 deletions(-) diff --git a/runtime/compiler/control/BasePersistentLogger.hpp b/runtime/compiler/control/BasePersistentLogger.hpp index 1e6f4eb73c6..d18cc955ca8 100644 --- a/runtime/compiler/control/BasePersistentLogger.hpp +++ b/runtime/compiler/control/BasePersistentLogger.hpp @@ -15,7 +15,7 @@ class BasePersistentLogger virtual bool connect() = 0; virtual void disconnect() = 0; - BasePersistentLogger( const char * databaseIP, uint32_t databasePort, const char * databaseName) + BasePersistentLogger(const char * databaseIP, uint32_t databasePort, const char * databaseName) { _databaseIP = databaseIP; _databasePort = databasePort; diff --git a/runtime/compiler/control/HookedByTheJit.cpp b/runtime/compiler/control/HookedByTheJit.cpp index b7c996ab923..633c63db6c5 100644 --- a/runtime/compiler/control/HookedByTheJit.cpp +++ b/runtime/compiler/control/HookedByTheJit.cpp @@ -82,10 +82,10 @@ #include "runtime/JITServerIProfiler.hpp" #include "runtime/JITServerStatisticsThread.hpp" #include "runtime/Listener.hpp" -#if defined(MONGO_LOGGER) -#include "control/LoadDBLibs.hpp" -#endif // defined(MONGO_LOGGER) -#endif +//#if defined(MONGO_LOGGER) +//#include "control/LoadDBLibs.hpp" +//#endif // defined(MONGO_LOGGER) +#endif // defined(J9VM_OPT_JITSERVER) extern "C" { struct J9JavaVM; @@ -4749,9 +4749,9 @@ void JitShutdown(J9JITConfig * jitConfig) { statsThreadObj->stopStatisticsThread(jitConfig); } -#if defined(MONGO_LOGGER) - Omongoc_cleanup(); -#endif // defined(MONGOLOGGER) +//#if defined(MONGO_LOGGER) +// JITServer::cleanupMongoC(); +//#endif // defined(MONGO_LOGGER) #endif TR_DebuggingCounters::report(); diff --git a/runtime/compiler/control/J9Options.cpp b/runtime/compiler/control/J9Options.cpp index a2138b2b605..eb73c497691 100644 --- a/runtime/compiler/control/J9Options.cpp +++ b/runtime/compiler/control/J9Options.cpp @@ -1074,25 +1074,25 @@ static void JITServerParseCommonOptions(J9JavaVM *vm, TR::CompilationInfo *compI const char *xxJITServerSSLKeyOption = "-XX:JITServerSSLKey="; const char *xxJITServerSSLCertOption = "-XX:JITServerSSLCert="; const char *xxJITServerSSLRootCertsOption = "-XX:JITServerSSLRootCerts="; - #ifdef PERSISTENT_LOGGING_SUPPORT - const char *xxJITServerPersistentLoggingDatabasePortOption = "-XX:JITServerPersistentLoggingDatabasePort="; - const char *xxJITServerPersistentLoggingDatabaseAddressOption = "-XX:JITServerPersistentLoggingDatabaseAddress="; - const char *xxJITServerPersistentLoggingDatabaseNameOption = "-XX:JITServerPersistentLoggingDatabaseName="; - const char *xxJITServerPersistentLoggingDatabaseUsernameOption = "-XX:JITServerPersistentLoggingDatabaseUsername="; - const char *xxJITServerPersistentLoggingDatabasePasswordOption = "-XX:JITServerPersistentLoggingDatabasePassword="; - #endif // PERSISTENT_LOGGING_SUPPORT int32_t xxJITServerPortArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPortOption, 0); int32_t xxJITServerTimeoutArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerTimeoutOption, 0); int32_t xxJITServerSSLKeyArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerSSLKeyOption, 0); int32_t xxJITServerSSLCertArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerSSLCertOption, 0); int32_t xxJITServerSSLRootCertsArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerSSLRootCertsOption, 0); - #ifdef PERSISTENT_LOGGING_SUPPORT - int32_t xxJITServerPersistentLoggingDatabasePortArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabasePortOption, 0); - int32_t xxJITServerPersistentLoggingDatabaseAddressArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseAddressOption, 0); - int32_t xxJITServerPersistentLoggingDatabaseNameArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseNameOption, 0); - int32_t xxJITServerPersistentLoggingDatabaseUsernameArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseUsernameOption, 0); - int32_t xxJITServerPersistentLoggingDatabasePasswordArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabasePasswordOption, 0); - #endif // PERSISTENT_LOGGING_SUPPORT +#if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) + const char *xxJITServerPersistentLoggingOption = "-XX:JITServerPersistentLogging="; + const char *xxJITServerPersistentLoggingDatabasePortOption = "-XX:JITServerPersistentLoggingDatabasePort="; + const char *xxJITServerPersistentLoggingDatabaseAddressOption = "-XX:JITServerPersistentLoggingDatabaseAddress="; + const char *xxJITServerPersistentLoggingDatabaseNameOption = "-XX:JITServerPersistentLoggingDatabaseName="; + const char *xxJITServerPersistentLoggingDatabaseUsernameOption = "-XX:JITServerPersistentLoggingDatabaseUsername="; + const char *xxJITServerPersistentLoggingDatabasePasswordOption = "-XX:JITServerPersistentLoggingDatabasePassword="; + int32_t xxJITServerPersistentLoggingArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingOption, 0); + int32_t xxJITServerPersistentLoggingDatabasePortArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabasePortOption, 0); + int32_t xxJITServerPersistentLoggingDatabaseAddressArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseAddressOption, 0); + int32_t xxJITServerPersistentLoggingDatabaseNameArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseNameOption, 0); + int32_t xxJITServerPersistentLoggingDatabaseUsernameArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseUsernameOption, 0); + int32_t xxJITServerPersistentLoggingDatabasePasswordArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabasePasswordOption, 0); +#endif // defined(MONGO_LOGGER) || ... if (xxJITServerPortArgIndex >= 0) { @@ -1101,41 +1101,50 @@ static void JITServerParseCommonOptions(J9JavaVM *vm, TR::CompilationInfo *compI if (ret == OPTION_OK) compInfo->getPersistentInfo()->setJITServerPort(port); } - #ifdef PERSISTENT_LOGGING_SUPPORT - if (xxJITServerPersistentLoggingDatabasePortArgIndex >= 0) - { - uint32_t port=0; - IDATA ret = GET_INTEGER_VALUE(xxJITServerPersistentLoggingDatabasePortArgIndex, xxJITServerPersistentLoggingDatabasePortOption, port); - if (ret == OPTION_OK) - compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabasePort(port); - } - if (xxJITServerPersistentLoggingDatabaseUsernameArgIndex >= 0) - { - char *username = NULL; - GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabaseUsernameArgIndex, '=', &username); - compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabaseUsername(username); - } - if (xxJITServerPersistentLoggingDatabaseNameArgIndex >= 0) - { - char *name = NULL; - GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabaseNameArgIndex, '=', &name); - compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabaseName(name); - } - if (xxJITServerPersistentLoggingDatabasePasswordArgIndex >= 0) - { - char *password = NULL; - GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabasePasswordArgIndex, '=', &password); - compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabasePassword(password); - } - - if (xxJITServerPersistentLoggingDatabaseAddressArgIndex >= 0) - { - char *address = NULL; - GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabaseAddressArgIndex, '=', &address); - compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabaseAddress(address); - } - #endif // PERSISTENT_LOGGING_SUPPORT +#if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) + if (xxJITServerPersistentLoggingArgIndex >= 0) + { + bool enable = false; + IDATA ret = GET_INTEGER_VALUE(xxJITServerPersistentLoggingArgIndex, xxJITServerPersistentLoggingOption, enable); + if (ret == OPTION_OK) + compInfo->getPersistentInfo()->setJITServerPersistentLogging(enable); + } + if (xxJITServerPersistentLoggingDatabasePortArgIndex >= 0) + { + uint32_t port=0; + IDATA ret = GET_INTEGER_VALUE(xxJITServerPersistentLoggingDatabasePortArgIndex, xxJITServerPersistentLoggingDatabasePortOption, port); + if (ret == OPTION_OK) + compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabasePort(port); + } + if (xxJITServerPersistentLoggingDatabaseUsernameArgIndex >= 0) + { + char *username = NULL; + GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabaseUsernameArgIndex, '=', &username); + compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabaseUsername(username); + } + if (xxJITServerPersistentLoggingDatabaseNameArgIndex >= 0) + { + char *name = NULL; + GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabaseNameArgIndex, '=', &name); + compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabaseName(name); + } + + if (xxJITServerPersistentLoggingDatabasePasswordArgIndex >= 0) + { + char *password = NULL; + GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabasePasswordArgIndex, '=', &password); + compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabasePassword(password); + } + + if (xxJITServerPersistentLoggingDatabaseAddressArgIndex >= 0) + { + char *address = NULL; + GET_OPTION_VALUE(xxJITServerPersistentLoggingDatabaseAddressArgIndex, '=', &address); + compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabaseAddress(address); + } +#endif // defined(MONGO_LOGGER) || ... + if (xxJITServerTimeoutArgIndex >= 0) { uint32_t timeoutMs=0; diff --git a/runtime/compiler/control/JITServerCompilationThread.cpp b/runtime/compiler/control/JITServerCompilationThread.cpp index b81b5fb2355..dedab4fcb94 100644 --- a/runtime/compiler/control/JITServerCompilationThread.cpp +++ b/runtime/compiler/control/JITServerCompilationThread.cpp @@ -26,14 +26,6 @@ #include "control/CompilationRuntime.hpp" #include "control/MethodToBeCompiled.hpp" #include "control/JITServerHelpers.hpp" -#ifdef CASSANDRA_LOGGER -#include "control/CassandraLogger.hpp" -#include -#endif // CASSANDRA_LOGGER -#ifdef MONGO_LOGGER -#include "control/MongoLogger.hpp" -#include -#endif // MONGO_LOGGER #include "env/ClassTableCriticalSection.hpp" #include "env/VMAccessCriticalSection.hpp" #include "env/JITServerPersistentCHTable.hpp" @@ -45,6 +37,12 @@ #include "net/ServerStream.hpp" #include "jitprotos.h" #include "vmaccess.h" +#ifdef CASSANDRA_LOGGER +#include "control/CassandraLogger.hpp" +#endif // CASSANDRA_LOGGER +#ifdef MONGO_LOGGER +#include "control/MongoLogger.hpp" +#endif // MONGO_LOGGER /** @@ -91,59 +89,56 @@ outOfProcessCompilationEnd( // Pack log file to send to client std::string logFileStr = TR::Options::packLogFile(comp->getOutFile()); - std::cout << "Pre Persistent Logging Section" << std::endl; - std::cout << comp->getOption(TR_PersistentLogging) << std::endl; -#ifdef PERSISTENT_LOGGING_SUPPORT - if (comp->getOption(TR_PersistentLogging)) + +#if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) + printf("Persistent Logging enabled\n"); + fflush(stdout); + if (compInfoPT->getCompilationInfo()->getPersistentInfo()->getJITServerPersistentLogging() + && comp->getOption(TR_PersistentLogging)) //Check both server and client enable persistent logging. { uint64_t clientUID = entry->getClientUID(); const char* methodSignature = compInfoPT->getCompilation()->signature(); TR::PersistentInfo* persistentInfo = compInfoPT->getCompilationInfo()->getPersistentInfo(); printf("Persistent Logging enabled\n"); - printf("Found Client ID %llu\n", clientUID); - printf("potential method full name: %s\n",methodSignature); +// printf("Found Client ID %llu\n", clientUID); +// printf("potential method full name: %s\n",methodSignature); uint32_t persistentLoggingDatabasePort = persistentInfo->getJITServerPersistentLoggingDatabasePort(); - printf("what is the persistent logging database port ? %lu\n",persistentLoggingDatabasePort); +// printf("what is the persistent logging database port ? %lu\n",persistentLoggingDatabasePort); const char* persistentLoggingDatabaseAddress = persistentInfo->getJITServerPersistentLoggingDatabaseAddress(); - std::cout << "what is the persistent logging database Address ? " << persistentLoggingDatabaseAddress << std::endl; +// std::cout << "what is the persistent logging database Address ? " << persistentLoggingDatabaseAddress << std::endl; const char* persistentLoggingDatabaseUsername = persistentInfo->getJITServerPersistentLoggingDatabaseUsername(); - std::cout << "what is the persistent logging database Username ? " << persistentLoggingDatabaseUsername << std::endl; +// std::cout << "what is the persistent logging database Username ? " << persistentLoggingDatabaseUsername << std::endl; const char* persistentLoggingDatabasePassword = persistentInfo->getJITServerPersistentLoggingDatabasePassword(); - std::cout <<"what is the persistent logging database Password ? "<< persistentLoggingDatabasePassword << std::endl; +// std::cout <<"what is the persistent logging database Password ? "<< persistentLoggingDatabasePassword << std::endl; const char* persistentLoggingDatabaseName = persistentInfo->getJITServerPersistentLoggingDatabaseName(); - std::cout << "what is the persistent logging database Name ? " << persistentLoggingDatabaseName << std::endl; -#ifdef CASSANDRA_LOGGER - CassandraLogger logger(persistentLoggingDatabaseAddress, - persistentLoggingDatabasePort, - persistentLoggingDatabaseName, - persistentLoggingDatabaseUsername, - persistentLoggingDatabasePassword); - std::cout << "Im Cassandra" << std::endl; -#endif // CASSANDRA_LOGGER - -#ifdef MONGO_LOGGER +// std::cout << "what is the persistent logging database Name ? " << persistentLoggingDatabaseName << std::endl; +#if defined(MONGO_LOGGER) MongoLogger logger(persistentLoggingDatabaseAddress, - persistentLoggingDatabasePort, - persistentLoggingDatabaseName, - persistentLoggingDatabaseUsername, - persistentLoggingDatabasePassword); - std::cout << "Im mongo" << std::endl; -#endif // MONGO_LOGGER + persistentLoggingDatabasePort, + persistentLoggingDatabaseName, + persistentLoggingDatabaseUsername, + persistentLoggingDatabasePassword); +#elif defined(CASSANDRA_LOGGER) + CassandraLogger logger(persistentLoggingDatabaseAddress, + persistentLoggingDatabasePort, + persistentLoggingDatabaseName, + persistentLoggingDatabaseUsername, + persistentLoggingDatabasePassword); +#endif // MONGO_LOGGER elif CASSANDRA_LOGGER bool isConnected = logger.connect(); if (isConnected) { - logger.logMethod(methodSignature, clientUID, logFileStr.c_str()); + if (!logger.logMethod(methodSignature, clientUID, logFileStr.c_str())) + fprintf(stderr, "JITServer: Persistent Logging Error - Database insert failed, skipping persistent logging."); logger.disconnect(); } else - { - printf("Persistent Logging Error: Database Connection Failed\n"); - } + fprintf(stderr, "JITServer: Persistent Logging Error - Database connection failed.\n"); } -#endif // PERSISTENT_LOGGING_SUPPORT +#endif // defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) std::string svmSymbolToIdStr; if (comp->getOption(TR_UseSymbolValidationManager)) diff --git a/runtime/compiler/control/LoadDBLibs.cpp b/runtime/compiler/control/LoadDBLibs.cpp index a99cda622cc..d9060997f57 100644 --- a/runtime/compiler/control/LoadDBLibs.cpp +++ b/runtime/compiler/control/LoadDBLibs.cpp @@ -7,6 +7,7 @@ #include #include +#if defined(MONGO_LOGGER) /* * MONGOC and BSON Library functions and strcuts */ @@ -27,7 +28,9 @@ Omongoc_collection_destroy_t *Omongoc_collection_destroy = NULL; Omongoc_database_destroy_t *Omongoc_database_destroy = NULL; Omongoc_uri_destroy_t *Omongoc_uri_destroy = NULL; Omongoc_client_destroy_t *Omongoc_client_destroy = NULL; +#endif // defined(MONGO_LOGGER) +#if defined(CASSANDRA_LOGGER) /* * CASSANDRA functions and structs */ @@ -52,10 +55,11 @@ Ocass_time_from_epoch_t *Ocass_time_from_epoch = NULL; Ocass_date_from_epoch_t *Ocass_date_from_epoch = NULL; Ocass_statement_bind_int64_t *Ocass_statement_bind_int64 = NULL; Ocass_statement_bind_uint32_t *Ocass_statement_bind_uint32 = NULL; - +#endif // defined(CASSANDRA_LOGGER) namespace JITServer { +#if defined(MONGO_LOGGER) void *loadLibmongoc() { void *result = NULL; @@ -69,13 +73,15 @@ namespace JITServer result = dlopen("libbson-1.0.so", RTLD_NOW); return result; } - +#endif // defined(MONGO_LOGGER) +#if defined(CASSANDRA_LOGGER) void *loadLibcassandra() { void *result = NULL; result = dlopen("libcassandra.so", RTLD_NOW); return result; } +#endif //defined(CASSANDRA_LOGGER) void unloadDBLib(void *handle) { @@ -87,6 +93,7 @@ namespace JITServer return dlsym(handle, sym); } +#if defined(MONGO_LOGGER) bool loadLibmongocAndSymbols() { void *handle = NULL; @@ -171,7 +178,9 @@ namespace JITServer return true; } +#endif // defined(MONGO_LOGGER) +#if defined(CASSANDRA_LOGGER) bool loadLibcassandraAndSymbols() { void *handle = NULL; @@ -235,4 +244,5 @@ namespace JITServer } return true; } +#endif // defined(CASSANDRA_LOGGER); } diff --git a/runtime/compiler/control/LoadDBLibs.hpp b/runtime/compiler/control/LoadDBLibs.hpp index d8acf80cd6d..3887b0c1aef 100644 --- a/runtime/compiler/control/LoadDBLibs.hpp +++ b/runtime/compiler/control/LoadDBLibs.hpp @@ -8,6 +8,7 @@ #include #include +#if defined(MONGO_LOGGER) /* * libbson function pointers and typedefs */ @@ -87,7 +88,9 @@ typedef void Omongoc_database_destroy_t(Omongoc_database_t *database); typedef void Omongoc_uri_destroy_t(Omongoc_uri_t *uri); typedef void Omongoc_client_destroy_t(Omongoc_client_t *client); +#endif // defined(MONGO_LOGGER) +#if defined(CASSANDRA_LOGGER) /* * libcassandra function pointers and typedefs */ @@ -148,10 +151,12 @@ typedef Ocass_uint32_t Ocass_date_from_epoch_t(Ocass_int64_t epoch_secs); typedef int Ocass_statement_bind_uint32_t(OCassStatement *statement, size_t index, Ocass_uint32_t value); typedef int Ocass_statement_bind_int64_t(OCassStatement *statement, size_t index, Ocass_int64_t value); +#endif // defined(CASSANDRA_LOGGER) /* * Function pointer definitions. */ +#if defined(MONGO_LOGGER) // mongoc and bson: extern "C" Obson_new_t *Obson_new; extern "C" Obson_append_utf8_t *Obson_append_utf8; @@ -170,7 +175,8 @@ extern "C" Omongoc_collection_destroy_t *Omongoc_collection_destroy; extern "C" Omongoc_database_destroy_t *Omongoc_database_destroy; extern "C" Omongoc_uri_destroy_t *Omongoc_uri_destroy; extern "C" Omongoc_client_destroy_t *Omongoc_client_destroy; - +#endif // defined(MONGO_LOGGER) +#if defined(CASSANDRA_LOGGER) // Cassandra: extern "C" Ocass_statement_new_t *Ocass_statement_new; extern "C" Ocass_statement_free_t *Ocass_statement_free; @@ -193,25 +199,35 @@ extern "C" Ocass_time_from_epoch_t *Ocass_time_from_epoch; extern "C" Ocass_date_from_epoch_t *Ocass_date_from_epoch; extern "C" Ocass_statement_bind_int64_t *Ocass_statement_bind_int64; extern "C" Ocass_statement_bind_uint32_t *Ocass_statement_bind_uint32; - +#endif // defined(CASSANDRA_LOGGER) namespace JITServer { +#if defined(MONGO_LOGGER) static bool is_mongoc_init = 0; + inline bool isMongoCInit() { return is_mongoc_init; } + + inline void initMongoC() { Omongoc_init(); is_mongoc_init = 1; } + + inline void cleanupMongoC() { Omongoc_cleanup(); is_mongoc_init = 0; } + void *loadLibmongoc(); void *loadLibbson(); - +#endif // defined(MONGO_LOGGER) +#if defined(CASSANDRA_LOGGER) void *loadLibcassandra(); - +#endif //defined(CASSANDRA_LOGGER) void unloadDBLib(void *handle); void *findDBLibSymbol(void *handle, const char *sym); - +#if defined(MONGO_LOGGER) bool loadLibmongocAndSymbols(); bool loadLibbsonAndSymbols(); - +#endif // defined(MONGO_LOGGER); +#if defined(CASSANDRA_LOGGER) bool loadLibcassandraAndSymbols(); +#endif // defined(CASSANDRA_LOGGER) } #endif //JITSERVER_LOADDBLIBS_HPP diff --git a/runtime/compiler/control/MongoLogger.cpp b/runtime/compiler/control/MongoLogger.cpp index c08ecf4e871..c11beeb6880 100644 --- a/runtime/compiler/control/MongoLogger.cpp +++ b/runtime/compiler/control/MongoLogger.cpp @@ -150,7 +150,7 @@ bool MongoLogger::logMethod(const char* method, uint64_t clientID, const char* l if (!Omongoc_collection_insert_one(_collection, insert, NULL, NULL, &error)) { fprintf(stderr, "JITServer: Mongo Logger failed to insert log.\n" - "error message: %s\n", error.message); + "error message: %s\n", error.message); } Obson_destroy(insert); diff --git a/runtime/compiler/control/MongoLogger.hpp b/runtime/compiler/control/MongoLogger.hpp index f1ea794f6a2..2cdbf047746 100644 --- a/runtime/compiler/control/MongoLogger.hpp +++ b/runtime/compiler/control/MongoLogger.hpp @@ -8,7 +8,7 @@ class MongoLogger : public BasePersistentLogger { private: //TODO: Allocate this with OpenJ9 Allocators. - char _uri_string[512]; + char _uri_string[256]; Omongoc_uri_t *_uri; Omongoc_client_t *_client; Omongoc_database_t *_db; diff --git a/runtime/compiler/control/rossa.cpp b/runtime/compiler/control/rossa.cpp index 43f5d217ed1..4c2e882712e 100644 --- a/runtime/compiler/control/rossa.cpp +++ b/runtime/compiler/control/rossa.cpp @@ -109,9 +109,9 @@ #include "net/CommunicationStream.hpp" #include "net/ClientStream.hpp" #include "net/LoadSSLLibs.hpp" -#if defined(PERSISTENT_LOGGING_SUPPORT) +#if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) #include "control/LoadDBLibs.hpp" -#endif //defined(PERSISTENT_LOGGING_SUPPORT) +#endif //defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) #include "runtime/JITClientSession.hpp" #include "runtime/Listener.hpp" #include "runtime/JITServerStatisticsThread.hpp" @@ -1655,25 +1655,6 @@ onLoadInternal( if (!JITServer::loadLibsslAndFindSymbols()) return -1; } -#if defined(PERSISTENT_LOGGING_SUPPORT) -// TODO: Get Flag from CLIENT command line. -// if(TR::Options::getCmdLineOptions()->getOption(TR_PersistentLogging)) -// { -#if defined(MONGO_LOGGER) - if(!JITServer::loadLibmongocAndSymbols() || !JITServer::loadLibbsonAndSymbols() ) - return -1; - if(!JITServer::is_mongoc_init) - { - Omongoc_init(); - JITServer::is_mongoc_init = 1; - } -#endif //defined(MONGO_LOGGER) -#if defined(CASSANDRA_LOGGER) - if(!JITServer::loadLibcassandraAndSymbols()) - return -1; -#endif //defined(CASSANDRA_LOGGER) -// } -#endif //defined(PERSISTENT_LOGGING_SUPPORT) if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER) { @@ -1703,6 +1684,26 @@ onLoadInternal( { ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->statisticsThreadObject = NULL; } + +#if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) +// TODO: Get Flag from command line. + if(compInfo->getPersistentInfo()->getJITServerPersistentLogging()) + { +#if defined(MONGO_LOGGER) + fprintf(stderr, "Result of the thing: %d", compInfo->getPersistentInfo()->getJITServerPersistentLogging()); + fflush(stderr); + if(!JITServer::loadLibmongocAndSymbols() || !JITServer::loadLibbsonAndSymbols() ) + return -1; + if(!JITServer::isMongoCInit()) + { + JITServer::initMongoC(); + } +#elif defined(CASSANDRA_LOGGER) + if(!JITServer::loadLibcassandraAndSymbols()) + return -1; +#endif //defined(CASSANDRA_LOGGER) + } +#endif //defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) } else if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT) { diff --git a/runtime/compiler/env/J9PersistentInfo.hpp b/runtime/compiler/env/J9PersistentInfo.hpp index c5dded0d581..b9a94014d66 100644 --- a/runtime/compiler/env/J9PersistentInfo.hpp +++ b/runtime/compiler/env/J9PersistentInfo.hpp @@ -133,19 +133,18 @@ class PersistentInfo : public OMR::PersistentInfoConnector _remoteCompilationMode(JITServer::NONE), _JITServerAddress("localhost"), _JITServerPort(38400), -#if defined(PERSISTENT_LOGGING_SUPPORT) - #ifdef CASSANDRA_LOGGER +#if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) + _JITServerPersistentLogging(false), + #if defined(CASSANDRA_LOGGER) _JITServerPersistentLoggingDatabasePort(9042), - #endif //CASSANDRA_LOGGER - - #ifdef MONGO_LOGGER + #elif defined(MONGO_LOGGER) _JITServerPersistentLoggingDatabasePort(27017), - #endif //MONGO_LOGGER + #endif //MONGO_LOGGER elif CASSANDRA_LOGGER _JITServerPersistentLoggingDatabaseAddress("127.0.0.1"), _JITServerPersistentLoggingDatabaseUsername("admin"), _JITServerPersistentLoggingDatabaseName("jitserver_logs"), _JITServerPersistentLoggingDatabasePassword("password"), -#endif /* defined(PERSISTENT_LOGGING_SUPPORT) */ +#endif /* defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) */ _socketTimeoutMs(2000), _clientUID(0), #endif /* defined(J9VM_OPT_JITSERVER) */ @@ -320,21 +319,20 @@ class PersistentInfo : public OMR::PersistentInfoConnector void setJITServerPort(uint32_t port) { _JITServerPort = port; } uint64_t getClientUID() const { return _clientUID; } void setClientUID(uint64_t val) { _clientUID = val; } - #if defined(PERSISTENT_LOGGING_SUPPORT) - void setJITServerPersistentLoggingDatabasePort(uint32_t port) {_JITServerPersistentLoggingDatabasePort = port;} - uint32_t getJITServerPersistentLoggingDatabasePort() const { return _JITServerPersistentLoggingDatabasePort; } - void setJITServerPersistentLoggingDatabaseAddress(char *addr) {_JITServerPersistentLoggingDatabaseAddress = addr;} - const char *getJITServerPersistentLoggingDatabaseAddress() const { return _JITServerPersistentLoggingDatabaseAddress; } - - void setJITServerPersistentLoggingDatabaseUsername(char *username) {_JITServerPersistentLoggingDatabaseUsername = username;} - const char *getJITServerPersistentLoggingDatabaseUsername() const { return _JITServerPersistentLoggingDatabaseUsername; } - - void setJITServerPersistentLoggingDatabasePassword(char *password) {_JITServerPersistentLoggingDatabasePassword = password;} - const char *getJITServerPersistentLoggingDatabasePassword() const { return _JITServerPersistentLoggingDatabasePassword; } - - void setJITServerPersistentLoggingDatabaseName(char *name) {_JITServerPersistentLoggingDatabaseName = name;} - const char *getJITServerPersistentLoggingDatabaseName() const { return _JITServerPersistentLoggingDatabaseName; } - # endif /* defined(PERSISTENT_LOGGING_SUPPORT) */ +#if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) + void setJITServerPersistentLogging(bool enable) { _JITServerPersistentLogging = enable; } + bool getJITServerPersistentLogging() const { return _JITServerPersistentLogging; } + void setJITServerPersistentLoggingDatabasePort(uint32_t port) { _JITServerPersistentLoggingDatabasePort = port; } + uint32_t getJITServerPersistentLoggingDatabasePort() const { return _JITServerPersistentLoggingDatabasePort; } + void setJITServerPersistentLoggingDatabaseAddress(char *addr) { _JITServerPersistentLoggingDatabaseAddress = addr; } + const char *getJITServerPersistentLoggingDatabaseAddress() const { return _JITServerPersistentLoggingDatabaseAddress; } + void setJITServerPersistentLoggingDatabaseUsername(char *username) { _JITServerPersistentLoggingDatabaseUsername = username; } + const char *getJITServerPersistentLoggingDatabaseUsername() const { return _JITServerPersistentLoggingDatabaseUsername; } + void setJITServerPersistentLoggingDatabasePassword(char *password) { _JITServerPersistentLoggingDatabasePassword = password; } + const char *getJITServerPersistentLoggingDatabasePassword() const { return _JITServerPersistentLoggingDatabasePassword; } + void setJITServerPersistentLoggingDatabaseName(char *name) { _JITServerPersistentLoggingDatabaseName = name; } + const char *getJITServerPersistentLoggingDatabaseName() const { return _JITServerPersistentLoggingDatabaseName; } +#endif /* defined(defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) */ #endif /* defined(J9VM_OPT_JITSERVER) */ private: @@ -422,14 +420,17 @@ class PersistentInfo : public OMR::PersistentInfoConnector #if defined(J9VM_OPT_JITSERVER) JITServer::RemoteCompilationModes _remoteCompilationMode; // JITServer::NONE, JITServer::CLIENT, JITServer::SERVER std::string _JITServerAddress; + uint32_t _JITServerPort; + uint32_t _socketTimeoutMs; // timeout for communication sockets used in out-of-process JIT compilation + uint64_t _clientUID; +#if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) + bool _JITServerPersistentLogging; const char* _JITServerPersistentLoggingDatabaseAddress; const char* _JITServerPersistentLoggingDatabaseUsername; const char* _JITServerPersistentLoggingDatabasePassword; const char* _JITServerPersistentLoggingDatabaseName; - uint32_t _JITServerPort; - uint32_t _JITServerPersistentLoggingDatabasePort; - uint32_t _socketTimeoutMs; // timeout for communication sockets used in out-of-process JIT compilation - uint64_t _clientUID; + uint32_t _JITServerPersistentLoggingDatabasePort; +#endif #endif /* defined(J9VM_OPT_JITSERVER) */ }; From 9fccda8620d50c6449d99e7619eb087a8bf71182 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Tue, 18 Feb 2020 17:00:40 -0800 Subject: [PATCH 18/61] IL Generation for withfield bytecode instruction This change adds prototype IL generation support for the value type withfield bytecode in the case where the class specified is resolved. If the class or field is unresolved, the JIT compilation is aborted with an UnsupportedValueTypeOperation exception. Signed-off-by: Yi Zhang --- .../compiler/ilgen/J9ByteCodeIlGenerator.hpp | 2 +- runtime/compiler/ilgen/Walker.cpp | 116 +++++++++++++++++- 2 files changed, 113 insertions(+), 5 deletions(-) diff --git a/runtime/compiler/ilgen/J9ByteCodeIlGenerator.hpp b/runtime/compiler/ilgen/J9ByteCodeIlGenerator.hpp index cdb46927cae..bd875257593 100644 --- a/runtime/compiler/ilgen/J9ByteCodeIlGenerator.hpp +++ b/runtime/compiler/ilgen/J9ByteCodeIlGenerator.hpp @@ -162,7 +162,7 @@ class TR_J9ByteCodeIlGenerator : public TR_IlGenerator, public TR_J9ByteCodeIter // GenLoadStore // void loadInstance(int32_t); - void loadInstance(TR::SymbolReference *, int32_t); + void loadInstance(TR::SymbolReference *); void loadStatic(int32_t); void loadAuto(TR::DataType type, int32_t slot, bool isAdjunct = false); TR::Node *loadSymbol(TR::ILOpCodes, TR::SymbolReference *); diff --git a/runtime/compiler/ilgen/Walker.cpp b/runtime/compiler/ilgen/Walker.cpp index 5c5d94180ac..7136f0bc990 100644 --- a/runtime/compiler/ilgen/Walker.cpp +++ b/runtime/compiler/ilgen/Walker.cpp @@ -560,12 +560,21 @@ TR::Block * TR_J9ByteCodeIlGenerator::walker(TR::Block * prevBlock) break; } case J9BCwithfield: + if (TR::Compiler->om.areValueTypesEnabled()) + { + genWithField(next2Bytes()); + _bcIndex += 3; + } + else + { + fej9()->unsupportedByteCode(comp(), opcode); + } + break; case J9BCbreakpoint: fej9()->unsupportedByteCode(comp(), opcode); case J9BCunknown: fej9()->unknownByteCode(comp(), opcode); break; - default: break; } @@ -4920,14 +4929,18 @@ TR_J9ByteCodeIlGenerator::loadAuto(TR::DataType type, int32_t slot, bool isAdjun push(load); } - void TR_J9ByteCodeIlGenerator::loadInstance(int32_t cpIndex) { if (_generateReadBarriersForFieldWatch && comp()->compileRelocatableCode()) comp()->failCompilation("NO support for AOT in field watch"); - TR::SymbolReference * symRef = symRefTab()->findOrCreateShadowSymbol(_methodSymbol, cpIndex, false); + loadInstance(symRef); + } + +void +TR_J9ByteCodeIlGenerator::loadInstance(TR::SymbolReference * symRef) + { TR::Symbol * symbol = symRef->getSymbol(); TR::DataType type = symbol->getDataType(); @@ -4964,7 +4977,7 @@ TR_J9ByteCodeIlGenerator::loadInstance(int32_t cpIndex) !strncmp(className, BDCLASS, BDCLASSLEN)) { int32_t fieldLen=0; - char * fieldName = _methodSymbol->getResolvedMethod()->fieldNameChars(cpIndex, fieldLen); + char * fieldName = _methodSymbol->getResolvedMethod()->fieldNameChars(symRef->getCPIndex(), fieldLen); if (fieldName != NULL && BDFIELDLEN == strlen(fieldName) && !strncmp(fieldName, BDFIELD, BDFIELDLEN)) { load->setIsBigDecimalLoad(); @@ -5981,6 +5994,101 @@ TR_J9ByteCodeIlGenerator::genNew(TR::ILOpCodes opCode) genFlush(0); } +void +TR_J9ByteCodeIlGenerator::genWithField(uint16_t fieldCpIndex) + { + const int32_t bcIndex = currentByteCodeIndex(); + int32_t classCpIndex = method()->classCPIndexOfFieldOrStatic(fieldCpIndex); + TR_OpaqueClassBlock *valueClass = method()->getClassFromConstantPool(comp(), classCpIndex, true); + if (!valueClass) + { + if (isOutermostMethod()) + { + TR::DebugCounter::incStaticDebugCounter(comp(), + TR::DebugCounter::debugCounterName(comp(), + "ilgen.abort/unresolved/withfield/class/(%s)/bc=%d", + comp()->signature(), + bcIndex)); + } + else + { + TR::DebugCounter::incStaticDebugCounter(comp(), + TR::DebugCounter::debugCounterName(comp(), + "ilgen.abort/unresolved/withfield/class/(%s)/bc=%d/root=(%s)", + _method->signature(comp()->trMemory()), + bcIndex, + comp()->signature())); + } + comp()->failCompilation("Unresolved class encountered for withfieldbytecode instruction"); + } + + bool isStore = false; + TR::SymbolReference * symRef = symRefTab()->findOrCreateShadowSymbol(_methodSymbol, fieldCpIndex, isStore); + if (symRef->isUnresolved()) + { + if (isOutermostMethod()) + { + TR::DebugCounter::incStaticDebugCounter(comp(), + TR::DebugCounter::debugCounterName(comp(), + "ilgen.abort/unresolved/withfield/field/(%s)/bc=%d", + comp()->signature(), + bcIndex)); + } + else + { + TR::DebugCounter::incStaticDebugCounter(comp(), + TR::DebugCounter::debugCounterName(comp(), + "ilgen.abort/unresolved/withfield/field/(%s)/bc=%d/root=(%s)", + _method->signature(comp()->trMemory()), + bcIndex, + comp()->signature())); + } + comp()->failCompilation("Unresolved field encountered for withfield bytecode instruction"); + } + + TR::Node *newFieldValue = pop(); + TR::Node *originalObject = pop(); + + /* + * Insert nullchk for the original object as requested by the JVM spec. + * Especially in case of value type class with a single field, the nullchk is still + * necessary even though the original object is actually not needed. + */ + TR::Node *passThruNode = TR::Node::create(TR::PassThrough, 1, originalObject); + genTreeTop(genNullCheck(passThruNode)); + + loadClassObject(valueClass); + const TR::TypeLayout *typeLayout = comp()->typeLayout(valueClass); + size_t fieldCount = typeLayout->count(); + + for (size_t idx = 0; idx < fieldCount; idx++) + { + const TR::TypeLayoutEntry &fieldEntry = typeLayout->entry(idx); + if (fieldEntry._offset == symRef->getOffset()) + push(newFieldValue); + else + { + auto* fieldSymRef = comp()->getSymRefTab()->findOrFabricateShadowSymbol(valueClass, + fieldEntry._datatype, + fieldEntry._offset, + fieldEntry._isVolatile, + fieldEntry._isPrivate, + fieldEntry._isFinal, + fieldEntry._fieldname, + fieldEntry._typeSignature + ); + push(originalObject); + loadInstance(fieldSymRef); + } + } + + TR::Node *newValueNode = genNodeAndPopChildren(TR::newvalue, fieldCount+1, symRefTab()->findOrCreateNewValueSymbolRef(_methodSymbol)); + newValueNode->setIdentityless(true); + genTreeTop(newValueNode); + push(newValueNode); + genFlush(0); + } + void TR_J9ByteCodeIlGenerator::genDefaultValue(uint16_t cpIndex) { From e9c156eab3649879cda70df5f460d368312d4364 Mon Sep 17 00:00:00 2001 From: Dan Heidinga Date: Thu, 2 Apr 2020 17:21:48 -0400 Subject: [PATCH 19/61] Remove unused & obsolete reflect implemention com.ibm.oti.reflect.* is mostly unused except for the annotation parsers. Delete the unused Method/Field/ Constructor implementations and leave the annotation forwarders. Further cleanup here may be possible Signed-off-by: Dan Heidinga --- .../com/ibm/oti/reflect/AnnotationParser.java | 27 +++---- .../com/ibm/oti/reflect/Constructor.java | 58 --------------- .../classes/com/ibm/oti/reflect/Field.java | 54 -------------- .../classes/com/ibm/oti/reflect/Method.java | 71 ------------------- 4 files changed, 15 insertions(+), 195 deletions(-) delete mode 100644 jcl/src/java.base/share/classes/com/ibm/oti/reflect/Constructor.java delete mode 100644 jcl/src/java.base/share/classes/com/ibm/oti/reflect/Field.java delete mode 100644 jcl/src/java.base/share/classes/com/ibm/oti/reflect/Method.java diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java index bf4411d47e3..0d3045fb190 100644 --- a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java +++ b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java @@ -25,6 +25,9 @@ import java.lang.annotation.Annotation; import java.nio.ByteBuffer; +import java.lang.reflect.Method; +import java.lang.reflect.Field; +import java.lang.reflect.Constructor; /*[IF Sidecar19-SE] import jdk.internal.reflect.ConstantPool; /*[ELSE]*/ @@ -33,23 +36,23 @@ public class AnnotationParser { - public static Annotation[] parseAnnotations(java.lang.reflect.Field field) { + public static Annotation[] parseAnnotations(Field field) { return parseAnnotations(getAnnotationsData(field), field.getDeclaringClass()); } - public static Annotation[] parseAnnotations(java.lang.reflect.Constructor constructor) { + public static Annotation[] parseAnnotations(Constructor constructor) { return parseAnnotations(getAnnotationsData(constructor), constructor.getDeclaringClass()); } - public static Annotation[] parseAnnotations(java.lang.reflect.Method method) { + public static Annotation[] parseAnnotations(Method method) { return parseAnnotations(getAnnotationsData(method), method.getDeclaringClass()); } - public static Annotation[][] parseParameterAnnotations(java.lang.reflect.Constructor constructor) { + public static Annotation[][] parseParameterAnnotations(Constructor constructor) { return parseParameterAnnotations(getParameterAnnotationsData(constructor), constructor.getDeclaringClass(), constructor.getParameterTypes().length); } - public static Annotation[][] parseParameterAnnotations(java.lang.reflect.Method method) { + public static Annotation[][] parseParameterAnnotations(Method method) { return parseParameterAnnotations(getParameterAnnotationsData(method), method.getDeclaringClass(), method.getParameterTypes().length); } @@ -65,7 +68,7 @@ public static byte[] getAnnotationsData(java.lang.Class clazz) { return result; }; - public static Object parseDefaultValue(java.lang.reflect.Method method) { + public static Object parseDefaultValue(Method method) { byte[] elementValueData = getDefaultValueData(method); if (elementValueData == null) return null; ByteBuffer buf = ByteBuffer.wrap(elementValueData); @@ -103,12 +106,12 @@ public static Annotation[] parseAnnotations(byte[] annotationsData, Class clazz) clazz)); } - private static native byte[] getAnnotationsData(java.lang.reflect.Field field); - private static native byte[] getAnnotationsData(java.lang.reflect.Constructor constructor); - private static native byte[] getAnnotationsData(java.lang.reflect.Method method); - private static native byte[] getParameterAnnotationsData(java.lang.reflect.Constructor constructor); - private static native byte[] getParameterAnnotationsData(java.lang.reflect.Method method); - private static native byte[] getDefaultValueData(java.lang.reflect.Method method); + private static native byte[] getAnnotationsData(Field field); + private static native byte[] getAnnotationsData(Constructor constructor); + private static native byte[] getAnnotationsData(Method method); + private static native byte[] getParameterAnnotationsData(Constructor constructor); + private static native byte[] getParameterAnnotationsData(Method method); + private static native byte[] getDefaultValueData(Method method); static native ConstantPool getConstantPool(Class clazz); private static native byte[] getAnnotationsDataImpl(java.lang.Class clazz); diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/Constructor.java b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/Constructor.java deleted file mode 100644 index 67ae8666592..00000000000 --- a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/Constructor.java +++ /dev/null @@ -1,58 +0,0 @@ -/*[INCLUDE-IF Sidecar16]*/ -package com.ibm.oti.reflect; - -/******************************************************************************* - * Copyright (c) 2005, 2010 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -import java.lang.annotation.Annotation; -import java.lang.ref.SoftReference; - -public class Constructor { - private java.lang.reflect.Constructor constructor; - private SoftReference annotations; - -public Constructor(java.lang.reflect.Constructor constructor) { - this.constructor = constructor; -} - -private synchronized Annotations getAnnotations() { - Annotations ans; - if (annotations == null || (ans = annotations.get()) == null) { - annotations = new SoftReference(ans = new Annotations(AnnotationParser.parseAnnotations(constructor))); - } - return ans; -} - -public T getAnnotation(Class cl) { - if (cl == null) throw new NullPointerException(); - return getAnnotations().getAnnotation(cl); -} - -public Annotation[] getDeclaredAnnotations() { - return getAnnotations().getAnnotations().clone(); -} - -public Annotation[][] getParameterAnnotations() { - return AnnotationParser.parseParameterAnnotations(constructor); -} - -} diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/Field.java b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/Field.java deleted file mode 100644 index 9752e8fa0e1..00000000000 --- a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/Field.java +++ /dev/null @@ -1,54 +0,0 @@ -/*[INCLUDE-IF Sidecar16]*/ -package com.ibm.oti.reflect; - -/******************************************************************************* - * Copyright (c) 2005, 2010 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -import java.lang.annotation.Annotation; -import java.lang.ref.SoftReference; - -public class Field { - private java.lang.reflect.Field field; - private SoftReference annotations; - -public Field(java.lang.reflect.Field field) { - this.field = field; -} - -private synchronized Annotations getAnnotations() { - Annotations ans; - if (annotations == null || (ans = annotations.get()) == null) { - annotations = new SoftReference(ans = new Annotations(AnnotationParser.parseAnnotations(field))); - } - return ans; -} - -public T getAnnotation(Class cl) { - if (cl == null) throw new NullPointerException(); - return getAnnotations().getAnnotation(cl); -} - -public Annotation[] getDeclaredAnnotations() { - return getAnnotations().getAnnotations().clone(); -} - -} diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/Method.java b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/Method.java deleted file mode 100644 index 4d10a2ed1a5..00000000000 --- a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/Method.java +++ /dev/null @@ -1,71 +0,0 @@ -/*[INCLUDE-IF Sidecar16]*/ -package com.ibm.oti.reflect; - -/******************************************************************************* - * Copyright (c) 2005, 2014 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -import java.lang.annotation.Annotation; -import java.lang.ref.SoftReference; - - -public class Method { - private final java.lang.reflect.Method method; - private SoftReference annotations; - private SoftReference srDefaultValue; - -public Method(java.lang.reflect.Method method) { - this.method = method; -} - -private synchronized Annotations getAnnotations() { - Annotations ans; - if (annotations == null || (ans = annotations.get()) == null) { - annotations = new SoftReference(ans = new Annotations(AnnotationParser.parseAnnotations(method))); - } - return ans; -} - -public T getAnnotation(Class cl) { - if (cl == null) throw new NullPointerException(); - return getAnnotations().getAnnotation(cl); -} - - -public Annotation[] getDeclaredAnnotations() { - return getAnnotations().getAnnotations().clone(); -} - -public Object getDefaultValue() { - Object defaultValue; - synchronized(this) { - if (srDefaultValue == null || (defaultValue = srDefaultValue.get()) == null) { - srDefaultValue = new SoftReference(defaultValue = AnnotationParser.parseDefaultValue(method)); - } - } - return defaultValue; -} - -public Annotation[][] getParameterAnnotations() { - return AnnotationParser.parseParameterAnnotations(method); -} - -} From 15ca0682b5acc78b1cc6499a46927280370ff6a0 Mon Sep 17 00:00:00 2001 From: XuechunHou Date: Thu, 2 Apr 2020 15:33:00 -0600 Subject: [PATCH 20/61] made error messages consistent --- .../compiler/control/BasePersistentLogger.hpp | 2 +- runtime/compiler/control/CassandraLogger.cpp | 38 +++++++++---------- runtime/compiler/control/J9Options.cpp | 12 +++--- .../control/JITServerCompilationThread.cpp | 4 +- 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/runtime/compiler/control/BasePersistentLogger.hpp b/runtime/compiler/control/BasePersistentLogger.hpp index 1e6f4eb73c6..d18cc955ca8 100644 --- a/runtime/compiler/control/BasePersistentLogger.hpp +++ b/runtime/compiler/control/BasePersistentLogger.hpp @@ -15,7 +15,7 @@ class BasePersistentLogger virtual bool connect() = 0; virtual void disconnect() = 0; - BasePersistentLogger( const char * databaseIP, uint32_t databasePort, const char * databaseName) + BasePersistentLogger(const char * databaseIP, uint32_t databasePort, const char * databaseName) { _databaseIP = databaseIP; _databasePort = databasePort; diff --git a/runtime/compiler/control/CassandraLogger.cpp b/runtime/compiler/control/CassandraLogger.cpp index b2b3a52b003..f505ac8a361 100644 --- a/runtime/compiler/control/CassandraLogger.cpp +++ b/runtime/compiler/control/CassandraLogger.cpp @@ -23,8 +23,8 @@ CassandraLogger::CassandraLogger(const char *databaseIP, uint32_t databasePort, bool CassandraLogger::createKeySpace() { - char queryString[1024]; - sprintf(queryString, "CREATE KEYSPACE IF NOT EXISTS %s WITH REPLICATION = {'class':'SimpleStrategy','replication_factor':1};", _databaseName); + char queryString[256]; + snprintf(queryString, 256, "CREATE KEYSPACE IF NOT EXISTS %s WITH REPLICATION = {'class':'SimpleStrategy','replication_factor':1};", _databaseName); OCassStatement* statement = Ocass_statement_new(queryString, 0); OCassFuture* queryFuture = Ocass_session_execute(_session, statement); @@ -35,7 +35,7 @@ bool CassandraLogger::createKeySpace() const char* message; size_t messageLength; Ocass_future_error_message(queryFuture, &message, &messageLength); - fprintf(stderr, "PersistentLogging: Cassandra Database Keyspace Creation Error: '%.*s'\n", (int)messageLength, message); + fprintf(stderr, "PersistentLogging - Cassandra Database Keyspace Creation Error: '%.*s'\n", (int)messageLength, message); Ocass_future_free(queryFuture); return false; @@ -47,8 +47,8 @@ bool CassandraLogger::createKeySpace() } bool CassandraLogger::createTable(const char *tableName) { - char queryString[1024]; - sprintf(queryString, "CREATE TABLE IF NOT EXISTS %s.%s (clientID text, methodName text, logContent text, insertionDate date,insertionTime time, primary key (clientID, methodName, insertionDate, insertionTime));", _databaseName, tableName); + char queryString[256]; + snprintf(queryString, 256, "CREATE TABLE IF NOT EXISTS %s.%s (clientID text, methodName text, logContent text, insertionDate date,insertionTime time, primary key (clientID, methodName, insertionDate, insertionTime));", _databaseName, tableName); OCassStatement* statement = Ocass_statement_new(queryString, 0); OCassFuture* queryFuture = Ocass_session_execute(_session, statement); Ocass_statement_free(statement); @@ -58,7 +58,7 @@ bool CassandraLogger::createTable(const char *tableName) const char* message; size_t messageLength; Ocass_future_error_message(queryFuture, &message, &messageLength); - fprintf(stderr, "Persistent Logging: Cassandra Database Table Creation Error: '%.*s'\n", (int)messageLength, message); + fprintf(stderr, "Persistent Logging - Cassandra Database Table Creation Error: '%.*s'\n", (int)messageLength, message); Ocass_future_free(queryFuture); return false; @@ -78,7 +78,7 @@ bool CassandraLogger::connect() int rc_set_protocol = Ocass_cluster_set_protocol_version(_cluster, 4); if (rc_set_protocol != 0) { - printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_protocol)); + fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_protocol)); Ocass_session_free(_session); Ocass_cluster_free(_cluster); return false; @@ -89,7 +89,7 @@ bool CassandraLogger::connect() int rc_set_ip = Ocass_cluster_set_contact_points(_cluster, _databaseIP); if (rc_set_ip != 0) { - printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_ip)); + fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_ip)); Ocass_session_free(_session); Ocass_cluster_free(_cluster); return false; @@ -100,7 +100,7 @@ bool CassandraLogger::connect() int rc_set_port = Ocass_cluster_set_port(_cluster, _databasePort); if (rc_set_port != 0) { - printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_port)); + fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_port)); Ocass_session_free(_session); Ocass_cluster_free(_cluster); @@ -117,7 +117,7 @@ bool CassandraLogger::connect() const char* message; size_t messageLength; Ocass_future_error_message(_connectFuture, &message, &messageLength); - fprintf(stderr, "Persistent Logging: Cassandra Database Connection Error: '%.*s'\n", (int)messageLength, message); + fprintf(stderr, "Persistent Logging - Cassandra Database Connection Error: '%.*s'\n", (int)messageLength, message); Ocass_session_free(_session); Ocass_cluster_free(_cluster); Ocass_future_free(_connectFuture); @@ -135,19 +135,19 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha if (!createKeySpace()) return false; const char* tableName = "logs"; if (!createTable(tableName)) return false; - char queryString[1024]; + char queryString[256]; - sprintf(queryString, "INSERT INTO %s.%s (clientID, methodName, logContent, insertionDate, insertionTime) VALUES (?, ?, ?, ?, ?)", _databaseName,tableName); + snprintf(queryString, 256, "INSERT INTO %s.%s (clientID, methodName, logContent, insertionDate, insertionTime) VALUES (?, ?, ?, ?, ?)", _databaseName,tableName); OCassStatement* statement = Ocass_statement_new(queryString, 5); /* Bind the values using the indices of the bind variables */ char strClientID[64]; - sprintf(strClientID, "%lu", clientID); + snprintf(strClientID, 64, "%lu", clientID); int rc_set_bind_pk = Ocass_statement_bind_string(statement, 0, strClientID); if (rc_set_bind_pk != 0) { - printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_pk)); + fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_pk)); Ocass_statement_free(statement); return false; } @@ -155,7 +155,7 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha int rc_set_bind_method = Ocass_statement_bind_string(statement, 1, method); if (rc_set_bind_pk != 0) { - printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_method)); + fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_method)); Ocass_statement_free(statement); return false; } @@ -163,7 +163,7 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha if (rc_set_bind_log_content != 0) { - printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_log_content)); + fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_log_content)); Ocass_statement_free(statement); return false; } @@ -179,7 +179,7 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha if (rc_set_bind_insertion_date != 0) { - printf("Persistent Logging - Cassandra Database Error: %s\n", Ocass_error_desc(rc_set_bind_insertion_date)); + fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n", Ocass_error_desc(rc_set_bind_insertion_date)); Ocass_statement_free(statement); return false; } @@ -187,7 +187,7 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha int rc_set_bind_insertion_time = Ocass_statement_bind_int64(statement, 4, time_of_insertion); if (rc_set_bind_insertion_time != 0) { - printf("Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_insertion_time)); + fprintf(stderr ,"Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_insertion_time)); Ocass_statement_free(statement); return false; } @@ -202,7 +202,7 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha const char* message; size_t messageLength; Ocass_future_error_message(queryFuture, &message, &messageLength); - fprintf(stderr, "query execution error: '%.*s'\n", (int)messageLength, message); + fprintf(stderr, "Persistent Logging - Cassandra Database Query Execution Error: '%.*s'\n", (int)messageLength, message); Ocass_future_free(queryFuture); return false; } diff --git a/runtime/compiler/control/J9Options.cpp b/runtime/compiler/control/J9Options.cpp index a2138b2b605..825497af3e9 100644 --- a/runtime/compiler/control/J9Options.cpp +++ b/runtime/compiler/control/J9Options.cpp @@ -1074,19 +1074,17 @@ static void JITServerParseCommonOptions(J9JavaVM *vm, TR::CompilationInfo *compI const char *xxJITServerSSLKeyOption = "-XX:JITServerSSLKey="; const char *xxJITServerSSLCertOption = "-XX:JITServerSSLCert="; const char *xxJITServerSSLRootCertsOption = "-XX:JITServerSSLRootCerts="; - #ifdef PERSISTENT_LOGGING_SUPPORT - const char *xxJITServerPersistentLoggingDatabasePortOption = "-XX:JITServerPersistentLoggingDatabasePort="; - const char *xxJITServerPersistentLoggingDatabaseAddressOption = "-XX:JITServerPersistentLoggingDatabaseAddress="; - const char *xxJITServerPersistentLoggingDatabaseNameOption = "-XX:JITServerPersistentLoggingDatabaseName="; - const char *xxJITServerPersistentLoggingDatabaseUsernameOption = "-XX:JITServerPersistentLoggingDatabaseUsername="; - const char *xxJITServerPersistentLoggingDatabasePasswordOption = "-XX:JITServerPersistentLoggingDatabasePassword="; - #endif // PERSISTENT_LOGGING_SUPPORT int32_t xxJITServerPortArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPortOption, 0); int32_t xxJITServerTimeoutArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerTimeoutOption, 0); int32_t xxJITServerSSLKeyArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerSSLKeyOption, 0); int32_t xxJITServerSSLCertArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerSSLCertOption, 0); int32_t xxJITServerSSLRootCertsArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerSSLRootCertsOption, 0); #ifdef PERSISTENT_LOGGING_SUPPORT + const char *xxJITServerPersistentLoggingDatabasePortOption = "-XX:JITServerPersistentLoggingDatabasePort="; + const char *xxJITServerPersistentLoggingDatabaseAddressOption = "-XX:JITServerPersistentLoggingDatabaseAddress="; + const char *xxJITServerPersistentLoggingDatabaseNameOption = "-XX:JITServerPersistentLoggingDatabaseName="; + const char *xxJITServerPersistentLoggingDatabaseUsernameOption = "-XX:JITServerPersistentLoggingDatabaseUsername="; + const char *xxJITServerPersistentLoggingDatabasePasswordOption = "-XX:JITServerPersistentLoggingDatabasePassword="; int32_t xxJITServerPersistentLoggingDatabasePortArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabasePortOption, 0); int32_t xxJITServerPersistentLoggingDatabaseAddressArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseAddressOption, 0); int32_t xxJITServerPersistentLoggingDatabaseNameArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseNameOption, 0); diff --git a/runtime/compiler/control/JITServerCompilationThread.cpp b/runtime/compiler/control/JITServerCompilationThread.cpp index b81b5fb2355..d812857c0a0 100644 --- a/runtime/compiler/control/JITServerCompilationThread.cpp +++ b/runtime/compiler/control/JITServerCompilationThread.cpp @@ -91,8 +91,6 @@ outOfProcessCompilationEnd( // Pack log file to send to client std::string logFileStr = TR::Options::packLogFile(comp->getOutFile()); - std::cout << "Pre Persistent Logging Section" << std::endl; - std::cout << comp->getOption(TR_PersistentLogging) << std::endl; #ifdef PERSISTENT_LOGGING_SUPPORT if (comp->getOption(TR_PersistentLogging)) { @@ -140,7 +138,7 @@ outOfProcessCompilationEnd( } else { - printf("Persistent Logging Error: Database Connection Failed\n"); + printf("Persistent Logging Error: Database Connection Failed\n"); } } #endif // PERSISTENT_LOGGING_SUPPORT From b7d61dd003c03b964c064a342530b542746a862b Mon Sep 17 00:00:00 2001 From: Chase Buhler Date: Thu, 2 Apr 2020 16:23:03 -0600 Subject: [PATCH 21/61] Convert sprintf to snprintf --- runtime/compiler/control/HookedByTheJit.cpp | 14 ++++++++------ .../control/JITServerCompilationThread.cpp | 16 +++------------- runtime/compiler/control/MongoLogger.cpp | 11 ++++++----- runtime/compiler/control/rossa.cpp | 2 -- 4 files changed, 17 insertions(+), 26 deletions(-) diff --git a/runtime/compiler/control/HookedByTheJit.cpp b/runtime/compiler/control/HookedByTheJit.cpp index 633c63db6c5..f2798dcdcef 100644 --- a/runtime/compiler/control/HookedByTheJit.cpp +++ b/runtime/compiler/control/HookedByTheJit.cpp @@ -82,9 +82,9 @@ #include "runtime/JITServerIProfiler.hpp" #include "runtime/JITServerStatisticsThread.hpp" #include "runtime/Listener.hpp" -//#if defined(MONGO_LOGGER) -//#include "control/LoadDBLibs.hpp" -//#endif // defined(MONGO_LOGGER) +#if defined(MONGO_LOGGER) +#include "control/LoadDBLibs.hpp" +#endif // defined(MONGO_LOGGER) #endif // defined(J9VM_OPT_JITSERVER) extern "C" { @@ -4736,6 +4736,11 @@ void JitShutdown(J9JITConfig * jitConfig) } } +#if defined(J9VM_OPT_JITSERVER) && defined(MONGO_LOGGER) + if(compInfo->getPersistentInfo()->getJITServerPersistentLogging()) + JITServer::cleanupMongoC(); +#endif //J9VM_OPT_JITSERVER && MONGO_LOGGER + TR::Compilation::shutdown(vm); TR::CompilationController::shutdown(); @@ -4749,9 +4754,6 @@ void JitShutdown(J9JITConfig * jitConfig) { statsThreadObj->stopStatisticsThread(jitConfig); } -//#if defined(MONGO_LOGGER) -// JITServer::cleanupMongoC(); -//#endif // defined(MONGO_LOGGER) #endif TR_DebuggingCounters::report(); diff --git a/runtime/compiler/control/JITServerCompilationThread.cpp b/runtime/compiler/control/JITServerCompilationThread.cpp index dedab4fcb94..2f093282365 100644 --- a/runtime/compiler/control/JITServerCompilationThread.cpp +++ b/runtime/compiler/control/JITServerCompilationThread.cpp @@ -91,30 +91,19 @@ outOfProcessCompilationEnd( std::string logFileStr = TR::Options::packLogFile(comp->getOutFile()); #if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) - printf("Persistent Logging enabled\n"); - fflush(stdout); if (compInfoPT->getCompilationInfo()->getPersistentInfo()->getJITServerPersistentLogging() && comp->getOption(TR_PersistentLogging)) //Check both server and client enable persistent logging. { + printf("Persistent Logging enabled\n"); uint64_t clientUID = entry->getClientUID(); const char* methodSignature = compInfoPT->getCompilation()->signature(); TR::PersistentInfo* persistentInfo = compInfoPT->getCompilationInfo()->getPersistentInfo(); - printf("Persistent Logging enabled\n"); -// printf("Found Client ID %llu\n", clientUID); -// printf("potential method full name: %s\n",methodSignature); uint32_t persistentLoggingDatabasePort = persistentInfo->getJITServerPersistentLoggingDatabasePort(); -// printf("what is the persistent logging database port ? %lu\n",persistentLoggingDatabasePort); const char* persistentLoggingDatabaseAddress = persistentInfo->getJITServerPersistentLoggingDatabaseAddress(); -// std::cout << "what is the persistent logging database Address ? " << persistentLoggingDatabaseAddress << std::endl; - const char* persistentLoggingDatabaseUsername = persistentInfo->getJITServerPersistentLoggingDatabaseUsername(); -// std::cout << "what is the persistent logging database Username ? " << persistentLoggingDatabaseUsername << std::endl; - const char* persistentLoggingDatabasePassword = persistentInfo->getJITServerPersistentLoggingDatabasePassword(); -// std::cout <<"what is the persistent logging database Password ? "<< persistentLoggingDatabasePassword << std::endl; - const char* persistentLoggingDatabaseName = persistentInfo->getJITServerPersistentLoggingDatabaseName(); -// std::cout << "what is the persistent logging database Name ? " << persistentLoggingDatabaseName << std::endl; + #if defined(MONGO_LOGGER) MongoLogger logger(persistentLoggingDatabaseAddress, persistentLoggingDatabasePort, @@ -128,6 +117,7 @@ outOfProcessCompilationEnd( persistentLoggingDatabaseUsername, persistentLoggingDatabasePassword); #endif // MONGO_LOGGER elif CASSANDRA_LOGGER + bool isConnected = logger.connect(); if (isConnected) { diff --git a/runtime/compiler/control/MongoLogger.cpp b/runtime/compiler/control/MongoLogger.cpp index c11beeb6880..ba8be02ab0d 100644 --- a/runtime/compiler/control/MongoLogger.cpp +++ b/runtime/compiler/control/MongoLogger.cpp @@ -61,18 +61,18 @@ char * MongoLogger::constructURI() { if (strcmp(_databasePassword,"") != 0) { - sprintf(_uri_string, "mongodb://%s:%s@%s:%u/?authSource=%s", _databaseUsername, _databasePassword, + snprintf(_uri_string, 256, "mongodb://%s:%s@%s:%u/?authSource=%s", _databaseUsername, _databasePassword, _databaseIP, _databasePort, _databaseName); } else { - sprintf(_uri_string, "mongodb://%s@%s:%u/?authSource=%s", _databaseUsername, _databaseIP, _databasePort, + snprintf(_uri_string, 256, "mongodb://%s@%s:%u/?authSource=%s", _databaseUsername, _databaseIP, _databasePort, _databaseName); } } else { - sprintf(_uri_string, "mongodb://%s:%u/?authSource=%s", _databaseIP, _databasePort, _databaseName); + snprintf(_uri_string, 256, "mongodb://%s:%u/?authSource=%s", _databaseIP, _databasePort, _databaseName); } return _uri_string; @@ -130,6 +130,8 @@ bool MongoLogger::logMethod(const char* method, uint64_t clientID, const char* l struct timespec t; clock_gettime(CLOCK_REALTIME, &t); int64_t timestamp = t.tv_sec * INT64_C(1000) + t.tv_nsec / 1000000; + char clientIDstr[20]; + snprintf(clientIDstr, 20, "%llu", clientID); /* * The following constructs and inserts the following JSON structure: * { @@ -142,8 +144,7 @@ bool MongoLogger::logMethod(const char* method, uint64_t clientID, const char* l Obson_t *insert = Obson_new(); Obson_error_t error; Obson_append_utf8(insert, "method", -1, method, -1); - Obson_append_utf8(insert, "client_id", -1, std::to_string(clientID).c_str(), -1); -//TODO: CONVER CLIENTID to CHAR * without using STRING. + Obson_append_utf8(insert, "client_id", -1, clientIDstr, -1); Obson_append_utf8(insert, "log", -1, logContent, -1); Obson_append_date_time(insert, "timestamp", -1, timestamp); diff --git a/runtime/compiler/control/rossa.cpp b/runtime/compiler/control/rossa.cpp index 4c2e882712e..fb68ee5fcbe 100644 --- a/runtime/compiler/control/rossa.cpp +++ b/runtime/compiler/control/rossa.cpp @@ -1690,8 +1690,6 @@ onLoadInternal( if(compInfo->getPersistentInfo()->getJITServerPersistentLogging()) { #if defined(MONGO_LOGGER) - fprintf(stderr, "Result of the thing: %d", compInfo->getPersistentInfo()->getJITServerPersistentLogging()); - fflush(stderr); if(!JITServer::loadLibmongocAndSymbols() || !JITServer::loadLibbsonAndSymbols() ) return -1; if(!JITServer::isMongoCInit()) From ee078d21529ca8b41ffa7a9743fcc67383896a83 Mon Sep 17 00:00:00 2001 From: Chase Buhler Date: Thu, 2 Apr 2020 16:23:33 -0600 Subject: [PATCH 22/61] Convert sprintf to snprintf --- runtime/compiler/control/MongoLogger.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/compiler/control/MongoLogger.hpp b/runtime/compiler/control/MongoLogger.hpp index 2cdbf047746..ce793e3b462 100644 --- a/runtime/compiler/control/MongoLogger.hpp +++ b/runtime/compiler/control/MongoLogger.hpp @@ -7,7 +7,6 @@ class MongoLogger : public BasePersistentLogger { private: - //TODO: Allocate this with OpenJ9 Allocators. char _uri_string[256]; Omongoc_uri_t *_uri; Omongoc_client_t *_client; From 2a47fcf1dc14dd95f3671fd99b8d512c8ebf0d71 Mon Sep 17 00:00:00 2001 From: Dan Heidinga Date: Thu, 2 Apr 2020 22:14:31 -0400 Subject: [PATCH 23/61] Fix copyrights Signed-off-by: Dan Heidinga --- .../share/classes/com/ibm/oti/reflect/AnnotationParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java index 0d3045fb190..59b9d8d0b4c 100644 --- a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java +++ b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java @@ -2,7 +2,7 @@ package com.ibm.oti.reflect; /******************************************************************************* - * Copyright (c) 2010, 2017 IBM Corp. and others + * Copyright (c) 2010, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this From d3f9ce6be5c884dcf2c764dadda66201e905deb0 Mon Sep 17 00:00:00 2001 From: Babneet Singh Date: Wed, 1 Apr 2020 14:59:02 -0400 Subject: [PATCH 24/61] Handle race condition in outOfLineINL In the below example, compareAndExchangeRelease translates to an OutOfLine INL method named OutOfLineINL_jdk_internal_misc_Unsafe_compareAndExchangeIntVolatile. Example: InstFieldVH <- InstanceFieldVarHandle provides access to an int field in an object. 1000 threads concurrently execute { int old, new; do { old = (int)InstFieldVH.getVolatile(object); new = old + 2; } while (old != InstFieldVH.compareAndExchangeRelease(object, old, new)); } There is a race condition between 1) invoking the target method in BytecodeInterpreter.hpp::outOfLineINL; and 2) resolving the native address (J9Method->extra) of the target method in BytecodeInterpreter.hpp::bindNative. Due to the race condition, the native address of the target method may not be resolved when certain threads invoke outOfLineINL. In such cases, outOfLineINL should resolve the native address before proceeding. bindnatv.cpp::resolveNativeAddress - The code to resolve the native address is protected by the J9JavaVM->bindNativeMutex. So, it can be safely invoked by multiple threads. If the native address is already resolved, then it returns without repeating the resolution process. Signed-off-by: Babneet Singh --- runtime/vm/BytecodeInterpreter.hpp | 77 +++++++++++++++++++----------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/runtime/vm/BytecodeInterpreter.hpp b/runtime/vm/BytecodeInterpreter.hpp index 7b3f98eda5c..233551b5d36 100644 --- a/runtime/vm/BytecodeInterpreter.hpp +++ b/runtime/vm/BytecodeInterpreter.hpp @@ -2019,40 +2019,50 @@ obj:; } VMINLINE VM_BytecodeAction - bindNative(REGISTER_ARGS_LIST) + resolveNativeAddressWithErrorHandling() { - VM_BytecodeAction rc = GOTO_RUN_METHOD; - buildMethodFrame(REGISTER_ARGS, _sendMethod, jitStackFrameFlags(REGISTER_ARGS, 0)); - updateVMStruct(REGISTER_ARGS); UDATA bindRC = resolveNativeAddress(_currentThread, _sendMethod, TRUE); if (J9_NATIVE_METHOD_BIND_OUT_OF_MEMORY == bindRC) { _vm->memoryManagerFunctions->j9gc_modron_global_collect_with_overrides(_currentThread, J9MMCONSTANT_EXPLICIT_GC_NATIVE_OUT_OF_MEMORY); bindRC = resolveNativeAddress(_currentThread, _sendMethod, TRUE); } - switch(bindRC) { - case J9_NATIVE_METHOD_BIND_SUCCESS: { - VMStructHasBeenUpdated(REGISTER_ARGS); - J9SFMethodFrame *methodFrame = (J9SFMethodFrame*)_sp; - _currentThread->jitStackFrameFlags = methodFrame->specialFrameFlags & J9_SSF_JIT_NATIVE_TRANSITION_FRAME; - restoreSpecialStackFrameLeavingArgs(REGISTER_ARGS, ((UDATA*)(methodFrame + 1)) - 1); - break; - } - case J9_NATIVE_METHOD_BIND_OUT_OF_MEMORY: - setNativeBindOutOfMemoryError(_currentThread, _sendMethod); - VMStructHasBeenUpdated(REGISTER_ARGS); - rc = GOTO_THROW_CURRENT_EXCEPTION; - break; - case J9_NATIVE_METHOD_BIND_RECURSIVE: - setRecursiveBindError(_currentThread, _sendMethod); - VMStructHasBeenUpdated(REGISTER_ARGS); - rc = GOTO_THROW_CURRENT_EXCEPTION; - break; - default: - setNativeNotFoundError(_currentThread, _sendMethod); - VMStructHasBeenUpdated(REGISTER_ARGS); + + VM_BytecodeAction rc = GOTO_RUN_METHOD; + if (J9_NATIVE_METHOD_BIND_SUCCESS != bindRC) { rc = GOTO_THROW_CURRENT_EXCEPTION; - break; + switch(bindRC) { + case J9_NATIVE_METHOD_BIND_OUT_OF_MEMORY: + setNativeBindOutOfMemoryError(_currentThread, _sendMethod); + break; + case J9_NATIVE_METHOD_BIND_RECURSIVE: + setRecursiveBindError(_currentThread, _sendMethod); + break; + default: + setNativeNotFoundError(_currentThread, _sendMethod); + break; + } } + + return rc; + } + + VMINLINE VM_BytecodeAction + bindNative(REGISTER_ARGS_LIST) + { + VM_BytecodeAction rc = GOTO_RUN_METHOD; + + buildMethodFrame(REGISTER_ARGS, _sendMethod, jitStackFrameFlags(REGISTER_ARGS, 0)); + + updateVMStruct(REGISTER_ARGS); + rc = resolveNativeAddressWithErrorHandling(); + VMStructHasBeenUpdated(REGISTER_ARGS); + + if (GOTO_RUN_METHOD == rc) { + J9SFMethodFrame *methodFrame = (J9SFMethodFrame *)_sp; + _currentThread->jitStackFrameFlags = methodFrame->specialFrameFlags & J9_SSF_JIT_NATIVE_TRANSITION_FRAME; + restoreSpecialStackFrameLeavingArgs(REGISTER_ARGS, ((UDATA *)(methodFrame + 1)) - 1); + } + return rc; } @@ -4618,8 +4628,21 @@ done:; outOfLineINL(REGISTER_ARGS_LIST) { updateVMStruct(REGISTER_ARGS); + J9OutOfLineINLMethod *target = (J9OutOfLineINLMethod *)(((UDATA)_sendMethod->extra) & ~J9_STARTPC_NOT_TRANSLATED); - VM_BytecodeAction rc = target(_currentThread, _sendMethod); + VM_BytecodeAction rc = GOTO_RUN_METHOD; + if (NULL == target) { + /* Resolve the native address and retry. */ + rc = resolveNativeAddressWithErrorHandling(); + if (GOTO_RUN_METHOD != rc) { + goto done; + } + target = (J9OutOfLineINLMethod *)(((UDATA)_sendMethod->extra) & ~J9_STARTPC_NOT_TRANSLATED); + } + + Assert_VM_true(NULL != target); + rc = target(_currentThread, _sendMethod); +done: VMStructHasBeenUpdated(REGISTER_ARGS); return rc; } From dade50445a2f6141a4b51424a4a03487cb91528b Mon Sep 17 00:00:00 2001 From: Annabelle Huo Date: Mon, 30 Mar 2020 12:32:43 -0400 Subject: [PATCH 25/61] Remove the obsolete APIs in known object table Remove getIndex() and getIndexAt() which have been replaced by getOrCreateIndex() and getOrCreateIndexAt(). Signed-off-by: Annabelle Huo --- runtime/compiler/env/J9KnownObjectTable.cpp | 97 --------------------- runtime/compiler/env/J9KnownObjectTable.hpp | 4 - 2 files changed, 101 deletions(-) diff --git a/runtime/compiler/env/J9KnownObjectTable.cpp b/runtime/compiler/env/J9KnownObjectTable.cpp index b16f76c3c3a..d25b95fc03a 100644 --- a/runtime/compiler/env/J9KnownObjectTable.cpp +++ b/runtime/compiler/env/J9KnownObjectTable.cpp @@ -62,103 +62,6 @@ J9::KnownObjectTable::isNull(Index index) } -TR::KnownObjectTable::Index -J9::KnownObjectTable::getIndex(uintptr_t objectPointer) - { - if (objectPointer == 0) - return 0; // Special Index value for NULL - - uint32_t nextIndex = self()->getEndIndex(); -#if defined(J9VM_OPT_JITSERVER) - if (self()->comp()->isOutOfProcessCompilation()) - { - TR_ASSERT_FATAL(false, "It is not safe to call getIndex() at the server. The object pointer could have become stale at the client."); - auto stream = TR::CompilationInfo::getStream(); - stream->write(JITServer::MessageType::KnownObjectTable_getOrCreateIndex, objectPointer); - auto recv = stream->read(); - - TR::KnownObjectTable::Index index = std::get<0>(recv); - uintptr_t *objectReferenceLocation = std::get<1>(recv); - TR_ASSERT_FATAL(index <= nextIndex, "The KOT index %d at the client is greater than the KOT index %d at the server", index, nextIndex); - - if (index < nextIndex) - { - return index; - } - else - { - updateKnownObjectTableAtServer(index, objectReferenceLocation); - } - } - else -#endif /* defined(J9VM_OPT_JITSERVER) */ - { - TR_J9VMBase *fej9 = (TR_J9VMBase *)(self()->fe()); - TR_ASSERT(fej9->haveAccess(), "Must haveAccess in J9::KnownObjectTable::getIndex"); - - // Search for existing matching entry - // - for (uint32_t i = 1; i < nextIndex; i++) - if (*_references.element(i) == objectPointer) - return i; - - // No luck -- allocate a new one - // - J9VMThread *thread = getJ9VMThreadFromTR_VM(self()->fe()); - TR_ASSERT(thread, "assertion failure"); - _references.setSize(nextIndex+1); - _references[nextIndex] = (uintptr_t*)thread->javaVM->internalVMFunctions->j9jni_createLocalRef((JNIEnv*)thread, (j9object_t)objectPointer); - } - - return nextIndex; - } - - -TR::KnownObjectTable::Index -J9::KnownObjectTable::getIndex(uintptr_t objectPointer, bool isArrayWithConstantElements) - { - TR::KnownObjectTable::Index index = self()->getIndex(objectPointer); - if (isArrayWithConstantElements) - { - self()->addArrayWithConstantElements(index); - } - return index; - } - - -TR::KnownObjectTable::Index -J9::KnownObjectTable::getIndexAt(uintptr_t *objectReferenceLocation) - { - TR::KnownObjectTable::Index result = UNKNOWN; -#if defined(J9VM_OPT_JITSERVER) - if (self()->comp()->isOutOfProcessCompilation()) - { - auto stream = TR::CompilationInfo::getStream(); - stream->write(JITServer::MessageType::KnownObjectTable_getOrCreateIndexAt, objectReferenceLocation); - result = std::get<0>(stream->read()); - - updateKnownObjectTableAtServer(result, objectReferenceLocation); - } - else -#endif /* defined(J9VM_OPT_JITSERVER) */ - { - TR::VMAccessCriticalSection getIndexAtCriticalSection(self()->comp()); - uintptr_t objectPointer = *objectReferenceLocation; // Note: object references held as uintptr_t must never be compressed refs - result = self()->getIndex(objectPointer); - } - return result; - } - -TR::KnownObjectTable::Index -J9::KnownObjectTable::getIndexAt(uintptr_t *objectReferenceLocation, bool isArrayWithConstantElements) - { - Index result = self()->getIndexAt(objectReferenceLocation); - if (isArrayWithConstantElements) - self()->addArrayWithConstantElements(result); - return result; - } - - TR::KnownObjectTable::Index J9::KnownObjectTable::getOrCreateIndex(uintptr_t objectPointer) { diff --git a/runtime/compiler/env/J9KnownObjectTable.hpp b/runtime/compiler/env/J9KnownObjectTable.hpp index d870ba4b4d4..3b8a878d4ac 100644 --- a/runtime/compiler/env/J9KnownObjectTable.hpp +++ b/runtime/compiler/env/J9KnownObjectTable.hpp @@ -86,8 +86,6 @@ class OMR_EXTENSIBLE KnownObjectTable : public OMR::KnownObjectTableConnector TR::KnownObjectTable *self(); Index getEndIndex(); - Index getIndex(uintptr_t objectPointer); - Index getIndex(uintptr_t objectPointer, bool isArrayWithConstantElements); Index getOrCreateIndex(uintptr_t objectPointer); Index getOrCreateIndex(uintptr_t objectPointer, bool isArrayWithConstantElements); uintptr_t *getPointerLocation(Index index); @@ -95,8 +93,6 @@ class OMR_EXTENSIBLE KnownObjectTable : public OMR::KnownObjectTableConnector void dumpTo(TR::FILE *file, TR::Compilation *comp); - Index getIndexAt(uintptr_t *objectReferenceLocation); - Index getIndexAt(uintptr_t *objectReferenceLocation, bool isArrayWithConstantElements); Index getOrCreateIndexAt(uintptr_t *objectReferenceLocation); Index getOrCreateIndexAt(uintptr_t *objectReferenceLocation, bool isArrayWithConstantElements); Index getExistingIndexAt(uintptr_t *objectReferenceLocation); From 469242de8bbbbe8273743c92d1b0421565eebba5 Mon Sep 17 00:00:00 2001 From: Graham Chapman Date: Fri, 3 Apr 2020 11:47:42 -0400 Subject: [PATCH 26/61] Fix default flag initialization Defaults must be initialized before calling processVMArgsFromFirstToLast. [ci skip] Signed-off-by: Graham Chapman --- runtime/vm/jvminit.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/runtime/vm/jvminit.c b/runtime/vm/jvminit.c index 79929fe9688..4360baa4d8d 100644 --- a/runtime/vm/jvminit.c +++ b/runtime/vm/jvminit.c @@ -5888,6 +5888,14 @@ protectedInitializeJavaVM(J9PortLibrary* portLibrary, void * userData) } #endif +#if defined(J9VM_OPT_METHOD_HANDLE) + /* Enable i2j MethodHandle transitions by default */ + vm->extendedRuntimeFlags |= J9_EXTENDED_RUNTIME_I2J_MH_TRANSITION_ENABLED; +#endif + + /* Default to using lazy in all but realtime */ + vm->extendedRuntimeFlags |= J9_EXTENDED_RUNTIME_LAZY_SYMBOL_RESOLUTION; + /* Scans cmd-line arguments in order */ if (JNI_OK != processVMArgsFromFirstToLast(vm)) { goto error; @@ -6046,14 +6054,6 @@ protectedInitializeJavaVM(J9PortLibrary* portLibrary, void * userData) if (JNI_OK != modifyDllLoadTable(vm, vm->dllLoadTable, vm->vmArgsArray)) { goto error; } - -#if defined(J9VM_OPT_METHOD_HANDLE) - /* Enable i2j MethodHandle transitions by default */ - vm->extendedRuntimeFlags |= J9_EXTENDED_RUNTIME_I2J_MH_TRANSITION_ENABLED; -#endif - - /* Default to using lazy in all but realtime */ - vm->extendedRuntimeFlags |= J9_EXTENDED_RUNTIME_LAZY_SYMBOL_RESOLUTION; #if !defined(WIN32) if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags,J9_EXTENDED_RUNTIME_HANDLE_SIGXFSZ)) { From de2596829843071a30a4d0101f7ea7a482871984 Mon Sep 17 00:00:00 2001 From: Peter Shipton Date: Fri, 3 Apr 2020 11:58:48 -0400 Subject: [PATCH 27/61] Include sanity.openjdk for AIX, Windows, Mac The sanity.openjdk target has been reconfigured to match the OpenJDK tier1 testing. The tests which used to fail on the excluded platforms are moved out of this suite. Signed-off-by: Peter Shipton --- buildenv/jenkins/variables/defaults.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/buildenv/jenkins/variables/defaults.yml b/buildenv/jenkins/variables/defaults.yml index 5c8898be894..dda609e6261 100644 --- a/buildenv/jenkins/variables/defaults.yml +++ b/buildenv/jenkins/variables/defaults.yml @@ -276,10 +276,6 @@ ppc64_aix: 14: 'PATH+XLC=/opt/IBM/xlC/16.1.0/bin:/opt/IBM/xlc/16.1.0/bin CC=xlclang CXX=xlclang++' next: 'PATH+XLC=/opt/IBM/xlC/16.1.0/bin:/opt/IBM/xlc/16.1.0/bin CC=xlclang CXX=xlclang++' excluded_tests: - 8: - - sanity.openjdk - 11: - - sanity.openjdk - special.system #========================================# # Linux x86 64bits Compressed Pointers @@ -375,10 +371,7 @@ x86-64_windows: build_env: vars: 'PATH+TOOLS=/cygdrive/c/openjdk/LLVM64/bin:/cygdrive/c/openjdk/nasm-2.13.03' excluded_tests: - 8: - - sanity.openjdk 11: - - sanity.openjdk - special.system #========================================# # Windows x86 64bits Large Heap @@ -405,10 +398,7 @@ x86-32_windows: 8: 'PATH+TOOLS=/cygdrive/c/openjdk/LLVM32/bin:/cygdrive/c/openjdk/nasm-2.13.03' excluded_tests: 8: - - sanity.openjdk - special.system - 11: - - sanity.openjdk #========================================# # OSX x86 64bits Compressed Pointers #========================================# @@ -436,10 +426,7 @@ x86-64_mac: all: 'OPENJ9_JAVA_OPTIONS=-Xdump:system+java:events=systhrow,filter=java/lang/ClassCastException,request=exclusive+prepwalk+preempt' 8: 'MACOSX_DEPLOYMENT_TARGET=10.9.0 SDKPATH=/Users/jenkins/Xcode4/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk' excluded_tests: - 8: - - sanity.openjdk 11: - - sanity.openjdk - special.system #========================================# # OSX x86 64bits Large Heap From 00c13bccf63b3ebdfa9d444644dee7591c3054b5 Mon Sep 17 00:00:00 2001 From: Graham Chapman Date: Fri, 3 Apr 2020 12:14:00 -0400 Subject: [PATCH 28/61] General cleanup Remove unused flags and files. Signed-off-by: Graham Chapman --- .../vm29/j9/stackwalker/JITStackWalker.java | 6 +--- runtime/codert_vm/dlt.c | 3 +- runtime/codert_vm/jswalk.c | 8 +---- runtime/oti/stackwalk.h | 4 +-- runtime/oti/util_api.h | 11 ------ runtime/util/CMakeLists.txt | 3 +- runtime/util/sleephelp.c | 35 ------------------- runtime/vm/BytecodeInterpreter.hpp | 1 - 8 files changed, 6 insertions(+), 65 deletions(-) delete mode 100644 runtime/util/sleephelp.c diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITStackWalker.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITStackWalker.java index 24e97352919..4c050e71682 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITStackWalker.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITStackWalker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2019 IBM Corp. and others + * Copyright (c) 2009, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -293,10 +293,6 @@ public FrameCallbackResult jitWalkStackFrames(WalkState walkState) walkState.arg0EA = walkState.i2jState.a0(); returnSP = walkState.i2jState.returnSP(); walkState.previousFrameFlags = new UDATA(0); - if (returnSP.anyBitsIn(J9_STACK_FLAGS_ARGS_ALIGNED)) { - swPrintf(walkState, 2, "I2J args were copied for alignment"); - walkState.previousFrameFlags = new UDATA(J9_STACK_FLAGS_JIT_ARGS_ALIGNED); - } walkState.walkSP = returnSP.untag(3L); swPrintf(walkState, 2, "I2J values: PC = {0}, A0 = {1}, walkSP = {2}, literals = {3}, JIT PC = {4}, pcAddress = {5}, decomp = {6}", walkState.pc.getHexAddress(), diff --git a/runtime/codert_vm/dlt.c b/runtime/codert_vm/dlt.c index 0c3101a8beb..901ad8f53c1 100644 --- a/runtime/codert_vm/dlt.c +++ b/runtime/codert_vm/dlt.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2001, 2014 IBM Corp. and others + * Copyright (c) 2001, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -194,7 +194,6 @@ setUpForDLT(J9VMThread * currentThread, J9StackWalkState * walkState) if (J9_ARE_ANY_BITS_SET((UDATA)sp, sizeof(UDATA))) { Trc_DLT_setUpForDLT_Aligning_Arguments(currentThread); memmove((walkState->sp = sp - 1), sp, argCount * sizeof(UDATA)); - returnSP = (UDATA *) ((UDATA) returnSP | J9_STACK_FLAGS_ARGS_ALIGNED); } elsState->returnSP = returnSP; } diff --git a/runtime/codert_vm/jswalk.c b/runtime/codert_vm/jswalk.c index c2b2ee38068..18d59ff3610 100644 --- a/runtime/codert_vm/jswalk.c +++ b/runtime/codert_vm/jswalk.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1991, 2019 IBM Corp. and others + * Copyright (c) 1991, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -291,12 +291,6 @@ i2jTransition: ; walkState->arg0EA = (UDATA *) walkState->i2jState->a0; returnSP = walkState->i2jState->returnSP; walkState->previousFrameFlags = 0; - if (((UDATA) returnSP) & J9_STACK_FLAGS_ARGS_ALIGNED) { -#ifdef J9VM_INTERP_STACKWALK_TRACING - swPrintf(walkState, 2, "I2J args were copied for alignment\n"); -#endif - walkState->previousFrameFlags = J9_STACK_FLAGS_JIT_ARGS_ALIGNED; - } walkState->walkSP = (UDATA *) UNTAG2(returnSP, UDATA *); #ifdef J9VM_INTERP_STACKWALK_TRACING swPrintf(walkState, 2, "I2J values: PC = %p, A0 = %p, walkSP = %p, literals = %p, JIT PC = %p, pcAddress = %p, decomp = %p\n", walkState->pc, diff --git a/runtime/oti/stackwalk.h b/runtime/oti/stackwalk.h index 72b6300c26f..990be90e7a3 100644 --- a/runtime/oti/stackwalk.h +++ b/runtime/oti/stackwalk.h @@ -113,11 +113,11 @@ extern "C" { #define J9_STACK_FLAGS_UNUSED_0x80000000 0x80000000 #define J9_STACK_FLAGS_JIT_CALL_IN_TYPE_J2_I 0x00000000 #define J9_STACK_FLAGS_JNI_REFS_REDIRECTED 0x00010000 -#define J9_STACK_FLAGS_ARGS_ALIGNED 0x00000002 +#define J9_STACK_FLAGS_UNUSED_0x2 0x00000002 #define J9_STACK_FLAGS_JIT_JNI_CALL_OUT_FRAME 0x20000000 #define J9_STACK_FLAGS_RELEASE_VMACCESS 0x00020000 #define J9_STACK_REPORT_FRAME_POP 0x00000001 -#define J9_STACK_FLAGS_JIT_ARGS_ALIGNED 0x04000000 +#define J9_STACK_FLAGS_JIT_UNUSED_0x04000000 0x04000000 #define J9_JNI_PUSHED_REFERENCE_COUNT_MASK 0x000000FF #define J9_STACK_FLAGS_CALL_OUT_FRAME_ALLOCATED 0x00020000 diff --git a/runtime/oti/util_api.h b/runtime/oti/util_api.h index 37e9e35263b..552ac768344 100644 --- a/runtime/oti/util_api.h +++ b/runtime/oti/util_api.h @@ -1652,17 +1652,6 @@ getOriginalROMMethod(J9Method * method); J9ROMMethod * getOriginalROMMethodUnchecked(J9Method * method); -/* ---------------- sleephelp.c ---------------- */ - -/** -* @brief -* @param sleepTime -* @return IDATA -*/ -IDATA -callThreadSleep(IDATA sleepTime); - - /* ---------------- subclass.c ---------------- */ /** diff --git a/runtime/util/CMakeLists.txt b/runtime/util/CMakeLists.txt index 26edfd84bd4..07a1c749391 100644 --- a/runtime/util/CMakeLists.txt +++ b/runtime/util/CMakeLists.txt @@ -1,5 +1,5 @@ ################################################################################ -# Copyright (c) 2017, 2019 IBM Corp. and others +# Copyright (c) 2017, 2020 IBM Corp. and others # # This program and the accompanying materials are made available under # the terms of the Eclipse Public License 2.0 which accompanies this @@ -80,7 +80,6 @@ add_library(j9util STATIC romhelp.c sendslot.c shchelp_j9.c - sleephelp.c srphashtable.c strhelp.c subclass.c diff --git a/runtime/util/sleephelp.c b/runtime/util/sleephelp.c deleted file mode 100644 index d5e43dd01cc..00000000000 --- a/runtime/util/sleephelp.c +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * Copyright (c) 1991, 2014 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -#include "omrthread.h" -#include "j9protos.h" -#include "util_internal.h" - -IDATA -callThreadSleep(IDATA sleepTime) -{ - return omrthread_sleep(sleepTime); -} - - - - diff --git a/runtime/vm/BytecodeInterpreter.hpp b/runtime/vm/BytecodeInterpreter.hpp index 7b3f98eda5c..dee68ca37ff 100644 --- a/runtime/vm/BytecodeInterpreter.hpp +++ b/runtime/vm/BytecodeInterpreter.hpp @@ -792,7 +792,6 @@ class INTERPRETER_CLASS if (J9_ARE_ANY_BITS_SET((UDATA)_sp, sizeof(UDATA))) { _sp -= 1; memmove(_sp, _sp + 1, sizeof(UDATA) * argCount); - returnSP |= J9_STACK_FLAGS_ARGS_ALIGNED; } J9I2JState *i2jState = &_currentThread->entryLocalStorage->i2jState; i2jState->returnSP = (UDATA*)returnSP; From b18e4c9e8c858f4704857b18a88434b69cfd3b25 Mon Sep 17 00:00:00 2001 From: Ashutosh Mehra Date: Fri, 3 Apr 2020 20:19:40 +0000 Subject: [PATCH 29/61] Protect including Listener.hpp by J9VM_OPT_JITSERVER Header file specific to JITServer should be protected by J9VM_OPT_JITSERVER when including them. Signed-off-by: Ashutosh Mehra --- runtime/compiler/control/DLLMain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtime/compiler/control/DLLMain.cpp b/runtime/compiler/control/DLLMain.cpp index 53f9a690b75..2ead34fa0e6 100644 --- a/runtime/compiler/control/DLLMain.cpp +++ b/runtime/compiler/control/DLLMain.cpp @@ -30,7 +30,9 @@ #include "env/VMJ9.h" #include "runtime/IProfiler.hpp" #include "runtime/J9Profiler.hpp" +#if defined(J9VM_OPT_JITSERVER) #include "runtime/Listener.hpp" +#endif /* J9VM_OPT_JITSERVER */ #include "runtime/codertinit.hpp" #include "rossa.h" From 7b9fa4fd925ff354520dc89a4e77ccffc75cb165 Mon Sep 17 00:00:00 2001 From: Devin Nakamura Date: Thu, 2 Apr 2020 11:53:20 -0400 Subject: [PATCH 30/61] Enable c99 interfaces on zos Needed for eclipse/omr#4645 Signed-off-by: Devin Nakamura --- runtime/makelib/targets.mk.zos.inc.ftl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/runtime/makelib/targets.mk.zos.inc.ftl b/runtime/makelib/targets.mk.zos.inc.ftl index 25791bf44b0..a32f5b1e097 100644 --- a/runtime/makelib/targets.mk.zos.inc.ftl +++ b/runtime/makelib/targets.mk.zos.inc.ftl @@ -1,5 +1,5 @@ <#-- -Copyright (c) 1998, 2019 IBM Corp. and others +Copyright (c) 1998, 2020 IBM Corp. and others This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this @@ -68,7 +68,9 @@ ifdef j9vm_uma_supportsIpv6 UMA_ZOS_FLAGS += -DIPv6_FUNCTION_SUPPORT endif -UMA_ZOS_FLAGS += -DJ9ZOS390 -DLONGLONG -DJ9VM_TIERED_CODE_CACHE -D_ALL_SOURCE -D_XOPEN_SOURCE_EXTENDED -DIBM_ATOE -D_POSIX_SOURCE +# _ISOC99_SOURCE Exposes c99 standard library changes which dont require c99 compiler support. (Also needed for c++, see below) +# __STDC_LIMIT_MACROS Is needed to expose limit macros from on c++ (also requires _ISOC99_SOURCE) +UMA_ZOS_FLAGS += -DJ9ZOS390 -DLONGLONG -DJ9VM_TIERED_CODE_CACHE -D_ALL_SOURCE -D_XOPEN_SOURCE_EXTENDED -DIBM_ATOE -D_POSIX_SOURCE -D_ISOC99_SOURCE -D__STDC_LIMIT_MACROS UMA_ZOS_FLAGS += -I$(OMR_DIR)/util/a2e/headers $(UMA_OPTIMIZATION_FLAGS) $(UMA_OPTIMIZATION_LINKER_FLAGS) \ -Wc,"convlit(ISO8859-1),xplink,rostring,FLOAT(IEEE,FOLD,AFP),enum(4)" -Wa,goff -Wc,NOANSIALIAS -Wc,"inline(auto,noreport,600,5000)" UMA_ZOS_FLAGS += -Wc,"SERVICE(j${uma.buildinfo.build_date})" -Wc,"TARGET(zOSV1R13)" From ccfb10cab5b7cfd26a30c256882d6764b3d78ea8 Mon Sep 17 00:00:00 2001 From: Marius Pirvu Date: Fri, 3 Apr 2020 21:00:13 -0400 Subject: [PATCH 31/61] Reduce number of VM_getClassFromSignature messages JITServer employs a cache to reduce the number of VM_getClassFromSignature messages, but this not entirely efficient for AOT compilations because the AOT frontend also performs some validation of the class found. If the validation fails getClassFromSignature() return NULL and the caching is not going to be performed at the server. In this commit the client will call the TR_J9VM version of getClassFromSignature() irrespective of the type of frontend. The class that is found is sent to server which caches it and then proceeds to perform the validation. Issue: #9116 Signed-off-by: Marius Pirvu --- runtime/compiler/control/JITClientCompilationThread.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index 14108abe23f..9997ee8b1db 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -285,11 +285,14 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes break; case MessageType::VM_getClassFromSignature: { + // Need to get a non-AOT frontend because the AOT frontend also + // performs some class validation which we want to do at the server + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); auto recv = client->getRecvData(); std::string sig = std::get<0>(recv); auto method = std::get<1>(recv); bool isVettedForAOT = std::get<2>(recv); - auto clazz = fe->getClassFromSignature(sig.c_str(), sig.length(), method, isVettedForAOT); + auto clazz = fej9->getClassFromSignature(sig.c_str(), sig.length(), method, isVettedForAOT); client->write(response, clazz); } break; From a49057255cbcae4e22e431b332991037fba0a4ec Mon Sep 17 00:00:00 2001 From: Chris Chong Date: Wed, 1 Apr 2020 06:09:33 -0700 Subject: [PATCH 32/61] Move FrontEnd noMultipleConcreteClasses into ClassEnv OMR FrontEnd is depreciated Thus removing noMultipleConcreteClasses frontend query, and move it to ClassEnv Also rename the function to containesZeroOrOneConcreteClass Signed-off-by: Chris Chong --- runtime/compiler/env/J9ClassEnv.cpp | 58 +++++++++++++++++++++++++++++ runtime/compiler/env/J9ClassEnv.hpp | 11 ++++++ runtime/compiler/env/VMJ9.cpp | 22 ----------- runtime/compiler/env/VMJ9.h | 2 - runtime/compiler/env/VMJ9Server.cpp | 49 ------------------------ runtime/compiler/env/VMJ9Server.hpp | 1 - 6 files changed, 69 insertions(+), 74 deletions(-) diff --git a/runtime/compiler/env/J9ClassEnv.cpp b/runtime/compiler/env/J9ClassEnv.cpp index b922615a861..2f41c4f970e 100644 --- a/runtime/compiler/env/J9ClassEnv.cpp +++ b/runtime/compiler/env/J9ClassEnv.cpp @@ -37,7 +37,10 @@ #include "j9cfg.h" #include "j9fieldsInfo.h" #include "rommeth.h" +#include "runtime/RuntimeAssumptions.hpp" +class TR_PersistentClassInfo; +template class List; /* REQUIRES STATE (_vmThread). MOVE vmThread to COMPILATION @@ -650,3 +653,58 @@ J9::ClassEnv::isZeroInitializable(TR_OpaqueClassBlock *clazz) { return (self()->classFlagsValue(clazz) & J9ClassContainsUnflattenedFlattenables) == 0; } + +bool +J9::ClassEnv::containesZeroOrOneConcreteClass(TR::Compilation *comp, List* subClasses) + { + int count = 0; +#if defined(J9VM_OPT_JITSERVER) + ListIterator j(subClasses); + TR_ScratchList subClassesNotCached(comp->trMemory()); + + // Process classes cached at the server first + ClientSessionData * clientData = TR::compInfoPT->getClientData(); + for (TR_PersistentClassInfo *ptClassInfo = j.getFirst(); ptClassInfo; ptClassInfo = j.getNext()) + { + TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); + J9Class *j9clazz = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz); + auto romClass = JITServerHelpers::getRemoteROMClassIfCached(clientData, j9clazz); + if (romClass == NULL) + { + subClassesNotCached.add(ptClassInfo); + } + else + { + if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) + { + count++; + } + if (count > 1) + { + return false; + } + } + } + + // Traverse though classes that are not cached on server + // With the following for loop outside if defined block + ListIterator i(&subClassesNotCached); +#else + ListIterator i(subClasses); +#endif /* defined(J9VM_OPT_JITSERVER) */ + + for (TR_PersistentClassInfo *ptClassInfo = i.getFirst(); ptClassInfo; ptClassInfo = i.getNext()) + { + TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); + if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) + { + count++; + } + if (count > 1) + { + return false; + } + } + + return true; + } diff --git a/runtime/compiler/env/J9ClassEnv.hpp b/runtime/compiler/env/J9ClassEnv.hpp index 7b03702dcd9..3f6bc15c950 100644 --- a/runtime/compiler/env/J9ClassEnv.hpp +++ b/runtime/compiler/env/J9ClassEnv.hpp @@ -43,6 +43,8 @@ namespace J9 { typedef J9::ClassEnv ClassEnvConnector; } namespace TR { class SymbolReference; } namespace TR { class TypeLayout; } namespace TR { class Region; } +class TR_PersistentClassInfo; +template class List; namespace J9 { @@ -169,6 +171,15 @@ class OMR_EXTENSIBLE ClassEnv : public OMR::ClassEnvConnector intptr_t getVFTEntry(TR::Compilation *comp, TR_OpaqueClassBlock* clazz, int32_t offset); uint8_t *getROMClassRefName(TR::Compilation *comp, TR_OpaqueClassBlock *clazz, uint32_t cpIndex, int &classRefLen); J9ROMConstantPoolItem *getROMConstantPool(TR::Compilation *comp, TR_OpaqueClassBlock *clazz); + + /** + * @brief Determine if a list of classes contains less than two concrete classes. + * A class is considered concrete if it is not an interface or an abstract class + * @param subClasses List of subclasses to be checked. + * @return Returns 'true' if the given list of classes contains less than + * 2 concrete classses and false otherwise. + */ + bool containesZeroOrOneConcreteClass(TR::Compilation *comp, List* subClasses); }; } diff --git a/runtime/compiler/env/VMJ9.cpp b/runtime/compiler/env/VMJ9.cpp index 34c444b6012..5a02f36b314 100644 --- a/runtime/compiler/env/VMJ9.cpp +++ b/runtime/compiler/env/VMJ9.cpp @@ -8351,28 +8351,6 @@ TR_J9VM::getROMMethodFromRAMMethod(J9Method *ramMethod) return J9_ROM_METHOD_FROM_RAM_METHOD(ramMethod); } -bool -TR_J9VM::noMultipleConcreteClasses(List* subClasses) - { - TR::Compilation *comp = _compInfoPT->getCompilation(); - int count = 0; - ListIterator i(subClasses); - for (TR_PersistentClassInfo *ptClassInfo = i.getFirst(); ptClassInfo; ptClassInfo = i.getNext()) - { - TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); - if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) - { - count++; - } - if (count > 1) - { - return false; - } - } - - return true; - } - ////////////////////////////////////////////////////////// // TR_J9SharedCacheVM ////////////////////////////////////////////////////////// diff --git a/runtime/compiler/env/VMJ9.h b/runtime/compiler/env/VMJ9.h index ca1eaef6f32..11a4075ac48 100644 --- a/runtime/compiler/env/VMJ9.h +++ b/runtime/compiler/env/VMJ9.h @@ -1127,8 +1127,6 @@ class TR_J9VM : public TR_J9VMBase TR_OpaqueClassBlock * getClassFromSignature(const char * sig, int32_t sigLength, J9ConstantPool * constantPool); - virtual bool noMultipleConcreteClasses(List* subClasses); - private: void transformJavaLangClassIsArrayOrIsPrimitive( TR::Compilation *, TR::Node * callNode, TR::TreeTop * treeTop, int32_t andMask); void transformJavaLangClassIsArray( TR::Compilation *, TR::Node * callNode, TR::TreeTop * treeTop); diff --git a/runtime/compiler/env/VMJ9Server.cpp b/runtime/compiler/env/VMJ9Server.cpp index aaee006f148..ad537a66a53 100644 --- a/runtime/compiler/env/VMJ9Server.cpp +++ b/runtime/compiler/env/VMJ9Server.cpp @@ -1837,55 +1837,6 @@ TR_J9ServerVM::getObjectSizeClass(uintptr_t objectSize) return 0; } -bool -TR_J9ServerVM::noMultipleConcreteClasses(List* subClasses) - { - TR::Compilation *comp = _compInfoPT->getCompilation(); - int count = 0; - TR_ScratchList subClassesNotCached(comp->trMemory()); - - // Process classes caches at the server first - ListIterator i(subClasses); - for (TR_PersistentClassInfo *ptClassInfo = i.getFirst(); ptClassInfo; ptClassInfo = i.getNext()) - { - TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); - J9Class *j9clazz = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz); - auto romClass = JITServerHelpers::getRemoteROMClassIfCached(_compInfoPT->getClientData(), j9clazz); - if (romClass == NULL) - { - subClassesNotCached.add(ptClassInfo); - } - else - { - if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) - { - count++; - } - if (count > 1) - { - return false; - } - } - } - - // Traverse though classes that are not cached on server - ListIterator j(&subClassesNotCached); - for (TR_PersistentClassInfo *ptClassInfo = j.getFirst(); ptClassInfo; ptClassInfo = j.getNext()) - { - TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); - if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) - { - count++; - } - if (count > 1) - { - return false; - } - } - - return true; - } - bool TR_J9SharedCacheServerVM::isClassLibraryMethod(TR_OpaqueMethodBlock *method, bool vettedForAOT) { diff --git a/runtime/compiler/env/VMJ9Server.hpp b/runtime/compiler/env/VMJ9Server.hpp index 4ba0876e1bd..fc999eaf3b9 100644 --- a/runtime/compiler/env/VMJ9Server.hpp +++ b/runtime/compiler/env/VMJ9Server.hpp @@ -187,7 +187,6 @@ class TR_J9ServerVM: public TR_J9VM virtual J9ROMMethod *getROMMethodFromRAMMethod(J9Method *ramMethod) override; virtual bool getReportByteCodeInfoAtCatchBlock() override; virtual void *getInvokeExactThunkHelperAddress(TR::Compilation *comp, TR::SymbolReference *glueSymRef, TR::DataType dataType) override; - virtual bool noMultipleConcreteClasses(List* subClasses) override; virtual uintptr_t getCellSizeForSizeClass(uintptr_t) override; virtual uintptr_t getObjectSizeClass(uintptr_t) override; From 263f12d091904bf098ed99a0e7f486e375478fb0 Mon Sep 17 00:00:00 2001 From: AlenBadel Date: Thu, 2 Apr 2020 18:47:18 -0400 Subject: [PATCH 33/61] Changing compare and branch for unresolved snippets within FieldWatch Replacing Andi. with Cmpi to branch into unresolved snippet routine. Signed-off-by: AlenBadel --- runtime/compiler/p/codegen/J9TreeEvaluator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/compiler/p/codegen/J9TreeEvaluator.cpp b/runtime/compiler/p/codegen/J9TreeEvaluator.cpp index 9f132dceff8..26f9f780253 100644 --- a/runtime/compiler/p/codegen/J9TreeEvaluator.cpp +++ b/runtime/compiler/p/codegen/J9TreeEvaluator.cpp @@ -988,8 +988,8 @@ J9::Power::TreeEvaluator::generateFillInDataBlockSequenceForUnresolvedField(TR:: TR::Register *cndReg = cg->allocateRegister(TR_CCR); generateTrg1MemInstruction(cg, TR::InstOpCode::Op_load, node, scratchReg, new (cg->trHeapMemory()) TR::MemoryReference(dataSnippetRegister, offsetInDataBlock, TR::Compiler->om.sizeofReferenceAddress(), cg)); - generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, scratchReg, scratchReg, cndReg, -1); - generateConditionalBranchInstruction(cg, TR::InstOpCode::bne, node, unresolvedLabel, cndReg); + generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::Op_cmpi, node, cndReg, scratchReg, -1); + generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, unresolvedLabel, cndReg); generateReportOOL->swapInstructionListsWithCompilation(); From 2f4b050068ea59eefcb6ea972633f6bfc5918b59 Mon Sep 17 00:00:00 2001 From: Filip Jeremic Date: Wed, 1 Apr 2020 15:58:54 -0400 Subject: [PATCH 34/61] Consolidate jitdump functionality into JitDump.cpp All functions related to jitdump generation are placed into JitDump.cpp and only the functions required external linkage are placed into the corresponding header file. This is the first step towards refactoring and improving the jitdump functionality and documentation. Signed-off-by: Filip Jeremic --- runtime/compiler/build/files/common.mk | 1 + runtime/compiler/control/CMakeLists.txt | 1 + .../compiler/control/CompilationThread.cpp | 14 +- runtime/compiler/control/HookedByTheJit.cpp | 654 ---------------- runtime/compiler/control/JitDump.cpp | 737 ++++++++++++++++++ runtime/compiler/control/JitDump.hpp | 38 + runtime/compiler/control/rossa.cpp | 5 +- 7 files changed, 779 insertions(+), 671 deletions(-) create mode 100644 runtime/compiler/control/JitDump.cpp create mode 100644 runtime/compiler/control/JitDump.hpp diff --git a/runtime/compiler/build/files/common.mk b/runtime/compiler/build/files/common.mk index b11fc2df578..7404c2a5044 100644 --- a/runtime/compiler/build/files/common.mk +++ b/runtime/compiler/build/files/common.mk @@ -275,6 +275,7 @@ JIT_PRODUCT_SOURCE_FILES+=\ compiler/control/DLLMain.cpp \ compiler/control/HookedByTheJit.cpp \ compiler/control/J9Options.cpp \ + compiler/control/JitDump.cpp \ compiler/control/MethodToBeCompiled.cpp \ compiler/control/rossa.cpp \ compiler/env/ClassLoaderTable.cpp \ diff --git a/runtime/compiler/control/CMakeLists.txt b/runtime/compiler/control/CMakeLists.txt index 9f7632920d6..d32444d88b6 100644 --- a/runtime/compiler/control/CMakeLists.txt +++ b/runtime/compiler/control/CMakeLists.txt @@ -27,6 +27,7 @@ j9jit_files( control/HookedByTheJit.cpp control/J9Options.cpp control/J9Recompilation.cpp + control/JitDump.cpp control/MethodToBeCompiled.cpp control/rossa.cpp ) diff --git a/runtime/compiler/control/CompilationThread.cpp b/runtime/compiler/control/CompilationThread.cpp index 531d69efb56..aae57c00758 100644 --- a/runtime/compiler/control/CompilationThread.cpp +++ b/runtime/compiler/control/CompilationThread.cpp @@ -49,6 +49,7 @@ #include "codegen/PrivateLinkage.hpp" #include "compile/CompilationTypes.hpp" #include "compile/ResolvedMethod.hpp" +#include "control/JitDump.hpp" #include "control/Recompilation.hpp" #include "control/RecompilationInfo.hpp" #include "control/MethodToBeCompiled.hpp" @@ -194,19 +195,6 @@ TR::CompilationInfoPerThreadBase::setCompilation(TR::Compilation *compiler) _compiler = compiler; } -#ifdef J9VM_RAS_DUMP_AGENTS -static UDATA -blankDumpSignalHandler(struct J9PortLibrary *portLibrary, U_32 gpType, void *gpInfo, void *arg) - { - J9VMThread *vmThread = (J9VMThread *) arg; - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "vmThread=%p Recursive crash occurred. Aborting JIT dump.", vmThread); - - // Returning J9PORT_SIG_EXCEPTION_RETURN will make us come back to the same crashing instruction over and over - // - return J9PORT_SIG_EXCEPTION_RETURN; // FIXME: is this the right return type? - This appears to be the right return type - } -#endif - #if defined(J9VM_OPT_JITSERVER) thread_local TR::CompilationInfoPerThread *TR::compInfoPT; #endif /* defined(J9VM_OPT_JITSERVER) */ diff --git a/runtime/compiler/control/HookedByTheJit.cpp b/runtime/compiler/control/HookedByTheJit.cpp index 8b3b173b261..840028c7e11 100644 --- a/runtime/compiler/control/HookedByTheJit.cpp +++ b/runtime/compiler/control/HookedByTheJit.cpp @@ -113,15 +113,6 @@ struct LDA { }; #endif -#define STACK_WALK_DEPTH 16 - -// struct to remember a method for JIT dump -typedef struct TR_MethodToBeCompiledForDump { - J9Method *_method; - void *_oldStartPC; - TR_Hotness _optLevel; -} TR_MethodToBeCompiledForDump; - #ifdef J9VM_JIT_RUNTIME_INSTRUMENTATION // extern until function is added to oti/jitprotos.h extern "C" void shutdownJITRuntimeInstrumentation(J9JavaVM *vm); @@ -1683,651 +1674,6 @@ static void initThreadAfterCreation(J9VMThread *vmThread) return; } -#ifdef J9VM_RAS_DUMP_AGENTS - -typedef struct DumpCurrentILParamenters - { - DumpCurrentILParamenters( - TR::Compilation *comp, - J9VMThread *vmThread, - J9JITConfig *jitConfig, - TR::FILE *logFile - ) : - _comp(comp), - _vmThread(vmThread), - _jitConfig(jitConfig), - _logFile(logFile) - {} - - TR::Compilation *_comp; - J9VMThread *_vmThread; - J9JITConfig *_jitConfig; - TR::FILE *_logFile; - } DumpCurrentILParamenters; - -static UDATA -blankDumpCurrentILSignalHandler(struct J9PortLibrary *portLibrary, U_32 gpType, void *gpInfo, void *arg) - { - J9VMThread *vmThread = (J9VMThread *) arg; - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "vmThread=%p Crashed while printing out current IL.", vmThread); - return J9PORT_SIG_EXCEPTION_RETURN; - } - -static void jitDumpFailedBecause(J9VMThread *currentThread, const char* message) - { - if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "JIT dump failed because %s", message); - Trc_JIT_DumpFail(currentThread, message); - return; - } - -static void stackWalkEndingBecause(const char* message) - { - if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "stack walk ending because %s", message); - return; - } - -static UDATA dumpCurrentILProtected(J9PortLibrary *portLib, void * opaqueParameters) - { - DumpCurrentILParamenters *p = static_cast(opaqueParameters); - TR::Compilation *comp = p->_comp; - J9VMThread *vmThread = p->_vmThread; - J9JITConfig *jitConfig = p->_jitConfig; - TR::FILE *logFile = p->_logFile; - - comp->findOrCreateDebug(); - - TR::Options *options = comp->getOptions(); - TR_Debug *dbg = comp->getDebug(); - TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, vmThread); - - if (logFile != NULL) - { - comp->setOutFile(logFile); - options->setOption(TR_TraceAll); - options->setOption(TR_TraceKnownObjectGraph); - dbg->setFile(logFile); - - trfprintf(logFile,"\n"); - - // Print Bytecodes - TR::IlGeneratorMethodDetails & details = comp->ilGenRequest().details(); - TR::ResolvedMethodSymbol *resolvedMethod = comp->getMethodSymbol(); - TR::SymbolReferenceTable *symRefTab = comp->getSymRefTab(); - TR_J9ByteCodeIlGenerator bci(details, resolvedMethod, fe, comp, symRefTab); - bci.printByteCodes(); - - dbg->printMethodHotness(); - comp->dumpMethodTrees("Trees"); - dbg->print(logFile, comp->getSymRefTab()); - - int bitMask = J9VMSTATE_JIT_CODEGEN | 0x0000FF00; // 0xFF?? is Codegen Phase - if ( ((vmThread->omrVMThread->vmState) & bitMask) == bitMask ) // if we are in the Codegen Phase - { - dbg->dumpMethodInstrs(logFile, "Post Binary Instructions", false, true); - - dbg->print(logFile,comp->cg()->getSnippetList(), true); // print Warm Snippets - dbg->print(logFile,comp->cg()->getSnippetList(), false); - - dbg->dumpMixedModeDisassembly(); - } - - // leaving to the very end in case there is a crash before this point. - comp->verifyTrees(comp->getMethodSymbol()); - comp->verifyBlocks(comp->getMethodSymbol()); - - trfprintf(logFile, "\n"); - } - - return 0; - } - -static void dumpCurrentIL(TR::Compilation *comp, J9VMThread *vmThread, J9JITConfig *jitConfig, TR::FILE *logFile ) - { - /* Acquire VM Access */ - bool alreadyHaveVMAccess = ((vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS) != 0); - bool haveAcquiredVMAccess = false; - if (!alreadyHaveVMAccess) - if (0 == vmThread->javaVM->internalVMFunctions->internalTryAcquireVMAccessWithMask(vmThread, J9_PUBLIC_FLAGS_HALT_THREAD_ANY_NO_JAVA_SUSPEND)) - haveAcquiredVMAccess = true; - - PORT_ACCESS_FROM_JITCONFIG(jitConfig); - - DumpCurrentILParamenters p( - comp, - vmThread, - jitConfig, - logFile - ); - - UDATA result = 0; - -#if defined(J9VM_PORT_SIGNAL_SUPPORT) - U_32 flags = J9PORT_SIG_FLAG_MAY_RETURN | - J9PORT_SIG_FLAG_SIGSEGV | J9PORT_SIG_FLAG_SIGFPE | - J9PORT_SIG_FLAG_SIGILL | J9PORT_SIG_FLAG_SIGBUS; - - static char *noSignalWrapper = feGetEnv("TR_NoSignalWrapper"); - - if (!noSignalWrapper && j9sig_can_protect(flags)) - { - UDATA protectedResult; - - protectedResult = j9sig_protect((j9sig_protected_fn)dumpCurrentILProtected, static_cast(&p), - (j9sig_handler_fn)blankDumpCurrentILSignalHandler, vmThread, - flags, &result); - } - else -#endif - result = dumpCurrentILProtected(privatePortLibrary, &p); - - - /* Release VM Access */ - if (!alreadyHaveVMAccess) - if (haveAcquiredVMAccess) - vmThread->javaVM->internalVMFunctions->internalReleaseVMAccess(vmThread); - } - -// Stack frame iterator. Iterates until STACK_WALK_DEPTH frames or the top are reached. -static UDATA logStackIterator(J9VMThread *currentThread, J9StackWalkState *walkState) - { - Trc_JIT_DumpWalkingFrame(currentThread); - - // stop iterating if the walk state is null - if (!walkState) - { - stackWalkEndingBecause("got a null walkState"); - return J9_STACKWALK_STOP_ITERATING; - } - - // get user data from walk state - TR_MethodToBeCompiledForDump* jittedMethodsOnStack = (TR_MethodToBeCompiledForDump *) walkState->userData1; - int *currentMethodIndex = (int *) walkState->userData2; - - // also stop iterating if passed user data is null - if (currentMethodIndex == 0 || jittedMethodsOnStack == 0) - { - stackWalkEndingBecause("one or both user data are null"); - return J9_STACKWALK_STOP_ITERATING; - } - - // also stop iterating if enough frames have been reached - if ((*currentMethodIndex) >= STACK_WALK_DEPTH) - { - stackWalkEndingBecause("reached limit on number of methods to recompile"); - return J9_STACKWALK_STOP_ITERATING; - } - - // if the frame has jit metadata, then it belongs to a JITed method - if (walkState->jitInfo) - { - // NOTE: method is the one (J9Method, a.k.a. TR_OpaqueMethodBlock) that gets - // passed to IlGeneratorMethodDetails - TR_ASSERT(walkState->method, "Found method metadata on the stack, but method is null."); - - // get method's body info (can be null) - TR_PersistentJittedBodyInfo* bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC((void*) walkState->jitInfo->startPC); - - // get global configuration options - TR::Options *options = TR::Options::getCmdLineOptions(); - - // get global opt level - // NOTE: getOptLevel returns -1 if it is not set - TR_Hotness globalOptLevel = (TR_Hotness) (-1); - if (options) - globalOptLevel = (TR_Hotness) options->getFixedOptLevel(); - - // add the method to our list ONLY if level can be determined; it can be determined - // either from body info (if it exists), or from fixed level (if it was set) - if (bodyInfo || (globalOptLevel != (-1))) - { - // set the method - jittedMethodsOnStack[*currentMethodIndex]._method = walkState->method; - - // set the method's oldStartPC: - // if bodyInfo exists, then we can do a recompilation (use startPCAfterPreviousCompile) - // if not, then we can't, and we do a first-time compilation (use 0) - if (bodyInfo) - jittedMethodsOnStack[*currentMethodIndex]._oldStartPC = bodyInfo->getStartPCAfterPreviousCompile(); - else - jittedMethodsOnStack[*currentMethodIndex]._oldStartPC = 0; - - // set the optLevel - if (bodyInfo) - jittedMethodsOnStack[*currentMethodIndex]._optLevel = bodyInfo->getHotness(); - else - // NOTE: global optLevel is not -1, since we checked for that above - jittedMethodsOnStack[*currentMethodIndex]._optLevel = globalOptLevel; - - // advance to the next method in the list - *currentMethodIndex = (*(currentMethodIndex) + 1); - } - } - - return J9_STACKWALK_KEEP_ITERATING; - } - -/// Recompiles a method for the JIT dump -static TR_CompilationErrorCode recompileMethodForLog( - J9VMThread *vmThread, - J9Method *ramMethod, - TR::CompilationInfo *compInfo, - TR_J9VMBase *frontendOfThread, - TR_Hotness optimizationLevel, - bool profilingCompile, - void *oldStartPC, - TR::FILE *logFile - ) - { - if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "recompiling a method for log: %p", ramMethod); - - Trc_JIT_DumpCompilingMethod(vmThread, ramMethod, optimizationLevel, oldStartPC); - - // the request to use Log should be passed to the compilation, via optimizationPlan - // then the option object created should use this to open the log; thus must create a new optimization plan - // the right optlevel would be set during the Options setting - TR_OptimizationPlan *plan = TR_OptimizationPlan::alloc(optimizationLevel); - if (!plan) - return compilationFailure; - - if (profilingCompile) - plan->setInsertInstrumentation(true); - - // pass the log file to the compilation - plan->setLogCompilation(logFile); - - bool successfullyQueued = false; - - trfprintf(logFile, "\n"); - - // actually request the compilation - if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo: compileMethod() about to issued synchronously"); - TR_CompilationErrorCode compErrCode; - - // Set the VM state of the crashed thread so the diagnostic thread can use consume it - compInfo->setVMStateOfCrashedThread(vmThread->omrVMThread->vmState); - - // create a compilation request - // NOTE: operator new() is overridden, and takes a storage object as a parameter - // TODO: this is indiscriminately compiling as J9::DumpMethodRequest, which is wrong; - // should be fixed by checking if the method is indeed DLT, and compiling DLT if so - { - J9::DumpMethodDetails details( ramMethod); - compInfo->compileMethod(vmThread, details, oldStartPC, TR_no, &compErrCode, &successfullyQueued, plan); - } - - if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo: crashing thread returned from compileMethod() with errorCode=%d", compErrCode); - - trfprintf(logFile, "\n"); - - // if the request failed, get rid of the optimization plan we made - if (!successfullyQueued) - TR_OptimizationPlan::freeOptimizationPlan(plan); - - return compErrCode; - } - -/// Dumps JIT-specific crash info -IDATA dumpJitInfo(J9VMThread *crashedThread, char *logFileLabel, J9RASdumpContext *context) - { - Trc_JIT_DumpStart(crashedThread); - -#if defined(J9VM_OPT_JITSERVER) - if (context && context->javaVM && context->javaVM->jitConfig) - { - J9JITConfig *jitConfig = context->javaVM->jitConfig; - TR::CompilationInfo *compInfo = TR::CompilationInfo::get(context->javaVM->jitConfig); - if (compInfo) - { - static char * isPrintJITServerMsgStats = feGetEnv("TR_PrintJITServerMsgStats"); - if (isPrintJITServerMsgStats && compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT) - JITServerHelpers::printJITServerMsgStats(jitConfig); - if (feGetEnv("TR_PrintJITServerCHTableStats")) - JITServerHelpers::printJITServerCHTableStats(jitConfig, compInfo); - if (feGetEnv("TR_PrintJITServerIPMsgStats")) - { - if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER) - { - TR_J9VMBase * vmj9 = (TR_J9VMBase *)(TR_J9VMBase::get(context->javaVM->jitConfig, 0)); - JITServerIProfiler *iProfiler = (JITServerIProfiler *)vmj9->getIProfiler(); - iProfiler->printStats(); - } - } - } - } -#endif - - if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "JIT dump initiated. Crashed vmThread=%p", crashedThread); - - // if either one of the args is null, we can't really do anything - if (crashedThread == 0 || logFileLabel == 0) - { - jitDumpFailedBecause(crashedThread, "one or both arguments are null"); - return 0; - } - - // if VM is gone, can't do anything either - if (crashedThread->javaVM == 0) - { - jitDumpFailedBecause(crashedThread, "VM pointer is null"); - return 0; - } - - // get a hold of jitConfig in order to later get compinfo and frontend - J9JITConfig * jitConfig = crashedThread->javaVM->jitConfig; - - // if jitConfig is gone, then we can't do anything either - if (jitConfig == 0) - { - jitDumpFailedBecause(crashedThread, "jitConfig is null"); - return 0; - } - // get global compinfo - TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig); - if (!compInfo) - { - jitDumpFailedBecause(crashedThread, "compInfo is null"); - return 0; - } - - // Must be able to allocate a frontend for this thread - TR_J9VMBase *frontendOfThread = TR_J9VMBase::get(jitConfig, crashedThread); - if (!frontendOfThread) - { - jitDumpFailedBecause(crashedThread, "thread's frontend is missing"); - return 0; - } - - // get global configuration options - TR::Options *options = TR::Options::getCmdLineOptions(); - if (!options) - { - jitDumpFailedBecause(crashedThread, "No cmdLineOptions available"); - return 0; - } - - - // open log file, using the postfixed timestamp if specified - TR::FILE *logFile; - char tmp[1025]; - logFileLabel = frontendOfThread->getFormattedName(tmp, 1025, logFileLabel, NULL, false); - logFile = trfopen(logFileLabel, "ab", false); - - trfprintf(logFile, - "\n" - "\n" - ); - - - // if some thread holds exclusive VM access we cannot do much - if (J9_XACCESS_NONE != jitConfig->javaVM->exclusiveAccessState) - { - jitDumpFailedBecause(crashedThread, "some thread is holding exclusive VM access"); - trfprintf(logFile, "Some thread is holding exclusive VM access. No log created.\n"); - trfclose(logFile); - return 0; - } - - - // to avoid deadlock, release compilation monitor until we are no longer holding it - while (compInfo->getCompilationMonitor()->owned_by_self()) - compInfo->releaseCompMonitor(crashedThread); - - // Release other monitors as well. In particular CHTable and classUnloadMonitor must not be held - while (TR::MonitorTable::get()->getClassTableMutex()->owned_by_self()) - frontendOfThread->releaseClassTableMutex(false); - - //FIXME: how do I detect that someone is holding the classUnloadMonitor - - // get crashed thread's own compinfo - TR::CompilationInfoPerThread *threadCompInfo = compInfo->getCompInfoForThread(crashedThread); - - // Crashes on the diagnostic thread should not be processed - if (threadCompInfo && threadCompInfo->isDiagnosticThread()) - { - jitDumpFailedBecause(crashedThread, "detected recursive crash"); - trfprintf(logFile, "Detected recursive crash. No log created.\n"); - trfclose(logFile); - return 0; - } - - // get the method currently being compiled - TR_MethodToBeCompiled *currentMethodBeingCompiled = 0; - if (threadCompInfo) - currentMethodBeingCompiled = threadCompInfo->getMethodBeingCompiled(); - - /* - * at this stage, we know that we are good to orchestrate a dump - */ - - if (options->getOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dump agent obtained necessary information to perform dump"); - - // if we are currently compiling a method, wake everyone waiting for it to compile - if (currentMethodBeingCompiled && currentMethodBeingCompiled->getMonitor()) - { - currentMethodBeingCompiled->getMonitor()->enter(); - currentMethodBeingCompiled->getMonitor()->notifyAll(); - currentMethodBeingCompiled->getMonitor()->exit(); - if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo notified all waiting threads"); - } - - // disable all non-essential compilations - compInfo->getPersistentInfo()->setDisableFurtherCompilation(true); - if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo disabled further compilation"); - - // get the dump thread - TR::CompilationInfoPerThread *recompilationThreadInfo = compInfo->getCompilationInfoForDumpThread(); - J9VMThread *recompilationThread = NULL; - if (recompilationThreadInfo) - recompilationThread = recompilationThreadInfo->getCompilationThread(); - - // purge the compilation queue if a thread was found - if (recompilationThread) - { - if (options->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo: diagnostic compilation thread available. Will purge compilation queue"); - compInfo->acquireCompMonitor(crashedThread); - compInfo->purgeMethodQueue(compilationFailure); // compilationFailure is a TR_CompilationErrorCode - compInfo->releaseCompMonitor(crashedThread); - } - - - - // if our compinfo is null, we are an application thread - if (threadCompInfo == 0) - { - if (options->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "crashed in application thread"); - trfprintf(logFile, "#INFO: Crashed in application thread %p.\n", crashedThread); - - // only bother doing anything if we have a healthy compilation thread available - if (recompilationThread) - { - // make space for methods to be recompiled - // FIXME: this is on the stack... is the stack big enough? - int currentMethodIndex = 0; - TR_MethodToBeCompiledForDump jittedMethodsOnStack[STACK_WALK_DEPTH] = { 0 }; - - // set up the stack walk object - J9StackWalkState walkState; - - walkState.userData1 = (void *)jittedMethodsOnStack; - walkState.userData2 = (void *)¤tMethodIndex; - walkState.walkThread = crashedThread; - walkState.skipCount = 0; - walkState.maxFrames = STACK_WALK_DEPTH; - walkState.flags = ( - // J9_STACKWALK_LINEAR | - // J9_STACKWALK_START_AT_JIT_FRAME | - // J9_STACKWALK_INCLUDE_NATIVES | - // J9_STACKWALK_HIDE_EXCEPTION_FRAMES | - // J9_STACKWALK_ITERATE_HIDDEN_JIT_FRAMES | - J9_STACKWALK_VISIBLE_ONLY | - J9_STACKWALK_SKIP_INLINES | - J9_STACKWALK_COUNT_SPECIFIED | - J9_STACKWALK_ITERATE_FRAMES - ); - walkState.frameWalkFunction = logStackIterator; - - /* - * NOTE [March 6th, 2013]: - * - * Graham Chapman said: - * - * This will make the stack walker jump back to the last - * interpreter transition point if a bad return address is found, - * rather than asserting. You'll miss a bunch of frames, but - * there's really nothing better to be done in that case. - */ - walkState.errorMode = J9_STACKWALK_ERROR_MODE_IGNORE; - - // actually walk the stack, adding all JITed methods to the queue - compInfo->acquireCompMonitor(crashedThread); - crashedThread->javaVM->walkStackFrames(crashedThread, &walkState); - compInfo->releaseCompMonitor(crashedThread); - - if (options->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "found %d JITed methods on Java stack", currentMethodIndex); - trfprintf(logFile, "#INFO: Found %d JITed methods on Java stack.\n", currentMethodIndex); - - // resume the compilation thread - recompilationThreadInfo->resumeCompilationThread(); - - // compile our methods - for (int i = 0; i < currentMethodIndex; i++) - { - // skip if method is somehow null - if (!(jittedMethodsOnStack[i]._method)) - continue; - - TR_CompilationErrorCode compErrCode; - compErrCode = recompileMethodForLog( - crashedThread, - jittedMethodsOnStack[i]._method, - compInfo, - frontendOfThread, - jittedMethodsOnStack[i]._optLevel, - false, - jittedMethodsOnStack[i]._oldStartPC, - logFile - ); - } // for - - if (currentMethodIndex == 0) - trfprintf(logFile, "#INFO: DUMP FAILED: no methods to recompile\n"); - - if (options->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "recompilations complete"); - - } // if recompilationThread - else - { - trfprintf(logFile, "#INFO: DUMP FAILED: no diagnostic thread\n"); - jitDumpFailedBecause(crashedThread, "no thread available to compile for dump"); - } - - } // if threadcompinfo - - // if our compinfo is not null, we are a compilation thread - else - { - if (options->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "crashed in compilation thread"); - trfprintf(logFile, "#INFO: Crashed in compilation thread %p.\n", crashedThread); - - // get current compilation - TR::Compilation *comp = threadCompInfo->getCompilation(); - - // if the compilation is in progress, dump interesting things from it and then recompile - if (comp) - { - if (options->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo: found comp object"); - - // dump IL of current compilation - dumpCurrentIL(comp, crashedThread, jitConfig, logFile); - - // if there was an available compilation thread, recompile the current method - if (recompilationThread) - { - // only proceed to recompile if the method is a regular Java method - if (currentMethodBeingCompiled && - currentMethodBeingCompiled->getMethodDetails().isOrdinaryMethod()) - { - // resume the healthy compilation thread - recompilationThreadInfo->resumeCompilationThread(); // TODO: Postpone this so that the thread does not get to sleep again - if (options->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo: have resumed DiagCompThread"); - - // get old start PC if method was available - void *oldStartPC = 0; - if (currentMethodBeingCompiled) - oldStartPC = currentMethodBeingCompiled->_oldStartPC; - - // request the compilation - TR_CompilationErrorCode compErrCode; - compErrCode = recompileMethodForLog( - crashedThread, - (J9Method *)(comp->getCurrentMethod()->getPersistentIdentifier()), - compInfo, - frontendOfThread, - (TR_Hotness)comp->getOptLevel(), - comp->isProfilingCompilation(), - oldStartPC, - logFile - ); - - if (options->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "recompilation complete"); - } - else - { - trfprintf(logFile, "#INFO: DUMP FAILED: not recompiling DLT method\n"); - jitDumpFailedBecause(crashedThread, "method was not a OrdinaryMethod"); - } - - } // if recompilationThread - else - { - trfprintf(logFile, "#INFO: DUMP FAILED: no diagnostic thread\n"); - jitDumpFailedBecause(crashedThread, "no thread available to compile for dump"); - } - - } // if comp - else - { - trfprintf(logFile, "#INFO: DUMP FAILED: no compilation in progress to redo\n"); - jitDumpFailedBecause(crashedThread, "found no in-progress compilation to redo"); - } - - } // if threadcompinfo - - trfprintf(logFile, "\n"); - - // flush and close log file - trfflush(logFile); - trfclose(logFile); - - // re-enable all non-essential compilations - compInfo->getPersistentInfo()->setDisableFurtherCompilation(false); - - if (options && options->getVerboseOption(TR_VerboseDump)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "JIT dump complete"); - - - return 0; - } // dumpJitInfo - -#endif - static void accumulateAndPrintDebugCounters(J9JITConfig *jitConfig) { TR_Debug *debug = TR::Options::getDebug(); diff --git a/runtime/compiler/control/JitDump.cpp b/runtime/compiler/control/JitDump.cpp new file mode 100644 index 00000000000..03ca8cd804f --- /dev/null +++ b/runtime/compiler/control/JitDump.cpp @@ -0,0 +1,737 @@ +/******************************************************************************* + * Copyright (c) 2020, 2020 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ + +#include +#include +#include +#include "control/JitDump.hpp" + +#include "codegen/CodeGenerator.hpp" +#include "compile/CompilationTypes.hpp" +#include "compile/Method.hpp" +#include "compile/ResolvedMethod.hpp" +#include "control/OptimizationPlan.hpp" +#include "control/OptionsUtil.hpp" +#include "control/Recompilation.hpp" +#include "control/RecompilationInfo.hpp" +#include "control/CompilationController.hpp" +#include "env/ClassLoaderTable.hpp" +#include "env/CompilerEnv.hpp" +#include "env/IO.hpp" +#include "env/J2IThunk.hpp" +#include "env/PersistentCHTable.hpp" +#include "env/PersistentInfo.hpp" +#include "env/jittypes.h" +#include "env/ClassTableCriticalSection.hpp" +#include "env/VMAccessCriticalSection.hpp" +#include "env/VMJ9.h" +#include "il/DataTypes.hpp" +#include "ilgen/IlGeneratorMethodDetails_inlines.hpp" +#include "infra/Monitor.hpp" +#include "infra/MonitorTable.hpp" +#include "infra/CriticalSection.hpp" +#include "optimizer/DebuggingCounters.hpp" +#include "optimizer/JProfilingBlock.hpp" +#include "runtime/CodeCacheManager.hpp" +#include "runtime/HookHelpers.hpp" +#include "runtime/MethodMetaData.h" +#include "runtime/RelocationRuntime.hpp" +#include "runtime/asmprotos.h" +#include "runtime/codertinit.hpp" +#include "control/MethodToBeCompiled.hpp" +#include "control/CompilationRuntime.hpp" +#include "control/CompilationThread.hpp" +#include "env/VMJ9.h" +#include "env/j9method.h" +#include "env/ut_j9jit.h" +#include "ilgen/J9ByteCodeIlGenerator.hpp" +#include "ilgen/J9ByteCodeIterator.hpp" +#include "runtime/IProfiler.hpp" +#include "runtime/HWProfiler.hpp" +#include "env/SystemSegmentProvider.hpp" +#if defined(J9VM_OPT_JITSERVER) +#include "control/JITServerHelpers.hpp" +#include "runtime/JITServerIProfiler.hpp" +#include "runtime/JITServerStatisticsThread.hpp" +#include "runtime/Listener.hpp" +#endif + +UDATA +blankDumpSignalHandler(struct J9PortLibrary *portLibrary, U_32 gpType, void *gpInfo, void *arg) + { + J9VMThread *vmThread = (J9VMThread *) arg; + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "vmThread=%p Recursive crash occurred. Aborting JIT dump.", vmThread); + + // Returning J9PORT_SIG_EXCEPTION_RETURN will make us come back to the same crashing instruction over and over + // + return J9PORT_SIG_EXCEPTION_RETURN; // FIXME: is this the right return type? - This appears to be the right return type + } + +typedef struct DumpCurrentILParamenters + { + DumpCurrentILParamenters( + TR::Compilation *comp, + J9VMThread *vmThread, + J9JITConfig *jitConfig, + TR::FILE *logFile + ) : + _comp(comp), + _vmThread(vmThread), + _jitConfig(jitConfig), + _logFile(logFile) + {} + + TR::Compilation *_comp; + J9VMThread *_vmThread; + J9JITConfig *_jitConfig; + TR::FILE *_logFile; + } DumpCurrentILParamenters; + +static UDATA +blankDumpCurrentILSignalHandler(struct J9PortLibrary *portLibrary, U_32 gpType, void *gpInfo, void *arg) + { + J9VMThread *vmThread = (J9VMThread *) arg; + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "vmThread=%p Crashed while printing out current IL.", vmThread); + return J9PORT_SIG_EXCEPTION_RETURN; + } + +static void jitDumpFailedBecause(J9VMThread *currentThread, const char* message) + { + if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "JIT dump failed because %s", message); + Trc_JIT_DumpFail(currentThread, message); + return; + } + +static void stackWalkEndingBecause(const char* message) + { + if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "stack walk ending because %s", message); + return; + } + +static UDATA dumpCurrentILProtected(J9PortLibrary *portLib, void * opaqueParameters) + { + DumpCurrentILParamenters *p = static_cast(opaqueParameters); + TR::Compilation *comp = p->_comp; + J9VMThread *vmThread = p->_vmThread; + J9JITConfig *jitConfig = p->_jitConfig; + TR::FILE *logFile = p->_logFile; + + comp->findOrCreateDebug(); + + TR::Options *options = comp->getOptions(); + TR_Debug *dbg = comp->getDebug(); + TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, vmThread); + + if (logFile != NULL) + { + comp->setOutFile(logFile); + options->setOption(TR_TraceAll); + options->setOption(TR_TraceKnownObjectGraph); + dbg->setFile(logFile); + + trfprintf(logFile,"\n"); + + // Print Bytecodes + TR::IlGeneratorMethodDetails & details = comp->ilGenRequest().details(); + TR::ResolvedMethodSymbol *resolvedMethod = comp->getMethodSymbol(); + TR::SymbolReferenceTable *symRefTab = comp->getSymRefTab(); + TR_J9ByteCodeIlGenerator bci(details, resolvedMethod, fe, comp, symRefTab); + bci.printByteCodes(); + + dbg->printMethodHotness(); + comp->dumpMethodTrees("Trees"); + dbg->print(logFile, comp->getSymRefTab()); + + int bitMask = J9VMSTATE_JIT_CODEGEN | 0x0000FF00; // 0xFF?? is Codegen Phase + if ( ((vmThread->omrVMThread->vmState) & bitMask) == bitMask ) // if we are in the Codegen Phase + { + dbg->dumpMethodInstrs(logFile, "Post Binary Instructions", false, true); + + dbg->print(logFile,comp->cg()->getSnippetList(), true); // print Warm Snippets + dbg->print(logFile,comp->cg()->getSnippetList(), false); + + dbg->dumpMixedModeDisassembly(); + } + + // leaving to the very end in case there is a crash before this point. + comp->verifyTrees(comp->getMethodSymbol()); + comp->verifyBlocks(comp->getMethodSymbol()); + + trfprintf(logFile, "\n"); + } + + return 0; + } + +static void dumpCurrentIL(TR::Compilation *comp, J9VMThread *vmThread, J9JITConfig *jitConfig, TR::FILE *logFile ) + { + /* Acquire VM Access */ + bool alreadyHaveVMAccess = ((vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS) != 0); + bool haveAcquiredVMAccess = false; + if (!alreadyHaveVMAccess) + if (0 == vmThread->javaVM->internalVMFunctions->internalTryAcquireVMAccessWithMask(vmThread, J9_PUBLIC_FLAGS_HALT_THREAD_ANY_NO_JAVA_SUSPEND)) + haveAcquiredVMAccess = true; + + PORT_ACCESS_FROM_JITCONFIG(jitConfig); + + DumpCurrentILParamenters p( + comp, + vmThread, + jitConfig, + logFile + ); + + UDATA result = 0; + +#if defined(J9VM_PORT_SIGNAL_SUPPORT) + U_32 flags = J9PORT_SIG_FLAG_MAY_RETURN | + J9PORT_SIG_FLAG_SIGSEGV | J9PORT_SIG_FLAG_SIGFPE | + J9PORT_SIG_FLAG_SIGILL | J9PORT_SIG_FLAG_SIGBUS; + + static char *noSignalWrapper = feGetEnv("TR_NoSignalWrapper"); + + if (!noSignalWrapper && j9sig_can_protect(flags)) + { + UDATA protectedResult; + + protectedResult = j9sig_protect((j9sig_protected_fn)dumpCurrentILProtected, static_cast(&p), + (j9sig_handler_fn)blankDumpCurrentILSignalHandler, vmThread, + flags, &result); + } + else +#endif + result = dumpCurrentILProtected(privatePortLibrary, &p); + + + /* Release VM Access */ + if (!alreadyHaveVMAccess) + if (haveAcquiredVMAccess) + vmThread->javaVM->internalVMFunctions->internalReleaseVMAccess(vmThread); + } + +#define STACK_WALK_DEPTH 16 + +// struct to remember a method for JIT dump +typedef struct TR_MethodToBeCompiledForDump { + J9Method *_method; + void *_oldStartPC; + TR_Hotness _optLevel; +} TR_MethodToBeCompiledForDump; + +// Stack frame iterator. Iterates until STACK_WALK_DEPTH frames or the top are reached. +static UDATA logStackIterator(J9VMThread *currentThread, J9StackWalkState *walkState) + { + Trc_JIT_DumpWalkingFrame(currentThread); + + // stop iterating if the walk state is null + if (!walkState) + { + stackWalkEndingBecause("got a null walkState"); + return J9_STACKWALK_STOP_ITERATING; + } + + // get user data from walk state + TR_MethodToBeCompiledForDump* jittedMethodsOnStack = (TR_MethodToBeCompiledForDump *) walkState->userData1; + int *currentMethodIndex = (int *) walkState->userData2; + + // also stop iterating if passed user data is null + if (currentMethodIndex == 0 || jittedMethodsOnStack == 0) + { + stackWalkEndingBecause("one or both user data are null"); + return J9_STACKWALK_STOP_ITERATING; + } + + // also stop iterating if enough frames have been reached + if ((*currentMethodIndex) >= STACK_WALK_DEPTH) + { + stackWalkEndingBecause("reached limit on number of methods to recompile"); + return J9_STACKWALK_STOP_ITERATING; + } + + // if the frame has jit metadata, then it belongs to a JITed method + if (walkState->jitInfo) + { + // NOTE: method is the one (J9Method, a.k.a. TR_OpaqueMethodBlock) that gets + // passed to IlGeneratorMethodDetails + TR_ASSERT(walkState->method, "Found method metadata on the stack, but method is null."); + + // get method's body info (can be null) + TR_PersistentJittedBodyInfo* bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC((void*) walkState->jitInfo->startPC); + + // get global configuration options + TR::Options *options = TR::Options::getCmdLineOptions(); + + // get global opt level + // NOTE: getOptLevel returns -1 if it is not set + TR_Hotness globalOptLevel = (TR_Hotness) (-1); + if (options) + globalOptLevel = (TR_Hotness) options->getFixedOptLevel(); + + // add the method to our list ONLY if level can be determined; it can be determined + // either from body info (if it exists), or from fixed level (if it was set) + if (bodyInfo || (globalOptLevel != (-1))) + { + // set the method + jittedMethodsOnStack[*currentMethodIndex]._method = walkState->method; + + // set the method's oldStartPC: + // if bodyInfo exists, then we can do a recompilation (use startPCAfterPreviousCompile) + // if not, then we can't, and we do a first-time compilation (use 0) + if (bodyInfo) + jittedMethodsOnStack[*currentMethodIndex]._oldStartPC = bodyInfo->getStartPCAfterPreviousCompile(); + else + jittedMethodsOnStack[*currentMethodIndex]._oldStartPC = 0; + + // set the optLevel + if (bodyInfo) + jittedMethodsOnStack[*currentMethodIndex]._optLevel = bodyInfo->getHotness(); + else + // NOTE: global optLevel is not -1, since we checked for that above + jittedMethodsOnStack[*currentMethodIndex]._optLevel = globalOptLevel; + + // advance to the next method in the list + *currentMethodIndex = (*(currentMethodIndex) + 1); + } + } + + return J9_STACKWALK_KEEP_ITERATING; + } + +/// Recompiles a method for the JIT dump +static TR_CompilationErrorCode recompileMethodForLog( + J9VMThread *vmThread, + J9Method *ramMethod, + TR::CompilationInfo *compInfo, + TR_J9VMBase *frontendOfThread, + TR_Hotness optimizationLevel, + bool profilingCompile, + void *oldStartPC, + TR::FILE *logFile + ) + { + if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "recompiling a method for log: %p", ramMethod); + + Trc_JIT_DumpCompilingMethod(vmThread, ramMethod, optimizationLevel, oldStartPC); + + // the request to use Log should be passed to the compilation, via optimizationPlan + // then the option object created should use this to open the log; thus must create a new optimization plan + // the right optlevel would be set during the Options setting + TR_OptimizationPlan *plan = TR_OptimizationPlan::alloc(optimizationLevel); + if (!plan) + return compilationFailure; + + if (profilingCompile) + plan->setInsertInstrumentation(true); + + // pass the log file to the compilation + plan->setLogCompilation(logFile); + + bool successfullyQueued = false; + + trfprintf(logFile, "\n"); + + // actually request the compilation + if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo: compileMethod() about to issued synchronously"); + TR_CompilationErrorCode compErrCode; + + // Set the VM state of the crashed thread so the diagnostic thread can use consume it + compInfo->setVMStateOfCrashedThread(vmThread->omrVMThread->vmState); + + // create a compilation request + // NOTE: operator new() is overridden, and takes a storage object as a parameter + // TODO: this is indiscriminately compiling as J9::DumpMethodRequest, which is wrong; + // should be fixed by checking if the method is indeed DLT, and compiling DLT if so + { + J9::DumpMethodDetails details( ramMethod); + compInfo->compileMethod(vmThread, details, oldStartPC, TR_no, &compErrCode, &successfullyQueued, plan); + } + + if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo: crashing thread returned from compileMethod() with errorCode=%d", compErrCode); + + trfprintf(logFile, "\n"); + + // if the request failed, get rid of the optimization plan we made + if (!successfullyQueued) + TR_OptimizationPlan::freeOptimizationPlan(plan); + + return compErrCode; + } + +/// Dumps JIT-specific crash info +IDATA dumpJitInfo(J9VMThread *crashedThread, char *logFileLabel, J9RASdumpContext *context) + { + Trc_JIT_DumpStart(crashedThread); + +#if defined(J9VM_OPT_JITSERVER) + if (context && context->javaVM && context->javaVM->jitConfig) + { + J9JITConfig *jitConfig = context->javaVM->jitConfig; + TR::CompilationInfo *compInfo = TR::CompilationInfo::get(context->javaVM->jitConfig); + if (compInfo) + { + static char * isPrintJITServerMsgStats = feGetEnv("TR_PrintJITServerMsgStats"); + if (isPrintJITServerMsgStats && compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT) + JITServerHelpers::printJITServerMsgStats(jitConfig); + if (feGetEnv("TR_PrintJITServerCHTableStats")) + JITServerHelpers::printJITServerCHTableStats(jitConfig, compInfo); + if (feGetEnv("TR_PrintJITServerIPMsgStats")) + { + if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER) + { + TR_J9VMBase * vmj9 = (TR_J9VMBase *)(TR_J9VMBase::get(context->javaVM->jitConfig, 0)); + JITServerIProfiler *iProfiler = (JITServerIProfiler *)vmj9->getIProfiler(); + iProfiler->printStats(); + } + } + } + } +#endif + + if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "JIT dump initiated. Crashed vmThread=%p", crashedThread); + + // if either one of the args is null, we can't really do anything + if (crashedThread == 0 || logFileLabel == 0) + { + jitDumpFailedBecause(crashedThread, "one or both arguments are null"); + return 0; + } + + // if VM is gone, can't do anything either + if (crashedThread->javaVM == 0) + { + jitDumpFailedBecause(crashedThread, "VM pointer is null"); + return 0; + } + + // get a hold of jitConfig in order to later get compinfo and frontend + J9JITConfig * jitConfig = crashedThread->javaVM->jitConfig; + + // if jitConfig is gone, then we can't do anything either + if (jitConfig == 0) + { + jitDumpFailedBecause(crashedThread, "jitConfig is null"); + return 0; + } + // get global compinfo + TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig); + if (!compInfo) + { + jitDumpFailedBecause(crashedThread, "compInfo is null"); + return 0; + } + + // Must be able to allocate a frontend for this thread + TR_J9VMBase *frontendOfThread = TR_J9VMBase::get(jitConfig, crashedThread); + if (!frontendOfThread) + { + jitDumpFailedBecause(crashedThread, "thread's frontend is missing"); + return 0; + } + + // get global configuration options + TR::Options *options = TR::Options::getCmdLineOptions(); + if (!options) + { + jitDumpFailedBecause(crashedThread, "No cmdLineOptions available"); + return 0; + } + + + // open log file, using the postfixed timestamp if specified + TR::FILE *logFile; + char tmp[1025]; + logFileLabel = frontendOfThread->getFormattedName(tmp, 1025, logFileLabel, NULL, false); + logFile = trfopen(logFileLabel, "ab", false); + + trfprintf(logFile, + "\n" + "\n" + ); + + + // if some thread holds exclusive VM access we cannot do much + if (J9_XACCESS_NONE != jitConfig->javaVM->exclusiveAccessState) + { + jitDumpFailedBecause(crashedThread, "some thread is holding exclusive VM access"); + trfprintf(logFile, "Some thread is holding exclusive VM access. No log created.\n"); + trfclose(logFile); + return 0; + } + + + // to avoid deadlock, release compilation monitor until we are no longer holding it + while (compInfo->getCompilationMonitor()->owned_by_self()) + compInfo->releaseCompMonitor(crashedThread); + + // Release other monitors as well. In particular CHTable and classUnloadMonitor must not be held + while (TR::MonitorTable::get()->getClassTableMutex()->owned_by_self()) + frontendOfThread->releaseClassTableMutex(false); + + //FIXME: how do I detect that someone is holding the classUnloadMonitor + + // get crashed thread's own compinfo + TR::CompilationInfoPerThread *threadCompInfo = compInfo->getCompInfoForThread(crashedThread); + + // Crashes on the diagnostic thread should not be processed + if (threadCompInfo && threadCompInfo->isDiagnosticThread()) + { + jitDumpFailedBecause(crashedThread, "detected recursive crash"); + trfprintf(logFile, "Detected recursive crash. No log created.\n"); + trfclose(logFile); + return 0; + } + + // get the method currently being compiled + TR_MethodToBeCompiled *currentMethodBeingCompiled = 0; + if (threadCompInfo) + currentMethodBeingCompiled = threadCompInfo->getMethodBeingCompiled(); + + /* + * at this stage, we know that we are good to orchestrate a dump + */ + + if (options->getOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dump agent obtained necessary information to perform dump"); + + // if we are currently compiling a method, wake everyone waiting for it to compile + if (currentMethodBeingCompiled && currentMethodBeingCompiled->getMonitor()) + { + currentMethodBeingCompiled->getMonitor()->enter(); + currentMethodBeingCompiled->getMonitor()->notifyAll(); + currentMethodBeingCompiled->getMonitor()->exit(); + if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo notified all waiting threads"); + } + + // disable all non-essential compilations + compInfo->getPersistentInfo()->setDisableFurtherCompilation(true); + if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo disabled further compilation"); + + // get the dump thread + TR::CompilationInfoPerThread *recompilationThreadInfo = compInfo->getCompilationInfoForDumpThread(); + J9VMThread *recompilationThread = NULL; + if (recompilationThreadInfo) + recompilationThread = recompilationThreadInfo->getCompilationThread(); + + // purge the compilation queue if a thread was found + if (recompilationThread) + { + if (options->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo: diagnostic compilation thread available. Will purge compilation queue"); + compInfo->acquireCompMonitor(crashedThread); + compInfo->purgeMethodQueue(compilationFailure); // compilationFailure is a TR_CompilationErrorCode + compInfo->releaseCompMonitor(crashedThread); + } + + + + // if our compinfo is null, we are an application thread + if (threadCompInfo == 0) + { + if (options->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "crashed in application thread"); + trfprintf(logFile, "#INFO: Crashed in application thread %p.\n", crashedThread); + + // only bother doing anything if we have a healthy compilation thread available + if (recompilationThread) + { + // make space for methods to be recompiled + // FIXME: this is on the stack... is the stack big enough? + int currentMethodIndex = 0; + TR_MethodToBeCompiledForDump jittedMethodsOnStack[STACK_WALK_DEPTH] = { 0 }; + + // set up the stack walk object + J9StackWalkState walkState; + + walkState.userData1 = (void *)jittedMethodsOnStack; + walkState.userData2 = (void *)¤tMethodIndex; + walkState.walkThread = crashedThread; + walkState.skipCount = 0; + walkState.maxFrames = STACK_WALK_DEPTH; + walkState.flags = ( + // J9_STACKWALK_LINEAR | + // J9_STACKWALK_START_AT_JIT_FRAME | + // J9_STACKWALK_INCLUDE_NATIVES | + // J9_STACKWALK_HIDE_EXCEPTION_FRAMES | + // J9_STACKWALK_ITERATE_HIDDEN_JIT_FRAMES | + J9_STACKWALK_VISIBLE_ONLY | + J9_STACKWALK_SKIP_INLINES | + J9_STACKWALK_COUNT_SPECIFIED | + J9_STACKWALK_ITERATE_FRAMES + ); + walkState.frameWalkFunction = logStackIterator; + + /* + * NOTE [March 6th, 2013]: + * + * Graham Chapman said: + * + * This will make the stack walker jump back to the last + * interpreter transition point if a bad return address is found, + * rather than asserting. You'll miss a bunch of frames, but + * there's really nothing better to be done in that case. + */ + walkState.errorMode = J9_STACKWALK_ERROR_MODE_IGNORE; + + // actually walk the stack, adding all JITed methods to the queue + compInfo->acquireCompMonitor(crashedThread); + crashedThread->javaVM->walkStackFrames(crashedThread, &walkState); + compInfo->releaseCompMonitor(crashedThread); + + if (options->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "found %d JITed methods on Java stack", currentMethodIndex); + trfprintf(logFile, "#INFO: Found %d JITed methods on Java stack.\n", currentMethodIndex); + + // resume the compilation thread + recompilationThreadInfo->resumeCompilationThread(); + + // compile our methods + for (int i = 0; i < currentMethodIndex; i++) + { + // skip if method is somehow null + if (!(jittedMethodsOnStack[i]._method)) + continue; + + TR_CompilationErrorCode compErrCode; + compErrCode = recompileMethodForLog( + crashedThread, + jittedMethodsOnStack[i]._method, + compInfo, + frontendOfThread, + jittedMethodsOnStack[i]._optLevel, + false, + jittedMethodsOnStack[i]._oldStartPC, + logFile + ); + } // for + + if (currentMethodIndex == 0) + trfprintf(logFile, "#INFO: DUMP FAILED: no methods to recompile\n"); + + if (options->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "recompilations complete"); + + } // if recompilationThread + else + { + trfprintf(logFile, "#INFO: DUMP FAILED: no diagnostic thread\n"); + jitDumpFailedBecause(crashedThread, "no thread available to compile for dump"); + } + + } // if threadcompinfo + + // if our compinfo is not null, we are a compilation thread + else + { + if (options->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "crashed in compilation thread"); + trfprintf(logFile, "#INFO: Crashed in compilation thread %p.\n", crashedThread); + + // get current compilation + TR::Compilation *comp = threadCompInfo->getCompilation(); + + // if the compilation is in progress, dump interesting things from it and then recompile + if (comp) + { + if (options->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo: found comp object"); + + // dump IL of current compilation + dumpCurrentIL(comp, crashedThread, jitConfig, logFile); + + // if there was an available compilation thread, recompile the current method + if (recompilationThread) + { + // only proceed to recompile if the method is a regular Java method + if (currentMethodBeingCompiled && + currentMethodBeingCompiled->getMethodDetails().isOrdinaryMethod()) + { + // resume the healthy compilation thread + recompilationThreadInfo->resumeCompilationThread(); // TODO: Postpone this so that the thread does not get to sleep again + if (options->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "dumpJitInfo: have resumed DiagCompThread"); + + // get old start PC if method was available + void *oldStartPC = 0; + if (currentMethodBeingCompiled) + oldStartPC = currentMethodBeingCompiled->_oldStartPC; + + // request the compilation + TR_CompilationErrorCode compErrCode; + compErrCode = recompileMethodForLog( + crashedThread, + (J9Method *)(comp->getCurrentMethod()->getPersistentIdentifier()), + compInfo, + frontendOfThread, + (TR_Hotness)comp->getOptLevel(), + comp->isProfilingCompilation(), + oldStartPC, + logFile + ); + + if (options->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "recompilation complete"); + } + else + { + trfprintf(logFile, "#INFO: DUMP FAILED: not recompiling DLT method\n"); + jitDumpFailedBecause(crashedThread, "method was not a OrdinaryMethod"); + } + + } // if recompilationThread + else + { + trfprintf(logFile, "#INFO: DUMP FAILED: no diagnostic thread\n"); + jitDumpFailedBecause(crashedThread, "no thread available to compile for dump"); + } + + } // if comp + else + { + trfprintf(logFile, "#INFO: DUMP FAILED: no compilation in progress to redo\n"); + jitDumpFailedBecause(crashedThread, "found no in-progress compilation to redo"); + } + + } // if threadcompinfo + + trfprintf(logFile, "\n"); + + // flush and close log file + trfflush(logFile); + trfclose(logFile); + + // re-enable all non-essential compilations + compInfo->getPersistentInfo()->setDisableFurtherCompilation(false); + + if (options && options->getVerboseOption(TR_VerboseDump)) + TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "JIT dump complete"); + + + return 0; + } // dumpJitInfo diff --git a/runtime/compiler/control/JitDump.hpp b/runtime/compiler/control/JitDump.hpp new file mode 100644 index 00000000000..c79bd9dd31e --- /dev/null +++ b/runtime/compiler/control/JitDump.hpp @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2020, 2020 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +#include "bcnames.h" +#include "jithash.h" +#include "jitprotos.h" +#include "j9.h" +#include "j9cfg.h" +#include "j9modron.h" +#include "j9nonbuilder.h" +#include "j9consts.h" +#include "mmhook.h" +#include "mmomrhook.h" +#include "vmaccess.h" + +UDATA +blankDumpSignalHandler(struct J9PortLibrary *portLibrary, U_32 gpType, void *gpInfo, void *arg); + +intptr_t +dumpJitInfo(J9VMThread * currentThread, char *label, J9RASdumpContext *context); diff --git a/runtime/compiler/control/rossa.cpp b/runtime/compiler/control/rossa.cpp index 3490431f1fa..6bdf92660cb 100644 --- a/runtime/compiler/control/rossa.cpp +++ b/runtime/compiler/control/rossa.cpp @@ -51,6 +51,7 @@ #include "codegen/PrivateLinkage.hpp" #include "control/CompilationRuntime.hpp" #include "control/CompilationThread.hpp" +#include "control/JitDump.hpp" #include "control/Recompilation.hpp" #include "control/RecompilationInfo.hpp" #include "runtime/ArtifactManager.hpp" @@ -125,10 +126,6 @@ extern "C" { struct J9RASdumpContext; } -#ifdef J9VM_RAS_DUMP_AGENTS -extern "C" intptr_t dumpJitInfo(J9VMThread * currentThread, char *label, J9RASdumpContext *context); -#endif - #if defined(TR_TARGET_X86) && defined(TR_HOST_32BIT) extern TR_X86CPUIDBuffer *queryX86TargetCPUID(void * javaVM); #endif From 103a3ad15ff0af3791d8b6381f39fbae0daa6df8 Mon Sep 17 00:00:00 2001 From: Babneet Singh Date: Mon, 6 Apr 2020 12:45:43 -0400 Subject: [PATCH 35/61] Remove ";" from the interpreter goto statements ";" is removed since it is not required. Signed-off-by: Babneet Singh --- runtime/vm/BytecodeInterpreter.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/vm/BytecodeInterpreter.hpp b/runtime/vm/BytecodeInterpreter.hpp index 802007966ad..d8fb7e8991a 100644 --- a/runtime/vm/BytecodeInterpreter.hpp +++ b/runtime/vm/BytecodeInterpreter.hpp @@ -821,7 +821,7 @@ class INTERPRETER_CLASS returnPoint = jitConfig->jitExitInterpreter0; break; case ';': -obj:; +obj: /* On 32-bit, object uses the "1" target (already loaded, so just break). * On 64-bit, object uses the "J" target (fall through) */ @@ -2274,7 +2274,7 @@ obj:; *(U_32 *)_sp = (U_32)_currentThread->returnValue; } rc = EXECUTE_BYTECODE; -done:; +done: return rc; } From 35b018cc33b2f89b9e804fe9ed955888f81b04ec Mon Sep 17 00:00:00 2001 From: Graham Chapman Date: Mon, 6 Apr 2020 15:28:11 -0400 Subject: [PATCH 36/61] Revert "Remove final from fields being set in native methods" --- .../share/classes/java/lang/invoke/MethodHandle.java | 6 +++--- .../java.base/share/classes/java/lang/invoke/VarHandle.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index ce37e73a463..32027d2d4f6 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar17]*/ /******************************************************************************* - * Copyright (c) 2009, 2020 IBM Corp. and others + * Copyright (c) 2009, 2019 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -198,9 +198,9 @@ final void requestCustomThunk() { private native void requestCustomThunkFromJit(ThunkTuple tt); @VMCONSTANTPOOL_FIELD - final MethodType type; /* Type of the MethodHandle */ + final MethodType type; /* Type of the MethodHandle */ @VMCONSTANTPOOL_FIELD - byte kind; /* The kind (STATIC/SPECIAL/etc) of this MethodHandle */ + final byte kind; /* The kind (STATIC/SPECIAL/etc) of this MethodHandle */ @VMCONSTANTPOOL_FIELD int invocationCount; /* used to determine how many times the MH has been invoked*/ diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java index b0605c67707..2189f1694bc 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -340,7 +340,7 @@ MethodType accessModeType(Class receiver, Class type, Class... args) { private final MethodHandle[] handleTable; final Class fieldType; final Class[] coordinateTypes; - int modifiers; + final int modifiers; /*[IF Java12]*/ private int hashCode = 0; /*[ENDIF] Java12 */ From 3131f2fff09b30c7d615348c579726d25cbd44d4 Mon Sep 17 00:00:00 2001 From: Devin Nakamura Date: Mon, 6 Apr 2020 18:49:59 -0400 Subject: [PATCH 37/61] CMake: move -qnortti to platform flags on aix The difference between the platform flags and normal C(XX)_FLAGS is that the platform flags get applied to the jit (as the jit discards the CMAKE_C(XX)_FLAGS Signed-off-by: Devin Nakamura --- runtime/cmake/platform/toolcfg/xlc.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/cmake/platform/toolcfg/xlc.cmake b/runtime/cmake/platform/toolcfg/xlc.cmake index d5b7e87414d..ed589ceff06 100644 --- a/runtime/cmake/platform/toolcfg/xlc.cmake +++ b/runtime/cmake/platform/toolcfg/xlc.cmake @@ -22,10 +22,10 @@ list(APPEND OMR_PLATFORM_COMPILE_OPTIONS -O3) -list(APPEND OMR_PLATFORM_CXX_COMPILE_OPTIONS -qsuppress=1540-1087:1540-1088:1540-1090) +list(APPEND OMR_PLATFORM_CXX_COMPILE_OPTIONS -qnortti -qsuppress=1540-1087:1540-1088:1540-1090) # OMR_PLATFORM_CXX_COMPILE_OPTIONS gets applied to the jit (which needs exceptions), # so we put these in the CMAKE_CXX_FLAGS instead -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -qnortti -qnoeh") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -qnoeh") set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -qpic=large") From 7f351416e0c147605081cd731e6cfb73948fc081 Mon Sep 17 00:00:00 2001 From: Marius Pirvu Date: Mon, 6 Apr 2020 23:12:43 -0400 Subject: [PATCH 38/61] Fix ClassEnv::containesZeroOrOneConcreteClass implementation The implementation of ClassEnv::containesZeroOrOneConcreteClass is broken because it allows JITServer specific code to be executed by a non-jitserver process. We need to protect such code with a runtime check: `if (comp->isOutOfProcessCompilation())` Fixes: #9144 Signed-off-by: Marius Pirvu --- runtime/compiler/env/J9ClassEnv.cpp | 70 +++++++++++++++-------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/runtime/compiler/env/J9ClassEnv.cpp b/runtime/compiler/env/J9ClassEnv.cpp index 2f41c4f970e..6ae82c29ef5 100644 --- a/runtime/compiler/env/J9ClassEnv.cpp +++ b/runtime/compiler/env/J9ClassEnv.cpp @@ -659,52 +659,56 @@ J9::ClassEnv::containesZeroOrOneConcreteClass(TR::Compilation *comp, List j(subClasses); - TR_ScratchList subClassesNotCached(comp->trMemory()); - - // Process classes cached at the server first - ClientSessionData * clientData = TR::compInfoPT->getClientData(); - for (TR_PersistentClassInfo *ptClassInfo = j.getFirst(); ptClassInfo; ptClassInfo = j.getNext()) + if (comp->isOutOfProcessCompilation()) { - TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); - J9Class *j9clazz = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz); - auto romClass = JITServerHelpers::getRemoteROMClassIfCached(clientData, j9clazz); - if (romClass == NULL) + ListIterator j(subClasses); + TR_ScratchList subClassesNotCached(comp->trMemory()); + + // Process classes cached at the server first + ClientSessionData * clientData = TR::compInfoPT->getClientData(); + for (TR_PersistentClassInfo *ptClassInfo = j.getFirst(); ptClassInfo; ptClassInfo = j.getNext()) { - subClassesNotCached.add(ptClassInfo); + TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); + J9Class *j9clazz = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz); + auto romClass = JITServerHelpers::getRemoteROMClassIfCached(clientData, j9clazz); + if (romClass == NULL) + { + subClassesNotCached.add(ptClassInfo); + } + else + { + if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) + { + if (++count > 1) + return false; + } + } } - else + // Traverse through classes that are not cached on server + ListIterator i(&subClassesNotCached); + for (TR_PersistentClassInfo *ptClassInfo = i.getFirst(); ptClassInfo; ptClassInfo = i.getNext()) { + TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) { - count++; - } - if (count > 1) - { - return false; + if (++count > 1) + return false; } } } - - // Traverse though classes that are not cached on server - // With the following for loop outside if defined block - ListIterator i(&subClassesNotCached); -#else - ListIterator i(subClasses); + else // non-jitserver #endif /* defined(J9VM_OPT_JITSERVER) */ - - for (TR_PersistentClassInfo *ptClassInfo = i.getFirst(); ptClassInfo; ptClassInfo = i.getNext()) { - TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); - if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) - { - count++; - } - if (count > 1) + ListIterator i(subClasses); + for (TR_PersistentClassInfo *ptClassInfo = i.getFirst(); ptClassInfo; ptClassInfo = i.getNext()) { - return false; + TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); + if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) + { + if (++count > 1) + return false; + } } } - return true; } From beda9dd440db1bab93daa060f8160c583f7d88cf Mon Sep 17 00:00:00 2001 From: Devin Nakamura Date: Mon, 6 Apr 2020 18:28:23 -0400 Subject: [PATCH 39/61] CMake: Add missing config optiopns to aix cache Also performed some cleanup in the file Signed-off-by: Devin Nakamura --- runtime/cmake/caches/aix_ppc-64.cmake | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/runtime/cmake/caches/aix_ppc-64.cmake b/runtime/cmake/caches/aix_ppc-64.cmake index 03d8ad0d31b..051a1041cec 100644 --- a/runtime/cmake/caches/aix_ppc-64.cmake +++ b/runtime/cmake/caches/aix_ppc-64.cmake @@ -20,25 +20,33 @@ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception ################################################################################ - -#TODO Platform hacks +#TODO: Env vars should be auto detected by platform set(J9VM_ARCH_POWER ON CACHE BOOL "") set(J9VM_ENV_DATA64 ON CACHE BOOL "") +set(J9VM_ENV_DLPAR ON CACHE BOOL "") set(J9VM_ENV_HAS_FPU ON CACHE BOOL "") set(J9VM_ENV_SHARED_LIBS_CALLEE_GLOBAL_TABLE_SETUP OFF CACHE BOOL "") set(J9VM_ENV_SHARED_LIBS_USE_GLOBAL_TABLE ON CACHE BOOL "") -set(OMR_GC_TLH_PREFETCH_FTA OFF CACHE BOOL "") -set(J9VM_JIT_RUNTIME_INSTRUMENTATION ON CACHE BOOL "") -set(J9VM_PORT_RUNTIME_INSTRUMENTATION ON CACHE BOOL "") -set(J9VM_MODULE_CODEGEN_PPC ON CACHE BOOL "") set(J9VM_GC_IDLE_HEAP_MANAGER OFF CACHE BOOL "") +set(J9VM_GC_TLH_PREFETCH_FTA OFF CACHE BOOL "") +set(J9VM_GC_SUBPOOLS_ALIAS ON CACHE BOOL "") set(J9VM_INTERP_ATOMIC_FREE_JNI ON CACHE BOOL "") set(J9VM_INTERP_ATOMIC_FREE_JNI_USES_FLUSH ON CACHE BOOL "") set(J9VM_INTERP_TWO_PASS_EXCLUSIVE ON CACHE BOOL "") +set(J9VM_JIT_RUNTIME_INSTRUMENTATION ON CACHE BOOL "") +set(J9VM_MODULE_CODEGEN_PPC ON CACHE BOOL "") set(J9VM_OPT_SWITCH_STACKS_FOR_SIGNAL_HANDLER OFF CACHE BOOL "") +set(J9VM_PORT_RUNTIME_INSTRUMENTATION ON CACHE BOOL "") set(J9VM_THR_ASYNC_NAME_UPDATE OFF CACHE BOOL "") + +set(OMR_GC_CONCURRENT_SCAVENGER ON CACHE BOOL "") +set(OMR_GC_HEAP_CARD_TABLE ON CACHE BOOL "") +set(OMR_THR_SPIN_WAKE_CONTROL OFF CACHE BOOL "") +set(OMR_THR_THREE_TIER_LOCKING OFF CACHE BOOL "") +set(OMR_THR_YIELD_ALG OFF CACHE BOOL "") + # Note: In CMake, 'set's on cache variables only apply if the cache variable # is not already set. Thus any cache varaibles set in this file, override # anything set in common.cmake From 9b3e6daed408df4b0e06f61f19ac65ac1e283e32 Mon Sep 17 00:00:00 2001 From: Devin Nakamura Date: Tue, 7 Apr 2020 00:21:25 -0400 Subject: [PATCH 40/61] CMake: Generate debug info on xlc Signed-off-by: Devin Nakamura --- runtime/cmake/platform/toolcfg/xlc.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/cmake/platform/toolcfg/xlc.cmake b/runtime/cmake/platform/toolcfg/xlc.cmake index ed589ceff06..84d7e316817 100644 --- a/runtime/cmake/platform/toolcfg/xlc.cmake +++ b/runtime/cmake/platform/toolcfg/xlc.cmake @@ -20,7 +20,7 @@ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception ################################################################################ -list(APPEND OMR_PLATFORM_COMPILE_OPTIONS -O3) +list(APPEND OMR_PLATFORM_COMPILE_OPTIONS -O3 -g) list(APPEND OMR_PLATFORM_CXX_COMPILE_OPTIONS -qnortti -qsuppress=1540-1087:1540-1088:1540-1090) From a9d0ee2890144831b7bcf22a0fe98e16e242a4f4 Mon Sep 17 00:00:00 2001 From: KONNO Kazuhiro Date: Tue, 7 Apr 2020 14:40:00 +0900 Subject: [PATCH 41/61] Enable DDR tests for AArch64 again This commit enables some of the DDR tests that were disabled for AArch64 in #8569. Signed-off-by: KONNO Kazuhiro --- test/functional/DDR_Test/playlist.xml | 4 ++-- test/functional/cmdLineTests/callsitedbgddrext/playlist.xml | 2 +- test/functional/cmdLineTests/classesdbgddrext/playlist.xml | 2 +- test/functional/cmdLineTests/modularityddrtests/playlist.xml | 2 +- test/functional/cmdLineTests/shrcdbgddrext/playlist.xml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/functional/DDR_Test/playlist.xml b/test/functional/DDR_Test/playlist.xml index 751ca92c61a..3dd6321280f 100644 --- a/test/functional/DDR_Test/playlist.xml +++ b/test/functional/DDR_Test/playlist.xml @@ -46,7 +46,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti -Dtest.list=$(Q)TestDDRExtensionGeneral$(Q) -DADDITIONALEXPORTS=$(ADDEXPORTS_JDKASM_UNNAMED) -f $(Q)$(TEST_RESROOT)$(D)tck_ddrext.xml$(Q); \ $(TEST_STATUS) - ^os.zos,^arch.aarch64 + ^os.zos extended @@ -82,7 +82,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti -Dtest.list=$(Q)TestCallsites$(Q) -DADDITIONALEXPORTS=$(ADDEXPORTS_JDKASM_UNNAMED) -f $(Q)$(TEST_RESROOT)$(D)tck_ddrext.xml$(Q); \ $(TEST_STATUS) - ^os.zos,^arch.aarch64 + ^os.zos extended diff --git a/test/functional/cmdLineTests/callsitedbgddrext/playlist.xml b/test/functional/cmdLineTests/callsitedbgddrext/playlist.xml index 2559f32df9f..65ef9b74c04 100644 --- a/test/functional/cmdLineTests/callsitedbgddrext/playlist.xml +++ b/test/functional/cmdLineTests/callsitedbgddrext/playlist.xml @@ -92,7 +92,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti -config $(Q)$(TEST_RESROOT)$(D)callsiteddrtests.xml$(Q) -plats all,$(PLATFORM),$(VARIATION) -nonZeroExitWhenError; \ ${TEST_STATUS} - ^os.zos,^arch.aarch64 + ^os.zos sanity diff --git a/test/functional/cmdLineTests/classesdbgddrext/playlist.xml b/test/functional/cmdLineTests/classesdbgddrext/playlist.xml index f032eca516a..14afc36b3af 100644 --- a/test/functional/cmdLineTests/classesdbgddrext/playlist.xml +++ b/test/functional/cmdLineTests/classesdbgddrext/playlist.xml @@ -64,7 +64,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti -xlist $(Q)$(TEST_RESROOT)$(D)dbgextddrtests_excludes.xml$(Q) -nonZeroExitWhenError; \ ${TEST_STATUS} - ^os.zos,^arch.aarch64 + ^os.zos extended diff --git a/test/functional/cmdLineTests/modularityddrtests/playlist.xml b/test/functional/cmdLineTests/modularityddrtests/playlist.xml index ee27b92be9b..f56883a2867 100644 --- a/test/functional/cmdLineTests/modularityddrtests/playlist.xml +++ b/test/functional/cmdLineTests/modularityddrtests/playlist.xml @@ -39,7 +39,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti -outputLimit 1000 -explainExcludes -nonZeroExitWhenError; \ ${TEST_STATUS} - ^os.zos,^arch.aarch64 + ^os.zos extended diff --git a/test/functional/cmdLineTests/shrcdbgddrext/playlist.xml b/test/functional/cmdLineTests/shrcdbgddrext/playlist.xml index 1fb1b81bd2b..7f39b3ec44d 100644 --- a/test/functional/cmdLineTests/shrcdbgddrext/playlist.xml +++ b/test/functional/cmdLineTests/shrcdbgddrext/playlist.xml @@ -40,7 +40,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti -config $(Q)$(TEST_RESROOT)$(D)shrcdbgextddrtests.xml$(Q) -plats all,$(PLATFORM),$(VARIATION) -nonZeroExitWhenError; \ ${TEST_STATUS} - ^os.zos,^arch.aarch64 + ^os.zos extended From 8fe089bfa5f0b384768f10d4143ee53ed58920fb Mon Sep 17 00:00:00 2001 From: KONNO Kazuhiro Date: Tue, 7 Apr 2020 15:47:28 +0900 Subject: [PATCH 42/61] AArch64: Call arm64CodeSync() in Trampoline.cpp This commit adds calls to arm64CodeSync() in Trampoline.cpp for AArch64. Power and ARM platforms call their CodeSync() functions. Signed-off-by: KONNO Kazuhiro --- runtime/compiler/runtime/Trampoline.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/runtime/compiler/runtime/Trampoline.cpp b/runtime/compiler/runtime/Trampoline.cpp index 8b03e1eef88..a75e692d435 100644 --- a/runtime/compiler/runtime/Trampoline.cpp +++ b/runtime/compiler/runtime/Trampoline.cpp @@ -863,6 +863,10 @@ void armCodeCacheParameters(int32_t *trampolineSize, void **callBacks, int32_t * #define TRAMPOLINE_SIZE 16 +#if defined(TR_HOST_ARM64) +extern void arm64CodeSync(uint8_t *, uint32_t); +#endif + void arm64CodeCacheConfig(int32_t ccSizeInByte, int32_t *numTempTrampolines) { *numTempTrampolines = 0; @@ -880,6 +884,10 @@ void arm64CreateHelperTrampolines(void *trampPtr, int32_t numHelpers) *((intptr_t *)buffer) = (intptr_t)runtimeHelperValue((TR_RuntimeHelper)i); buffer += 2; } + +#if defined(TR_HOST_ARM64) + arm64CodeSync((uint8_t*)trampPtr, TRAMPOLINE_SIZE * numHelpers); +#endif } void arm64CreateMethodTrampoline(void *trampPtr, void *startPC, void *method) @@ -893,6 +901,10 @@ void arm64CreateMethodTrampoline(void *trampPtr, void *startPC, void *method) *buffer = 0xD61F0200; //BR R16 buffer += 1; *((intptr_t *)buffer) = dispatcher; + +#if defined(TR_HOST_ARM64) + arm64CodeSync((uint8_t*)trampPtr, TRAMPOLINE_SIZE); +#endif } bool arm64CodePatching(void *callee, void *callSite, void *currentPC, void *currentTramp, void *newAddrOfCallee, void *extra) @@ -934,6 +946,9 @@ bool arm64CodePatching(void *callee, void *callSite, void *currentPC, void *curr else { *((uint64_t*)currentTramp+1) = (uint64_t)entryAddress; +#if defined(TR_HOST_ARM64) + arm64CodeSync((uint8_t*)currentTramp+8, 8); +#endif } } @@ -944,6 +959,9 @@ bool arm64CodePatching(void *callee, void *callSite, void *currentPC, void *curr { branchInstr |= (distance >> 2) & 0x03ffffff; *(int32_t *)callSite = branchInstr; +#if defined(TR_HOST_ARM64) + arm64CodeSync((uint8_t*)callSite, 4); +#endif } return true; From e3f353a0eca56e22cc29cf15cdc9ec54a6bedb95 Mon Sep 17 00:00:00 2001 From: Peter Shipton Date: Tue, 7 Apr 2020 09:12:35 -0400 Subject: [PATCH 43/61] Include sanity.openjdk for XL platforms There may be machine capacity to do runs of sanity.openjdk on the remaining platforms. Remove the excludes from the x, p, z linux XL platforms. [ci skip] Signed-off-by: Peter Shipton --- buildenv/jenkins/variables/defaults.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/buildenv/jenkins/variables/defaults.yml b/buildenv/jenkins/variables/defaults.yml index dda609e6261..53e3d6ba9c8 100644 --- a/buildenv/jenkins/variables/defaults.yml +++ b/buildenv/jenkins/variables/defaults.yml @@ -199,10 +199,8 @@ ppc64le_linux_xl: extends: ['ppc64le_linux', 'largeheap'] excluded_tests: 8: - - sanity.openjdk - special.system 11: - - sanity.openjdk - special.system #========================================# # Linux PPCLE 64bits Compressed Pointers /w JITSERVER @@ -237,10 +235,7 @@ s390x_linux: s390x_linux_xl: extends: ['s390x_linux', 'largeheap'] excluded_tests: - 8: - - sanity.openjdk - 11: - - sanity.openjdk + 11: - special.system #========================================# # Linux S390 64bits Compressed Pointers /w JITSERVER @@ -319,10 +314,7 @@ x86-64_linux_xl: extends: ['x86-64_linux', 'largeheap'] excluded_tests: 8: - - sanity.openjdk - special.system - 11: - - sanity.openjdk #========================================# # Linux x86 64bits Compressed Pointers / Valhalla #========================================# From 9d9d05d862c5c3321ba8deb1ebe9c55a3f37a05e Mon Sep 17 00:00:00 2001 From: Devin Nakamura Date: Tue, 7 Apr 2020 09:48:53 -0400 Subject: [PATCH 44/61] CMake: Enable omrsig Signed-off-by: Devin Nakamura --- runtime/cmake/omr_config.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/cmake/omr_config.cmake b/runtime/cmake/omr_config.cmake index b5dd876b4a3..b6ebdb9e4a9 100644 --- a/runtime/cmake/omr_config.cmake +++ b/runtime/cmake/omr_config.cmake @@ -1,5 +1,5 @@ ################################################################################ -# Copyright (c) 2018, 2019 IBM Corp. and others +# Copyright (c) 2018, 2020 IBM Corp. and others # # This program and the accompanying materials are made available under # the terms of the Eclipse Public License 2.0 which accompanies this @@ -28,3 +28,4 @@ set(OMR_DDR OFF CACHE BOOL "") set(OMR_EXAMPLE OFF CACHE INTERNAL "") set(OMR_FVTEST OFF CACHE INTERNAL "") set(OMR_GC ON CACHE INTERNAL "") +set(OMRPORT_OMRSIG_SUPPORT ON CACHE INTERNAL "") From ebc967e4c4fee9caad2dd5875f0d7ea8830056ef Mon Sep 17 00:00:00 2001 From: Joe deKoning Date: Tue, 7 Apr 2020 08:17:11 -0400 Subject: [PATCH 45/61] Change location for OpenJ9 bootjdks on AIX * new versions of AIX add system SDKs into /usr ** system SDKs are of an older vintage than OpenJ9 wants to use * eclipse/openj9#8979 Signed-off-by: Joe deKoning --- buildenv/jenkins/variables/defaults.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/buildenv/jenkins/variables/defaults.yml b/buildenv/jenkins/variables/defaults.yml index dda609e6261..b3cca27daa3 100644 --- a/buildenv/jenkins/variables/defaults.yml +++ b/buildenv/jenkins/variables/defaults.yml @@ -253,10 +253,10 @@ s390x_linux_jit: ppc64_aix: extends: ['debuginfo', 'freemarker', 'openjdk_reference_repo', 'openssl'] boot_jdk: - 8: '/usr/java7' - 11: '/usr/java11_64' - 14: '/usr/java13_64' - next: '/usr/java13_64' + 8: '/opt/java7' + 11: '/opt/java11_64' + 14: '/opt/java13_64' + next: '/opt/java13_64' release: all: 'aix-ppc64-server-release' 8: 'aix-ppc64-normal-server-release' From 608d97bc356a3b31c03c364814758f1aa3d6364d Mon Sep 17 00:00:00 2001 From: Dmitry Ten Date: Fri, 3 Apr 2020 14:43:39 -0400 Subject: [PATCH 46/61] Eliminate storeValidationRecordIfNecessary messages A lot of these messsages were being sent during AOT compilations. Replacing one message that fetches all required information with invocations of multiple methods that return the same information significantly reduces the total message count, since the latter methods already do a lot of server-side caching. Signed-off-by: Dmitry Ten --- .../control/JITClientCompilationThread.cpp | 20 ----- runtime/compiler/env/j9methodServer.cpp | 73 ++++++++----------- runtime/compiler/net/MessageTypes.hpp | 2 - 3 files changed, 30 insertions(+), 65 deletions(-) diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index d62d62935a4..6ff4e7a6a6b 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -1880,26 +1880,6 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes client->write(response, methodInfo, isRomClassForMethodInSC, sameLoaders, sameClass); } break; - case MessageType::ResolvedRelocatableMethod_storeValidationRecordIfNecessary: - { - auto recv = client->getRecvData(); - auto ramMethod = std::get<0>(recv); - auto constantPool = std::get<1>(recv); - auto cpIndex = std::get<2>(recv); - bool isStatic = std::get<3>(recv); - J9Class *definingClass = std::get<4>(recv); - J9Class *clazz = (J9Class *) J9_CLASS_FROM_METHOD(ramMethod); - if (!definingClass) - { - definingClass = (J9Class *) TR_ResolvedJ9Method::definingClassFromCPFieldRef(comp, constantPool, cpIndex, isStatic); - } - UDATA *classChain = NULL; - if (definingClass) - classChain = fe->sharedCache()->rememberClass(definingClass); - - client->write(response, clazz, definingClass, classChain); - } - break; case MessageType::ResolvedRelocatableMethod_getFieldType: { auto recv = client->getRecvData(); diff --git a/runtime/compiler/env/j9methodServer.cpp b/runtime/compiler/env/j9methodServer.cpp index 74ed985b811..742cb9457c0 100644 --- a/runtime/compiler/env/j9methodServer.cpp +++ b/runtime/compiler/env/j9methodServer.cpp @@ -2038,69 +2038,56 @@ bool TR_ResolvedRelocatableJ9JITServerMethod::storeValidationRecordIfNecessary(TR::Compilation * comp, J9ConstantPool *constantPool, int32_t cpIndex, TR_ExternalRelocationTargetKind reloKind, J9Method *ramMethod, J9Class *definingClass) { TR_J9VMBase *fej9 = (TR_J9VMBase *) comp->fe(); + bool storeClassInfo = true; bool fieldInfoCanBeUsed = false; TR_AOTStats *aotStats = ((TR_JitPrivateConfig *)fej9->_jitConfig->privateConfig)->aotStats; bool isStatic = (reloKind == TR_ValidateStaticField); - UDATA *classChain = NULL; - auto clientData = _fe->_compInfoPT->getClientData(); - PersistentUnorderedMap &classChainCache = clientData->getClassChainDataCache(); - if (definingClass) - { - // if defining class is known, check if we already have a corresponding class chain cached - OMR::CriticalSection classChainDataMapMonitor(clientData->getClassChainDataMapMonitor()); - auto it = classChainCache.find(definingClass); - if (it != classChainCache.end()) - classChain = it->second; - } - - if (!classChain) + if (comp->getDebug()) { - _stream->write(JITServer::MessageType::ResolvedRelocatableMethod_storeValidationRecordIfNecessary, ramMethod, constantPool, cpIndex, isStatic, definingClass); - // 1. RAM class of ramMethod - // 2. defining class - // 3. class chain - auto recv = _stream->read(); - - J9Class *clazz = std::get<0>(recv); + // guard this code with debug check, to avoid + // sending extra messages when not tracing traceMsg(comp, "storeValidationRecordIfNecessary:\n"); traceMsg(comp, "\tconstantPool %p cpIndex %d\n", constantPool, cpIndex); traceMsg(comp, "\treloKind %d isStatic %d\n", reloKind, isStatic); - J9UTF8 *methodClassName = J9ROMCLASS_CLASSNAME(TR::Compiler->cls.romClassOf((TR_OpaqueClassBlock *) clazz)); - traceMsg(comp, "\tmethod %p from class %p %.*s\n", ramMethod, clazz, J9UTF8_LENGTH(methodClassName), J9UTF8_DATA(methodClassName)); + J9UTF8 *methodClassName = + J9ROMCLASS_CLASSNAME( + TR::Compiler->cls.romClassOf( + fej9->getClassOfMethod(reinterpret_cast(ramMethod)))); + traceMsg(comp, + "\tmethod %p from class %p %.*s\n", + ramMethod, + fej9->getClassOfMethod(reinterpret_cast(ramMethod)), + J9UTF8_LENGTH(methodClassName), + J9UTF8_DATA(methodClassName)); traceMsg(comp, "\tdefiningClass %p\n", definingClass); + } - if (!definingClass) - { - definingClass = std::get<1>(recv); - traceMsg(comp, "\tdefiningClass recomputed from cp as %p\n", definingClass); - } + if (!definingClass) + { + definingClass = (J9Class *) TR_ResolvedJ9JITServerMethod::definingClassFromCPFieldRef(comp, cpIndex, isStatic); + traceMsg(comp, "\tdefiningClass recomputed from cp as %p\n", definingClass); + } - if (!definingClass) - { - if (aotStats) - aotStats->numDefiningClassNotFound++; - return false; - } + if (!definingClass) + { + if (aotStats) + aotStats->numDefiningClassNotFound++; + return false; + } + if (comp->getDebug()) + { J9UTF8 *className = J9ROMCLASS_CLASSNAME(TR::Compiler->cls.romClassOf((TR_OpaqueClassBlock *) definingClass)); traceMsg(comp, "\tdefiningClass name %.*s\n", J9UTF8_LENGTH(className), J9UTF8_DATA(className)); - - // all kinds of validations may need to rely on the entire class chain, so make sure we can build one first - classChain = std::get<2>(recv); } + // all kinds of validations may need to rely on the entire class chain, so make sure we can build one first + void *classChain = fej9->sharedCache()->rememberClass(definingClass); if (!classChain) return false; - { - // class chain and defining class found, cache here - OMR::CriticalSection classChainDataMapMonitor(clientData->getClassChainDataMapMonitor()); - classChainCache.insert(std::make_pair(definingClass, classChain)); - } - - bool inLocalList = false; TR::list* aotClassInfo = comp->_aotClassInfo; if (!aotClassInfo->empty()) diff --git a/runtime/compiler/net/MessageTypes.hpp b/runtime/compiler/net/MessageTypes.hpp index 083aa0b642c..75f9c9cd4f7 100644 --- a/runtime/compiler/net/MessageTypes.hpp +++ b/runtime/compiler/net/MessageTypes.hpp @@ -97,7 +97,6 @@ enum MessageType : uint16_t ResolvedMethod_definingClassFromCPFieldRef, ResolvedRelocatableMethod_createResolvedRelocatableJ9Method, - ResolvedRelocatableMethod_storeValidationRecordIfNecessary, ResolvedRelocatableMethod_fieldAttributes, ResolvedRelocatableMethod_staticAttributes, ResolvedRelocatableMethod_getFieldType, @@ -367,7 +366,6 @@ static const char *messageNames[MessageType_ARRAYSIZE] = "ResolvedMethod_dynamicConstant", // 63 "ResolvedMethod_definingClassFromCPFieldRef", // 64 "ResolvedRelocatableMethod_createResolvedRelocatableJ9Method", // 65 - "ResolvedRelocatableMethod_storeValidationRecordIfNecessary", // 66 "ResolvedRelocatableMethod_fieldAttributes", // 67 "ResolvedRelocatableMethod_staticAttributes", // 68 "ResolvedRelocatableMethod_getFieldType", // 69 From af693129d3675d7b8816270e4df3612b111ddfbe Mon Sep 17 00:00:00 2001 From: Filip Jeremic Date: Tue, 7 Apr 2020 13:27:24 -0400 Subject: [PATCH 47/61] Minimize includes in JitDump.cpp/hpp and reinstate extern "C" We are reinstating the `extern "C"` qualifier here on the two functions we expose because although not marking them as such still works it depends on the include order, i.e. whether we include j9protos.h before we declare the non-extern functions. This is fragile, so to avoid these linker issues we reinstate the `extern "C"` qualifier here. Signed-off-by: Filip Jeremic --- runtime/compiler/control/JitDump.cpp | 41 +--------------------------- runtime/compiler/control/JitDump.hpp | 13 ++------- 2 files changed, 3 insertions(+), 51 deletions(-) diff --git a/runtime/compiler/control/JitDump.cpp b/runtime/compiler/control/JitDump.cpp index 03ca8cd804f..71b350adfa4 100644 --- a/runtime/compiler/control/JitDump.cpp +++ b/runtime/compiler/control/JitDump.cpp @@ -20,54 +20,15 @@ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception *******************************************************************************/ -#include -#include -#include #include "control/JitDump.hpp" #include "codegen/CodeGenerator.hpp" -#include "compile/CompilationTypes.hpp" -#include "compile/Method.hpp" -#include "compile/ResolvedMethod.hpp" -#include "control/OptimizationPlan.hpp" -#include "control/OptionsUtil.hpp" -#include "control/Recompilation.hpp" -#include "control/RecompilationInfo.hpp" -#include "control/CompilationController.hpp" -#include "env/ClassLoaderTable.hpp" -#include "env/CompilerEnv.hpp" -#include "env/IO.hpp" -#include "env/J2IThunk.hpp" -#include "env/PersistentCHTable.hpp" -#include "env/PersistentInfo.hpp" -#include "env/jittypes.h" -#include "env/ClassTableCriticalSection.hpp" -#include "env/VMAccessCriticalSection.hpp" #include "env/VMJ9.h" -#include "il/DataTypes.hpp" -#include "ilgen/IlGeneratorMethodDetails_inlines.hpp" -#include "infra/Monitor.hpp" -#include "infra/MonitorTable.hpp" -#include "infra/CriticalSection.hpp" -#include "optimizer/DebuggingCounters.hpp" -#include "optimizer/JProfilingBlock.hpp" -#include "runtime/CodeCacheManager.hpp" -#include "runtime/HookHelpers.hpp" -#include "runtime/MethodMetaData.h" -#include "runtime/RelocationRuntime.hpp" -#include "runtime/asmprotos.h" -#include "runtime/codertinit.hpp" #include "control/MethodToBeCompiled.hpp" #include "control/CompilationRuntime.hpp" #include "control/CompilationThread.hpp" -#include "env/VMJ9.h" -#include "env/j9method.h" #include "env/ut_j9jit.h" #include "ilgen/J9ByteCodeIlGenerator.hpp" -#include "ilgen/J9ByteCodeIterator.hpp" -#include "runtime/IProfiler.hpp" -#include "runtime/HWProfiler.hpp" -#include "env/SystemSegmentProvider.hpp" #if defined(J9VM_OPT_JITSERVER) #include "control/JITServerHelpers.hpp" #include "runtime/JITServerIProfiler.hpp" @@ -83,7 +44,7 @@ blankDumpSignalHandler(struct J9PortLibrary *portLibrary, U_32 gpType, void *gpI // Returning J9PORT_SIG_EXCEPTION_RETURN will make us come back to the same crashing instruction over and over // - return J9PORT_SIG_EXCEPTION_RETURN; // FIXME: is this the right return type? - This appears to be the right return type + return J9PORT_SIG_EXCEPTION_RETURN; } typedef struct DumpCurrentILParamenters diff --git a/runtime/compiler/control/JitDump.hpp b/runtime/compiler/control/JitDump.hpp index c79bd9dd31e..4118e28ed14 100644 --- a/runtime/compiler/control/JitDump.hpp +++ b/runtime/compiler/control/JitDump.hpp @@ -19,20 +19,11 @@ * * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception *******************************************************************************/ -#include "bcnames.h" -#include "jithash.h" -#include "jitprotos.h" #include "j9.h" -#include "j9cfg.h" -#include "j9modron.h" #include "j9nonbuilder.h" -#include "j9consts.h" -#include "mmhook.h" -#include "mmomrhook.h" -#include "vmaccess.h" -UDATA +extern J9_CFUNC UDATA blankDumpSignalHandler(struct J9PortLibrary *portLibrary, U_32 gpType, void *gpInfo, void *arg); -intptr_t +extern J9_CFUNC intptr_t dumpJitInfo(J9VMThread * currentThread, char *label, J9RASdumpContext *context); From 25184bfe02661a17167cc2de8b0208e34ca8ea9f Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Mon, 6 Apr 2020 11:43:22 -0700 Subject: [PATCH 48/61] Clear peeking ilgen callNode from callsite The callNode generated from peeking ilgen is used to create the callsite of appropriate type and check for targets. Set it to NULL when both are done so that inliner code can reliably figure out whether the callsite has been updated with proper ilgen callNode or not. Signed-off-by: Yi Zhang --- runtime/compiler/optimizer/J9EstimateCodeSize.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/runtime/compiler/optimizer/J9EstimateCodeSize.cpp b/runtime/compiler/optimizer/J9EstimateCodeSize.cpp index 2321f9fb977..cfbd507092f 100644 --- a/runtime/compiler/optimizer/J9EstimateCodeSize.cpp +++ b/runtime/compiler/optimizer/J9EstimateCodeSize.cpp @@ -1239,7 +1239,8 @@ TR_J9EstimateCodeSize::realEstimateCodeSize(TR_CallTarget *calltarget, TR_CallSt TR::Node* parent = tt->getNode(); TR::Node* callNode = tt->getNode()->getFirstChild(); TR::SymbolReference* symRef = callNode->getSymbolReference(); - if (!callNode->getSymbolReference()->isUnresolved() && !visited.contains(callNode)) + if (!callNode->getSymbolReference()->isUnresolved() && !visited.contains(callNode) && + !callSites[callNode->getByteCodeIndex()]) // skip if the callsite has already been created for this byte code index { int i = callNode->getByteCodeIndex(); visited.add(callNode); @@ -1268,6 +1269,10 @@ TR_J9EstimateCodeSize::realEstimateCodeSize(TR_CallTarget *calltarget, TR_CallSt //support counters calltarget->addDeadCallee(callsite); } + + // clearing the node generated by peeking ilgen + // _callNode will be filled with node generated by actual ilgen @see TR_InlinerBase::findAndUpdateCallSiteInGraph + callsite->_callNode = NULL; } } } From 3a61ecae967679dd89e36789fa51b2b30b745be6 Mon Sep 17 00:00:00 2001 From: Annabelle Huo Date: Tue, 7 Apr 2020 13:15:02 -0400 Subject: [PATCH 49/61] Reduce CompInfo_isCompiled message from the server One frequent path on which the server sends CompInfo_isCompiled message is in ClientSessionData::cacheIProfilerInfo(). On this path, we could combine the message into other two messages: IProfiler_setCallCount and IProfiler_profilingSample. Signed-off-by: Annabelle Huo --- .../control/JITClientCompilationThread.cpp | 11 ++-- runtime/compiler/runtime/JITClientSession.cpp | 3 +- runtime/compiler/runtime/JITClientSession.hpp | 2 +- .../compiler/runtime/JITServerIProfiler.cpp | 64 ++++++++++--------- .../compiler/runtime/JITServerIProfiler.hpp | 2 +- 5 files changed, 44 insertions(+), 38 deletions(-) diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index 9997ee8b1db..dc00b858ea1 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -120,7 +120,7 @@ handler_IProfiler_profilingSample(JITServer::ClientStream *client, TR_J9VM *fe, if (wholeMethodInfo) { // Serialize all the information related to this method - abort = iProfiler->serializeAndSendIProfileInfoForMethod(method, comp, client, usePersistentCache); + abort = iProfiler->serializeAndSendIProfileInfoForMethod(method, comp, client, usePersistentCache, isCompiled); } if (!wholeMethodInfo || abort) // Send information just for this entry { @@ -135,11 +135,11 @@ handler_IProfiler_profilingSample(JITServer::ClientStream *client, TR_J9VM *fe, auto storage = (TR_IPBCDataStorageHeader*)&entryBytes[0]; uintptr_t methodStartAddress = (uintptr_t)TR::Compiler->mtd.bytecodeStart(method); entry->serialize(methodStartAddress, storage, comp->getPersistentInfo()); - client->write(JITServer::MessageType::IProfiler_profilingSample, entryBytes, false, usePersistentCache); + client->write(JITServer::MessageType::IProfiler_profilingSample, entryBytes, false, usePersistentCache, isCompiled); } else { - client->write(JITServer::MessageType::IProfiler_profilingSample, std::string(), false, usePersistentCache); + client->write(JITServer::MessageType::IProfiler_profilingSample, std::string(), false, usePersistentCache, isCompiled); } // Unlock the entry if (auto callGraphEntry = entry->asIPBCDataCallGraph()) @@ -148,7 +148,7 @@ handler_IProfiler_profilingSample(JITServer::ClientStream *client, TR_J9VM *fe, } else // No valid info for specified bytecode index { - client->write(JITServer::MessageType::IProfiler_profilingSample, std::string(), false, usePersistentCache); + client->write(JITServer::MessageType::IProfiler_profilingSample, std::string(), false, usePersistentCache, isCompiled); } } } @@ -2617,7 +2617,8 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes auto count = std::get<2>(recv); TR_IProfiler * iProfiler = fe->getIProfiler(); iProfiler->setCallCount(method, bcIndex, count, comp); - client->write(response, JITServer::Void()); + + client->write(response, TR::CompilationInfo::isCompiled((J9Method *)method)); } break; case MessageType::Recompilation_getExistingMethodInfo: diff --git a/runtime/compiler/runtime/JITClientSession.cpp b/runtime/compiler/runtime/JITClientSession.cpp index 91fca0a2586..43ffb223f58 100644 --- a/runtime/compiler/runtime/JITClientSession.cpp +++ b/runtime/compiler/runtime/JITClientSession.cpp @@ -228,7 +228,7 @@ ClientSessionData::getCachedIProfilerInfo(TR_OpaqueMethodBlock *method, uint32_t } bool -ClientSessionData::cacheIProfilerInfo(TR_OpaqueMethodBlock *method, uint32_t byteCodeIndex, TR_IPBytecodeHashTableEntry *entry) +ClientSessionData::cacheIProfilerInfo(TR_OpaqueMethodBlock *method, uint32_t byteCodeIndex, TR_IPBytecodeHashTableEntry *entry, bool isCompiled) { OMR::CriticalSection getRemoteROMClass(getROMMapMonitor()); // check whether info about j9method exists @@ -240,7 +240,6 @@ ClientSessionData::cacheIProfilerInfo(TR_OpaqueMethodBlock *method, uint32_t byt if (!iProfilerMap) { // Check and update if method is compiled when collecting profiling data - bool isCompiled = TR::CompilationInfo::isCompiled((J9Method*)method); if (isCompiled) it->second._isCompiledWhenProfiling = true; diff --git a/runtime/compiler/runtime/JITClientSession.hpp b/runtime/compiler/runtime/JITClientSession.hpp index e79bd823b6e..a898470d386 100644 --- a/runtime/compiler/runtime/JITClientSession.hpp +++ b/runtime/compiler/runtime/JITClientSession.hpp @@ -351,7 +351,7 @@ class ClientSessionData TR::Monitor *getClassMapMonitor() { return _classMapMonitor; } TR::Monitor *getClassChainDataMapMonitor() { return _classChainDataMapMonitor; } TR_IPBytecodeHashTableEntry *getCachedIProfilerInfo(TR_OpaqueMethodBlock *method, uint32_t byteCodeIndex, bool *methodInfoPresent); - bool cacheIProfilerInfo(TR_OpaqueMethodBlock *method, uint32_t byteCodeIndex, TR_IPBytecodeHashTableEntry *entry); + bool cacheIProfilerInfo(TR_OpaqueMethodBlock *method, uint32_t byteCodeIndex, TR_IPBytecodeHashTableEntry *entry, bool isCompiled); VMInfo *getOrCacheVMInfo(JITServer::ServerStream *stream); void clearCaches(); // destroys _chTableClassMap, _romClassMap and _J9MethodMap TR_AddressSet& getUnloadedClassAddresses() diff --git a/runtime/compiler/runtime/JITServerIProfiler.cpp b/runtime/compiler/runtime/JITServerIProfiler.cpp index 3f3b7c234c1..56d7734c979 100644 --- a/runtime/compiler/runtime/JITServerIProfiler.cpp +++ b/runtime/compiler/runtime/JITServerIProfiler.cpp @@ -201,10 +201,11 @@ JITServerIProfiler::profilingSample(TR_OpaqueMethodBlock *method, uint32_t byteC // Ask the client again and see if the two sources of information match auto stream = TR::CompilationInfo::getStream(); stream->write(JITServer::MessageType::IProfiler_profilingSample, method, byteCodeIndex, (uintptr_t)1); - auto recv = stream->read(); + auto recv = stream->read(); const std::string ipdata = std::get<0>(recv); bool wholeMethod = std::get<1>(recv); // indicates whether the client has sent info for entire method bool usePersistentCache = std::get<2>(recv); + bool isCompiled = std::get<3>(recv); TR_ASSERT(!wholeMethod, "Client should not have sent whole method info"); uintptr_t methodStart = TR::Compiler->mtd.bytecodeStart(method); TR_IPBCDataStorageHeader *clientData = ipdata.empty() ? NULL : (TR_IPBCDataStorageHeader *) &ipdata[0]; @@ -237,10 +238,11 @@ JITServerIProfiler::profilingSample(TR_OpaqueMethodBlock *method, uint32_t byteC // auto stream = TR::CompilationInfo::getStream(); stream->write(JITServer::MessageType::IProfiler_profilingSample, method, byteCodeIndex, (uintptr_t)(_useCaching ? 0 : 1)); - auto recv = stream->read(); + auto recv = stream->read(); const std::string ipdata = std::get<0>(recv); bool wholeMethod = std::get<1>(recv); // indicates whether the client sent info for entire method bool usePersistentCache = std::get<2>(recv); // indicates whether info can be saved in persistent memory, or only in heap memory + bool isCompiled = std::get<3>(recv); _statsIProfilerInfoMsgToClient++; bool doCache = _useCaching && wholeMethod; @@ -254,10 +256,10 @@ JITServerIProfiler::profilingSample(TR_OpaqueMethodBlock *method, uint32_t byteC { // cache some empty data so that we don't ask again for this method // this method contains empty data - if (usePersistentCache && !clientSessionData->cacheIProfilerInfo(method, byteCodeIndex, NULL)) - _statsIProfilerInfoCachingFailures++; + if (usePersistentCache && !clientSessionData->cacheIProfilerInfo(method, byteCodeIndex, NULL, isCompiled)) + _statsIProfilerInfoCachingFailures++; else if (!usePersistentCache && !compInfoPT->cacheIProfilerInfo(method, byteCodeIndex, NULL)) - _statsIProfilerInfoCachingFailures++; + _statsIProfilerInfoCachingFailures++; } return NULL; } @@ -300,7 +302,7 @@ JITServerIProfiler::profilingSample(TR_OpaqueMethodBlock *method, uint32_t byteC bci += 2; } } - if (usePersistentCache && !clientSessionData->cacheIProfilerInfo(method, bci, entry)) + if (usePersistentCache && !clientSessionData->cacheIProfilerInfo(method, bci, entry, isCompiled)) { // If caching failed we must delete the entry allocated with persistent memory _statsIProfilerInfoCachingFailures++; @@ -496,14 +498,14 @@ JITServerIProfiler::setCallCount(TR_OpaqueMethodBlock *method, int32_t bcIndex, return; bool sendRemoteMessage = false; + bool createNewEntry = false; + bool methodInfoPresentInPersistent = false; ClientSessionData *clientData = TR::compInfoPT->getClientData(); // Find clientSessionData + auto compInfoPT = (TR::CompilationInfoPerThreadRemote *) TR::compInfoPT; if (_useCaching) { OMR::CriticalSection getRemoteROMClass(clientData->getROMMapMonitor()); - auto & j9methodMap = clientData->getJ9MethodMap(); - bool methodInfoPresentInPersistent = false; bool methodInfoPresentInHeap = false; - auto compInfoPT = (TR::CompilationInfoPerThreadRemote *) TR::compInfoPT; // Check persistent cache first, then per-compilation cache TR_IPBytecodeHashTableEntry *entry = clientData->getCachedIProfilerInfo(method, bcIndex, &methodInfoPresentInPersistent); if (!methodInfoPresentInPersistent) @@ -529,24 +531,10 @@ JITServerIProfiler::setCallCount(TR_OpaqueMethodBlock *method, int32_t bcIndex, // Nothing to do because the correct data is already in place } } - else + else // Info for this bcIndex is missing. { - // Info for this bcIndex is missing. - // Create a new entry, add it to the cache and send a remote message as well - uintptr_t methodStart = TR::Compiler->mtd.bytecodeStart(method); - TR_AllocationKind allocKind = methodInfoPresentInPersistent ? persistentAlloc : heapAlloc; - TR_IPBCDataCallGraph *cgEntry = (TR_IPBCDataCallGraph*)comp->trMemory()->allocateMemory(sizeof(TR_IPBCDataCallGraph), allocKind, TR_Memory::IPBCDataCallGraph); - cgEntry = new (cgEntry) TR_IPBCDataCallGraph(methodStart + bcIndex); - - CallSiteProfileInfo *csInfo = cgEntry->getCGData(); - csInfo->_weight[0] = count; - // TODO: we should probably add some class as well - if (methodInfoPresentInPersistent) - clientData->cacheIProfilerInfo(method, bcIndex, cgEntry); - else - compInfoPT->cacheIProfilerInfo(method, bcIndex, cgEntry); - sendRemoteMessage = true; + createNewEntry = true; } } else @@ -563,7 +551,25 @@ JITServerIProfiler::setCallCount(TR_OpaqueMethodBlock *method, int32_t bcIndex, { auto stream = TR::CompilationInfo::getStream(); stream->write(JITServer::MessageType::IProfiler_setCallCount, method, bcIndex, count); - stream->read(); + auto recv = stream->read(); + bool isCompiled = std::get<0>(recv); + + if (createNewEntry) + { + // Create a new entry, add it to the cache and send a remote message as well + uintptr_t methodStart = TR::Compiler->mtd.bytecodeStart(method); + TR_AllocationKind allocKind = methodInfoPresentInPersistent ? persistentAlloc : heapAlloc; + TR_IPBCDataCallGraph *cgEntry = (TR_IPBCDataCallGraph*)comp->trMemory()->allocateMemory(sizeof(TR_IPBCDataCallGraph), allocKind, TR_Memory::IPBCDataCallGraph); + cgEntry = new (cgEntry) TR_IPBCDataCallGraph(methodStart + bcIndex); + + CallSiteProfileInfo *csInfo = cgEntry->getCGData(); + csInfo->_weight[0] = count; + // TODO: we should probably add some class as well + if (methodInfoPresentInPersistent) + clientData->cacheIProfilerInfo(method, bcIndex, cgEntry, isCompiled); + else + compInfoPT->cacheIProfilerInfo(method, bcIndex, cgEntry); + } } } @@ -733,7 +739,7 @@ JITClientIProfiler::serializeIProfilerMethodEntries(uintptr_t *pcEntries, uint32 * @return Whether the operation was successful */ bool -JITClientIProfiler::serializeAndSendIProfileInfoForMethod(TR_OpaqueMethodBlock *method, TR::Compilation *comp, JITServer::ClientStream *client, bool usePersistentCache) +JITClientIProfiler::serializeAndSendIProfileInfoForMethod(TR_OpaqueMethodBlock *method, TR::Compilation *comp, JITServer::ClientStream *client, bool usePersistentCache, bool isCompiled) { TR::StackMemoryRegion stackMemoryRegion(*comp->trMemory()); uint32_t numEntries = 0; @@ -762,11 +768,11 @@ JITClientIProfiler::serializeAndSendIProfileInfoForMethod(TR_OpaqueMethodBlock * intptr_t writtenBytes = serializeIProfilerMethodEntries(pcEntries, numEntries, (uintptr_t)&buffer[0], methodStart); TR_ASSERT(writtenBytes == bytesFootprint, "BST doesn't match expected footprint"); // send the information to the server - client->write(JITServer::MessageType::IProfiler_profilingSample, buffer, true, usePersistentCache); + client->write(JITServer::MessageType::IProfiler_profilingSample, buffer, true, usePersistentCache, isCompiled); } else if (!numEntries && !abort)// Empty IProfiler data for this method { - client->write(JITServer::MessageType::IProfiler_profilingSample, std::string(), true, usePersistentCache); + client->write(JITServer::MessageType::IProfiler_profilingSample, std::string(), true, usePersistentCache, isCompiled); } // release any entry that has been locked by us diff --git a/runtime/compiler/runtime/JITServerIProfiler.hpp b/runtime/compiler/runtime/JITServerIProfiler.hpp index 6ae47706cd5..ef310c05baa 100644 --- a/runtime/compiler/runtime/JITServerIProfiler.hpp +++ b/runtime/compiler/runtime/JITServerIProfiler.hpp @@ -142,7 +142,7 @@ class JITClientIProfiler : public TR_IProfiler // Thus, any virtual function here must call the corresponding method in // the base class. It may be better not to override any methods though - bool serializeAndSendIProfileInfoForMethod(TR_OpaqueMethodBlock*method, TR::Compilation *comp, JITServer::ClientStream *client, bool usePersistentCache); + bool serializeAndSendIProfileInfoForMethod(TR_OpaqueMethodBlock*method, TR::Compilation *comp, JITServer::ClientStream *client, bool usePersistentCache, bool isCompiled); std::string serializeIProfilerMethodEntry(TR_OpaqueMethodBlock *omb); private: From 726e4b2cc06d6f9380a99c79fb53131a5b14b5d0 Mon Sep 17 00:00:00 2001 From: "Keith W. Campbell" Date: Tue, 7 Apr 2020 13:35:40 -0400 Subject: [PATCH 50/61] Clean up DTFJ code * avoid raw types * remove unused imports Signed-off-by: Keith W. Campbell --- .../dtfj/corereaders/CoreReaderSupport.java | 7 ++- .../com/ibm/jvm/dtfjview/CombinedContext.java | 28 ++++++------ .../dtfjview/commands/DeadlockCommand.java | 18 ++++---- .../jvm/dtfjview/commands/FindCommand.java | 28 ++++++------ .../jvm/dtfjview/commands/OpenCommand.java | 4 +- .../infocommands/InfoClassCommand.java | 11 +++-- .../infocommands/InfoHeapCommand.java | 15 +++---- .../infocommands/InfoJitmCommand.java | 10 ++--- .../infocommands/InfoLockCommand.java | 43 +++++++++---------- .../infocommands/InfoMemoryCommand.java | 10 ++--- .../infocommands/InfoMmapCommand.java | 20 ++++----- .../commands/infocommands/InfoSymCommand.java | 8 ++-- .../infocommands/InfoThreadCommand.java | 3 +- .../commands/xcommands/XJCommand.java | 9 ++-- .../commands/xcommands/XKCommand.java | 8 ++-- 15 files changed, 105 insertions(+), 117 deletions(-) diff --git a/jcl/src/openj9.dtfj/share/classes/com/ibm/dtfj/corereaders/CoreReaderSupport.java b/jcl/src/openj9.dtfj/share/classes/com/ibm/dtfj/corereaders/CoreReaderSupport.java index a11a782ef1b..a1a473e4975 100644 --- a/jcl/src/openj9.dtfj/share/classes/com/ibm/dtfj/corereaders/CoreReaderSupport.java +++ b/jcl/src/openj9.dtfj/share/classes/com/ibm/dtfj/corereaders/CoreReaderSupport.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2017 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -72,6 +72,7 @@ protected byte[] coreReadBytes(int n) throws IOException { return _reader.readBytes(n); } + @Override public IAbstractAddressSpace getAddressSpace() { if (null == _addressSpace) { MemoryRange[] ranges = getMemoryRangesAsArray(); @@ -89,6 +90,7 @@ public IAbstractAddressSpace getAddressSpace() { return _addressSpace; } + @Override public boolean isTruncated() { return false; } @@ -110,7 +112,8 @@ protected boolean coreCheckOffset (long location) throws IOException { coreSeek(currentPos); return canRead; } - + + @Override public void releaseResources() throws IOException { _reader.releaseResources(); } diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/CombinedContext.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/CombinedContext.java index aa3781fd309..2fbda46c845 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/CombinedContext.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/CombinedContext.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2011, 2017 IBM Corp. and others + * Copyright (c) 2011, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -201,38 +201,38 @@ private boolean isDDRCommand(String cmdline) { */ public void startDDRInteractiveSession(Image image, PrintStream out) { ddrAvailable = false; - //late bind / reflect to the DDR -interactive main class so as not to provide a compile time link - Class ddriClass = null; + // late bind / reflect to the DDR -interactive main class so as not to provide a compile time link + Class ddriClass; try { - //ddriClass = Class.forName(DDR_INTERACTIVE_CLASS, true, image.getClass().getClassLoader()); ddriClass = Class.forName(DDR_INTERACTIVE_CLASS, true, image.getClass().getClassLoader()); } catch (ClassNotFoundException e) { logger.fine("DDR is not enabled for " + image.getSource() + " (context " + id + "). It may be pre-DDR or not a core file e.g. javacore or PHD"); return; } - Constructor constructor = null; + Constructor constructor; try { - constructor = ddriClass.getConstructor(new Class[]{List.class, PrintStream.class}); + constructor = ddriClass.getConstructor(List.class, PrintStream.class); } catch (Exception e) { logger.log(Level.FINE, "Error getting DDR Interactive constructor", e); return; } try { - ArrayList contexts = new ArrayList(); - contexts.add((DTFJContext)this); + List contexts = new ArrayList<>(1); + contexts.add(this); ddriObject = constructor.newInstance(contexts, out); - ddriMethod = ddriObject.getClass().getMethod("processLine", new Class[]{String.class}); + ddriMethod = ddriObject.getClass().getMethod("processLine", String.class); ddrAvailable = true; if (hasPropertyBeenSet(VERBOSE_MODE_PROPERTY)) { out.println("DTFJ DDR is enabled for this core dump"); } - } catch(InvocationTargetException e) { - if((e.getCause() != null) && (e.getCause() instanceof UnsupportedOperationException)) { - //this is thrown if DDR is not supported for this DTFJ Image e.g. it's pre-DDR, or a javacore etc. + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if ((cause != null) && (cause instanceof UnsupportedOperationException)) { + // this is thrown if DDR is not supported for this DTFJ Image e.g. it's pre-DDR, or a javacore etc. logger.fine("DDR is not enabled for " + image.getSource() + " (context " + id + "). It may be pre-DDR or not a core file e.g. javacore or PHD"); } else { - //for an invocation exception show the cause not the reflection exception - ddrStartupException = e.getCause(); + // for an invocation exception show the cause not the reflection exception + ddrStartupException = cause; logger.log(Level.FINE, "Error creating DDR Interactive instance", e.getCause()); } } catch (Exception e) { diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/DeadlockCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/DeadlockCommand.java index 4b3cdbcf5c9..952d1bf5fb0 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/DeadlockCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/DeadlockCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2018 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -24,8 +24,6 @@ import java.io.PrintStream; import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; import java.util.SortedMap; import java.util.TreeMap; import java.util.Vector; @@ -65,9 +63,9 @@ public void run(String command, String[] args, IContext context, PrintStream out public void doCommand() { - SortedMap monitorNodes = new TreeMap(); + SortedMap monitorNodes = new TreeMap<>(); JavaRuntime jr = ctx.getRuntime(); - Iterator itMonitor = jr.getMonitors(); + Iterator itMonitor = jr.getMonitors(); int nodeListNum = 0; out.print("\n deadlocks for runtime \n"); @@ -123,7 +121,7 @@ public void doCommand() // heap. But the active ones can be found by walking the thread list and looking // at the blocking objects. (Any others aren't blocking any threads anyway so aren't // interesting. - Iterator itThread = jr.getThreads(); + Iterator itThread = jr.getThreads(); while (itThread.hasNext()) { try { Object o = itThread.next(); @@ -164,7 +162,7 @@ public void doCommand() } } - Iterator values = monitorNodes.values().iterator(); + Iterator values = monitorNodes.values().iterator(); // Step 2. iterate over Hashtable and for every MonitorNode, iterate over monitor m1's // enter waiters (JavaMonitor.getEnterWaiters()), which are JavaThreads, and for each @@ -172,7 +170,7 @@ public void doCommand() while (values.hasNext()) { MonitorNode currNode = (MonitorNode)values.next(); - Iterator itWaiters = currNode.getEnterWaiters(); + Iterator itWaiters = currNode.getEnterWaiters(); while (itWaiters.hasNext()) { Object o = itWaiters.next(); if( !(o instanceof JavaThread) ) { @@ -201,7 +199,7 @@ public void doCommand() values = monitorNodes.values().iterator(); int visit = 1; - Vector lists = new Vector(); + Vector lists = new Vector<>(); // Step 3. iterate over Hashtable and for every MonitorNode m1: // Step 3a. set a unique visit number, visit > 0 (visit++ would work) @@ -349,7 +347,7 @@ public void doCommand() } boolean lastListWasLoop = true; - Iterator itList = lists.iterator(); + Iterator itList = lists.iterator(); // Step 5. print the lists while (itList.hasNext()) diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/FindCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/FindCommand.java index 251638847a4..bd0e64079a0 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/FindCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/FindCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2019 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -46,7 +46,7 @@ public class FindCommand extends BaseJdmpviewCommand{ */ FindAttribute findAtt = new FindAttribute(); StringBuffer sb = new StringBuffer(); - ArrayList matches = new ArrayList(); + ArrayList matches = new ArrayList<>(); { addCommand("find", "", "searches memory for a given string. Please run \"help find\" for details."); @@ -75,7 +75,7 @@ public void doCommand(String[] params){ if (!isParametersValid(params)) return; determineModeFromPattern(); if (!parseParams(params)) return; - Iterator imageSections = ctx.getAddressSpace().getImageSections(); + Iterator imageSections = ctx.getAddressSpace().getImageSections(); while(imageSections.hasNext()){ if (matches.size() > findAtt.numMatchesToDisplay) break; @@ -83,7 +83,7 @@ public void doCommand(String[] params){ if (scanImageSection(imageSection)) break; } if (matches.size() > 0) - findAtt.lastMatch = ((Long)matches.get(matches.size()-1)).longValue(); + findAtt.lastMatch = matches.get(matches.size() - 1).longValue(); ctx.getProperties().put(Utils.FIND_ATTRIBUTES, findAtt); doPrint(); if (matches.size() > 0) @@ -105,15 +105,15 @@ private void printLastMatchContent(){ + findAtt.numBytesToPrint, out); } - private void doPrint(){ + private void doPrint() { int size = matches.size(); - if(0 == size){ + if (0 == size) { sb.append("No matches found.\n"); } else{ int limit = Math.min(findAtt.numMatchesToDisplay, size); - for(int i = 0; i < limit; i++){ - long match = ((Long)matches.get(i)).longValue(); + for (int i = 0; i < limit; i++) { + long match = matches.get(i).longValue(); sb.append("#" + i + ": " + "0x" + Long.toHexString(match) + "\n"); } } @@ -148,17 +148,17 @@ else if(findAtt.startAddress <= imageEndAddress && findAtt.startAddress >= image private boolean scanRegion(long start, long end, ImageSection imageSection){ ImagePointer imagePointer = imageSection.getBaseAddress(); long i; - if (0 != start%findAtt.boundary) { - i = start - start%findAtt.boundary + findAtt.boundary; + if (0 != start % findAtt.boundary) { + i = start - start % findAtt.boundary + findAtt.boundary; } else { i = start; } int patternLength = findAtt.length(); byte[] bytes = findAtt.getBytes(); - for(; i <= end; i+=findAtt.boundary){ + for (; i <= end; i += findAtt.boundary) { int j; - for(j = 0; j < patternLength; j++){ + for (j = 0; j < patternLength; j++) { byte oneByte = bytes[j]; try { if (getByteFromImage(imagePointer, i+j) == oneByte){ @@ -171,7 +171,7 @@ private boolean scanRegion(long start, long end, ImageSection imageSection){ return false; } } - if (j >= patternLength){ + if (j >= patternLength) { matches.add(Long.valueOf(i)); if (matches.size() == findAtt.numMatchesToDisplay) return true; @@ -253,7 +253,7 @@ private void determineModeFromPattern(){ private void alignBits(){ int patternLength = findAtt.pattern.length(); - if (0 != patternLength%2){ + if (0 != patternLength % 2) { findAtt.pattern = "0" + findAtt.pattern; } } diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/OpenCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/OpenCommand.java index b7d9d7b9bb8..05a7580bcd2 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/OpenCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/OpenCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2011, 2017 IBM Corp. and others + * Copyright (c) 2011, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -47,7 +47,6 @@ import com.ibm.dtfj.java.JavaRuntime; import com.ibm.dtfj.utils.file.FileManager; import com.ibm.java.diagnostics.utils.IContext; -import com.ibm.java.diagnostics.utils.IDTFJContext; import com.ibm.java.diagnostics.utils.commands.CommandException; import com.ibm.jvm.dtfjview.CombinedContext; import com.ibm.jvm.dtfjview.JdmpviewContextManager; @@ -264,4 +263,3 @@ public void printDetailedHelp(PrintStream out) { } } - diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoClassCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoClassCommand.java index 798c000b1c9..7b0ad3bcb8c 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoClassCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoClassCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2017 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -35,7 +35,6 @@ import com.ibm.dtfj.image.CorruptData; import com.ibm.dtfj.image.CorruptDataException; -import com.ibm.dtfj.image.DataUnavailable; import com.ibm.dtfj.java.JavaClass; import com.ibm.dtfj.java.JavaClassLoader; import com.ibm.dtfj.java.JavaHeap; @@ -245,12 +244,12 @@ private void cacheRuntimeClasses() { JavaRuntime runtime = ctx.getRuntime(); classInstanceCounts.put(runtime, classesOfThisRuntime); - Iterator itClassLoader = runtime.getJavaClassLoaders(); + Iterator itClassLoader = runtime.getJavaClassLoaders(); while (itClassLoader.hasNext()) { JavaClassLoader jcl = (JavaClassLoader)itClassLoader.next(); - Iterator itClass = jcl.getDefinedClasses(); + Iterator itClass = jcl.getDefinedClasses(); while (itClass.hasNext()) { Object obj = itClass.next(); if(obj instanceof JavaClass) { @@ -319,7 +318,7 @@ private void countClassInstances() { long corruptClassCount = 0; long corruptClassNameCount = 0; - Iterator itHeap = runtime.getHeaps(); + Iterator itHeap = runtime.getHeaps(); while (itHeap.hasNext()) { Object heap = itHeap.next(); if(heap instanceof CorruptData) { @@ -327,7 +326,7 @@ private void countClassInstances() { continue; } JavaHeap jh = (JavaHeap)heap; - Iterator itObject = jh.getObjects(); + Iterator itObject = jh.getObjects(); // Walk through all objects in this heap, accumulating counts and total memory size by class while (itObject.hasNext()) { diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoHeapCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoHeapCommand.java index 6a541271302..09442c72383 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoHeapCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoHeapCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2017 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -72,8 +72,7 @@ public void run(String command, String[] args, IContext context, PrintStream out private void printHeapInfo(String param, JavaRuntime runtime, PrintStream out){ - - Iterator itHeaps = runtime.getHeaps(); + Iterator itHeaps = runtime.getHeaps(); int countheaps = 1; while (itHeaps.hasNext()) @@ -92,8 +91,7 @@ private void printHeapInfo(String param, JavaRuntime runtime, PrintStream out){ } } private void printSectionInfo(JavaHeap theHeap, PrintStream out){ - - Iterator itSections = theHeap.getSections(); + Iterator itSections = theHeap.getSections(); int countSections = 1; while (itSections.hasNext()){ @@ -118,8 +116,7 @@ private void printSectionInfo(JavaHeap theHeap, PrintStream out){ private boolean searchForHeap(String param, JavaRuntime jr, PrintStream out){ boolean foundHeap = false; - - Iterator itHeaps = jr.getHeaps(); + Iterator itHeaps = jr.getHeaps(); int countheaps = 1; while (itHeaps.hasNext()) @@ -148,7 +145,7 @@ private void printOccupancyInfo(JavaHeap theHeap, PrintStream out){ long totalObjects = 0; //total number of objects on the heap long totalCorruptObjects = 0; //total number of corrupt objects - Iterator itSections = theHeap.getSections(); + Iterator itSections = theHeap.getSections(); Object obj = null; //object returned from various iterators CorruptData cdata = null; //corrupt data while (itSections.hasNext()){ @@ -167,7 +164,7 @@ private void printOccupancyInfo(JavaHeap theHeap, PrintStream out){ } out.print("\t Size of heap: "+ size + " bytes\n"); - Iterator itObjects = theHeap.getObjects(); + Iterator itObjects = theHeap.getObjects(); try{ while (itObjects.hasNext()){ obj = itObjects.next(); diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoJitmCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoJitmCommand.java index fdb250b9884..a02f8d2d928 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoJitmCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoJitmCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2017 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -58,16 +58,16 @@ public void run(String command, String[] args, IContext context, PrintStream out private void showJITdMethods() { JavaRuntime jr = ctx.getRuntime(); - Iterator itJavaClassLoader = jr.getJavaClassLoaders(); + Iterator itJavaClassLoader = jr.getJavaClassLoaders(); while (itJavaClassLoader.hasNext()) { JavaClassLoader jcl = (JavaClassLoader)itJavaClassLoader.next(); - Iterator itJavaClass = jcl.getDefinedClasses(); + Iterator itJavaClass = jcl.getDefinedClasses(); while (itJavaClass.hasNext()) { JavaClass jc = (JavaClass)itJavaClass.next(); - Iterator itJavaMethod = jc.getDeclaredMethods(); + Iterator itJavaMethod = jc.getDeclaredMethods(); String jcName; try { @@ -96,7 +96,7 @@ private void showJITdMethods() { if (jm.getCompiledSections().hasNext()) { - Iterator itImageSection = jm.getCompiledSections(); + Iterator itImageSection = jm.getCompiledSections(); while (itImageSection.hasNext()) { ImageSection is = (ImageSection)itImageSection.next(); diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoLockCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoLockCommand.java index e4c932d54a3..646fefcf234 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoLockCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoLockCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2017 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -36,12 +36,10 @@ import com.ibm.dtfj.image.ImageThread; import com.ibm.dtfj.image.MemoryAccessException; import com.ibm.dtfj.java.JavaClass; -import com.ibm.dtfj.java.JavaField; import com.ibm.dtfj.java.JavaMonitor; import com.ibm.dtfj.java.JavaObject; import com.ibm.dtfj.java.JavaRuntime; import com.ibm.dtfj.java.JavaThread; -import com.ibm.dtfj.runtime.ManagedRuntime; import com.ibm.java.diagnostics.utils.IContext; import com.ibm.java.diagnostics.utils.commands.CommandException; import com.ibm.java.diagnostics.utils.plugins.DTFJPlugin; @@ -68,9 +66,9 @@ public void run(String command, String[] args, IContext context, PrintStream out } private void showSystemLocks() { - Vector vMonitorsWithLockedObjects = new Vector(); + Vector vMonitorsWithLockedObjects = new Vector<>(); JavaRuntime jRuntime = ctx.getRuntime(); - Iterator monitors = jRuntime.getMonitors(); + Iterator monitors = jRuntime.getMonitors(); out.println("\nSystem locks..."); while (monitors.hasNext()){ @@ -110,7 +108,7 @@ private void showSystemLocks() { private void showWaiters(JavaMonitor jMonitor) throws CorruptDataException { // List any threads waiting on enter or notify for this monitor - Iterator itEnterWaiter = jMonitor.getEnterWaiters(); + Iterator itEnterWaiter = jMonitor.getEnterWaiters(); while (itEnterWaiter.hasNext()) { Object t = itEnterWaiter.next(); if( !(t instanceof JavaThread) ) { @@ -125,7 +123,7 @@ private void showWaiters(JavaMonitor jMonitor) logger.log(Level.FINE, Exceptions.getDataUnavailableString(), dae); } } - Iterator itNotifyWaiter = jMonitor.getNotifyWaiters(); + Iterator itNotifyWaiter = jMonitor.getNotifyWaiters(); while (itNotifyWaiter.hasNext()) { Object t = itNotifyWaiter.next(); if( !(t instanceof JavaThread) ) { @@ -142,15 +140,15 @@ private void showWaiters(JavaMonitor jMonitor) } } - private void showLockedObjects(Vector vMonitorsWithLockedObjects) { + private void showLockedObjects(Vector vMonitorsWithLockedObjects) { out.println("\nObject Locks in use..."); if (0 == vMonitorsWithLockedObjects.size()){ out.println("\t...None."); return; } - Iterator lockedObjects = vMonitorsWithLockedObjects.iterator(); + Iterator lockedObjects = vMonitorsWithLockedObjects.iterator(); while(lockedObjects.hasNext()){ - JavaMonitor jMonitor = (JavaMonitor)lockedObjects.next(); + JavaMonitor jMonitor = lockedObjects.next(); JavaObject jObject = jMonitor.getObject(); try{ JavaThread owner = jMonitor.getOwner(); @@ -182,22 +180,22 @@ private void showLockedObjects(Vector vMonitorsWithLockedObjects) { private void showJavaUtilConcurrentLocks() { // A map of lock objects and their waiting threads. - Map locksToThreads = new HashMap(); + Map> locksToThreads = new HashMap<>(); JavaRuntime jr = ctx.getRuntime(); - Iterator itThread = jr.getThreads(); + Iterator itThread = jr.getThreads(); while (itThread.hasNext()) { try { Object o = itThread.next(); - if( !(o instanceof JavaThread) ) { + if (!(o instanceof JavaThread)) { continue; } - JavaThread jt = (JavaThread)o; - if( (jt.getState() & JavaThread.STATE_PARKED) != 0 ) { + JavaThread jt = (JavaThread) o; + if ((jt.getState() & JavaThread.STATE_PARKED) != 0) { JavaObject lock = jt.getBlockingObject(); - if( lock != null ) { - List parkedList = (List)locksToThreads.get(lock); - if( parkedList == null ) { - parkedList = new LinkedList(); + if (lock != null) { + List parkedList = locksToThreads.get(lock); + if (parkedList == null) { + parkedList = new LinkedList<>(); locksToThreads.put(lock, parkedList); } parkedList.add(jt); @@ -216,11 +214,10 @@ private void showJavaUtilConcurrentLocks() { out.println("\t...None."); out.println(); } - for( Object e: locksToThreads.entrySet() ) { + for (Map.Entry> entry : locksToThreads.entrySet()) { try { - Map.Entry entry = (Map.Entry)e; - JavaObject lock = (JavaObject)entry.getKey(); - List threads = (List)entry.getValue(); + JavaObject lock = entry.getKey(); + List threads = entry.getValue(); String threadName = ""; JavaThread lockOwnerThread = Utils.getParkBlockerOwner(lock, ctx.getRuntime()); if( lockOwnerThread != null ) { diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoMemoryCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoMemoryCommand.java index 892171734da..36e3b01f630 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoMemoryCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoMemoryCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2013, 2017 IBM Corp. and others + * Copyright (c) 2013, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -56,7 +56,7 @@ public void run(String command, String[] args, IContext context, PrintStream out JavaRuntime runtime = ctx.getRuntime(); try { - Iterator memoryCategories = runtime.getMemoryCategories(); + Iterator memoryCategories = runtime.getMemoryCategories(); printAllMemoryCategories(out, memoryCategories); printDbgmallocWarning(out, runtime); } catch (DataUnavailable du) { @@ -100,7 +100,7 @@ private void printDbgmallocWarning(PrintStream out, JavaRuntime runtime) { * @param out the PrintStream to write to. * @param memoryCategories the memory categories to write */ - private void printAllMemoryCategories(PrintStream out, Iterator memoryCategories) { + private void printAllMemoryCategories(PrintStream out, Iterator memoryCategories) { try { while (memoryCategories.hasNext()) { Object obj = memoryCategories.next(); @@ -147,7 +147,7 @@ private void printCategory(JavaRuntimeMemoryCategory category, LinkedList category.getShallowBytes() ) { - Iterator memoryCategories = category.getChildren(); + Iterator memoryCategories = category.getChildren(); JavaRuntimeMemoryCategory other = getOtherCategory(category); while (memoryCategories.hasNext()) { @@ -187,7 +187,7 @@ private void printCategory(JavaRuntimeMemoryCategory category, LinkedList category.getShallowBytes()) { - Iterator memoryCategories = category.getChildren(); + Iterator memoryCategories = category.getChildren(); while (memoryCategories.hasNext()) { Object obj = memoryCategories.next(); if( obj instanceof JavaRuntimeMemoryCategory) { diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoMmapCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoMmapCommand.java index 14cb3155725..43cb6d24381 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoMmapCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoMmapCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2017 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -77,10 +77,10 @@ public void run(String command, String[] args, IContext context, PrintStream out } } - List sortedSections = new LinkedList(); - Iterator imageSections = ctx.getAddressSpace().getImageSections(); - while( imageSections.hasNext() ) { - sortedSections.add(imageSections.next()); + List sortedSections = new LinkedList<>(); + Iterator imageSections = ctx.getAddressSpace().getImageSections(); + while (imageSections.hasNext()) { + sortedSections.add((ImageSection) imageSections.next()); } if( sortOrder != null ) { Collections.sort(sortedSections, sortOrder); @@ -101,11 +101,11 @@ public void run(String command, String[] args, IContext context, PrintStream out out.println(); long totalSize = 0; long totalSizeRwx = 0; - Iterator sortedIterator = sortedSections.iterator(); - while(sortedIterator.hasNext()){ - ImageSection imageSection = (ImageSection)sortedIterator.next(); - if( addressPointer != null ) { - if( imageSection.getBaseAddress().getAddress() <= addressPointer.getAddress() && + Iterator sortedIterator = sortedSections.iterator(); + while (sortedIterator.hasNext()) { + ImageSection imageSection = sortedIterator.next(); + if (addressPointer != null) { + if (imageSection.getBaseAddress().getAddress() <= addressPointer.getAddress() && imageSection.getBaseAddress().add(imageSection.getSize()).getAddress() > addressPointer.getAddress() ) { // Print this address } else { diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoSymCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoSymCommand.java index 8409b857fd8..a8326906842 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoSymCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoSymCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2017 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -99,7 +99,7 @@ private void listModules(String moduleName) { } catch (CorruptDataException e) { out.println(Exceptions.getCorruptDataExceptionString()); } - Iterator iLibs; + Iterator iLibs; try { iLibs = ip.getLibraries(); } catch (DataUnavailable du) { @@ -157,7 +157,7 @@ private void printModule(ImageModule imageModule, boolean printSymbols) { // if we do not have the load address, simply omit it } - Iterator itSection = imageModule.getSections(); + Iterator itSection = imageModule.getSections(); if (itSection.hasNext()) { out.print(", sections:\n"); @@ -190,7 +190,7 @@ private void printModule(ImageModule imageModule, boolean printSymbols) { } if (printSymbols) { out.print("\t " + "symbols:\n"); - Iterator itSymbols = imageModule.getSymbols(); + Iterator itSymbols = imageModule.getSymbols(); while (itSymbols.hasNext()) { Object next = itSymbols.next(); if (next instanceof ImageSymbol) { diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoThreadCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoThreadCommand.java index 180dc29f5e4..1b7aa42b230 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoThreadCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/infocommands/InfoThreadCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2019 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -33,7 +33,6 @@ import java.util.Map; import java.util.logging.Level; import java.util.stream.Collectors; -import java.util.stream.IntStream; import com.ibm.dtfj.image.CorruptData; import com.ibm.dtfj.image.CorruptDataException; diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/xcommands/XJCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/xcommands/XJCommand.java index 38531564e4f..e6c64034ede 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/xcommands/XJCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/xcommands/XJCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2017 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -28,7 +28,6 @@ import com.ibm.dtfj.image.CorruptData; import com.ibm.dtfj.image.CorruptDataException; import com.ibm.dtfj.image.DataUnavailable; -import com.ibm.dtfj.image.ImagePointer; import com.ibm.dtfj.java.JavaClass; import com.ibm.dtfj.java.JavaHeap; import com.ibm.dtfj.java.JavaObject; @@ -45,8 +44,7 @@ public class XJCommand extends XCommand { { addCommand("x/j", " | ", "displays information about a particular object or all objects of a class"); } - - + @Override public boolean recognises(String command, IContext context) { if(super.recognises(command, context)) { @@ -61,8 +59,7 @@ public void doCommand(String[] args) String param = args[0]; Long objAddress; String objName; - - + objAddress = Utils.longFromStringWithPrefix(param); if (null == objAddress) { diff --git a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/xcommands/XKCommand.java b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/xcommands/XKCommand.java index 364dfd9461c..4a29f9d963b 100644 --- a/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/xcommands/XKCommand.java +++ b/jcl/src/openj9.dtfjview/share/classes/com/ibm/jvm/dtfjview/commands/xcommands/XKCommand.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar18-SE]*/ /******************************************************************************* - * Copyright (c) 2004, 2017 IBM Corp. and others + * Copyright (c) 2004, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -123,7 +123,7 @@ public void doCommand(String[] args) private boolean printSymbol(long pointer, long diff, int pointerSize) { ImageProcess ip = ctx.getProcess(); - Iterator itModule; + Iterator itModule; try { itModule = ip.getLibraries(); } catch (CorruptDataException e) { @@ -135,7 +135,7 @@ private boolean printSymbol(long pointer, long diff, int pointerSize) } while (null != itModule && itModule.hasNext()) { ImageModule im = (ImageModule)itModule.next(); - Iterator itImageSection = im.getSections(); + Iterator itImageSection = im.getSections(); while (itImageSection.hasNext()) { ImageSection is = (ImageSection)itImageSection.next(); long startAddr = is.getBaseAddress().getAddress(); @@ -145,7 +145,7 @@ private boolean printSymbol(long pointer, long diff, int pointerSize) /* can we find a matching symbol? */ long maxDifference = pointer - startAddr; ImageSymbol bestSymbol = null; - for (Iterator iter = im.getSymbols(); iter.hasNext();) { + for (Iterator iter = im.getSymbols(); iter.hasNext();) { Object next = iter.next(); if (next instanceof CorruptData) continue; From 8a1b779c28be49bc11fefbb2b9f51879e1c4e500 Mon Sep 17 00:00:00 2001 From: Chris Chong Date: Tue, 7 Apr 2020 14:13:36 -0700 Subject: [PATCH 51/61] Fix typo in function name containesZeroOrOneConcreteClass Duplicate the function with the fixed name Signed-off-by: Chris Chong --- runtime/compiler/env/J9ClassEnv.cpp | 59 +++++++++++++++++++++++++++++ runtime/compiler/env/J9ClassEnv.hpp | 9 +++++ 2 files changed, 68 insertions(+) diff --git a/runtime/compiler/env/J9ClassEnv.cpp b/runtime/compiler/env/J9ClassEnv.cpp index 6ae82c29ef5..2e455b86d20 100644 --- a/runtime/compiler/env/J9ClassEnv.cpp +++ b/runtime/compiler/env/J9ClassEnv.cpp @@ -712,3 +712,62 @@ J9::ClassEnv::containesZeroOrOneConcreteClass(TR::Compilation *comp, List* subClasses) + { + int count = 0; +#if defined(J9VM_OPT_JITSERVER) + if (comp->isOutOfProcessCompilation()) + { + ListIterator j(subClasses); + TR_ScratchList subClassesNotCached(comp->trMemory()); + + // Process classes cached at the server first + ClientSessionData * clientData = TR::compInfoPT->getClientData(); + for (TR_PersistentClassInfo *ptClassInfo = j.getFirst(); ptClassInfo; ptClassInfo = j.getNext()) + { + TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); + J9Class *j9clazz = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz); + auto romClass = JITServerHelpers::getRemoteROMClassIfCached(clientData, j9clazz); + if (romClass == NULL) + { + subClassesNotCached.add(ptClassInfo); + } + else + { + if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) + { + if (++count > 1) + return false; + } + } + } + // Traverse through classes that are not cached on server + ListIterator i(&subClassesNotCached); + for (TR_PersistentClassInfo *ptClassInfo = i.getFirst(); ptClassInfo; ptClassInfo = i.getNext()) + { + TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); + if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) + { + if (++count > 1) + return false; + } + } + } + else // non-jitserver +#endif /* defined(J9VM_OPT_JITSERVER) */ + { + ListIterator i(subClasses); + for (TR_PersistentClassInfo *ptClassInfo = i.getFirst(); ptClassInfo; ptClassInfo = i.getNext()) + { + TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId(); + if (!TR::Compiler->cls.isInterfaceClass(comp, clazz) && !TR::Compiler->cls.isAbstractClass(comp, clazz)) + { + if (++count > 1) + return false; + } + } + } + return true; + } diff --git a/runtime/compiler/env/J9ClassEnv.hpp b/runtime/compiler/env/J9ClassEnv.hpp index 3f6bc15c950..e8e03b12b69 100644 --- a/runtime/compiler/env/J9ClassEnv.hpp +++ b/runtime/compiler/env/J9ClassEnv.hpp @@ -180,6 +180,15 @@ class OMR_EXTENSIBLE ClassEnv : public OMR::ClassEnvConnector * 2 concrete classses and false otherwise. */ bool containesZeroOrOneConcreteClass(TR::Compilation *comp, List* subClasses); + + /** + * @brief Determine if a list of classes contains less than two concrete classes. + * A class is considered concrete if it is not an interface or an abstract class + * @param subClasses List of subclasses to be checked. + * @return Returns 'true' if the given list of classes contains less than + * 2 concrete classses and false otherwise. + */ + bool containsZeroOrOneConcreteClass(TR::Compilation *comp, List* subClasses); }; } From 4bf4d035891acd2a5f1c9b7269000b5f6d4c9090 Mon Sep 17 00:00:00 2001 From: Ashutosh Mehra Date: Mon, 6 Apr 2020 20:54:39 +0000 Subject: [PATCH 52/61] Use _regionBytesAllocated to enforce scratch space limit Currently the code uses _systemBytesAllocated when enforcing scratch space limit. _systemBytesAllocated represents memory allocated using J9MemorySegments which are by default 16 MB in size for scratch segments. This causes two problems: 1. It prevents allocation of new system segment when scratch space limit is not a multiple of system segment size(=16 MB), even though the actual usage (_regionBytesAllocated) + requested amount is less than scratch space limit. Eg scratch space limit is set to 30 MB, and one system segment is allocated (of 16 MB), so _systemBytesAllocated = 16 MB. Lets say current usage (i.e._regionBytesAllocated is 14 MB). If we get a request of 4 MB, then we would throw std::bad_alloc even though the usage would be well below the scratch space limit after requested memory is allocated. 2. It allows memory usage beyond scratch space limit and upto system segment size even when the limit is less than the systemt segment size. Eg if scratch space limit is set to 12 MB, it would allow still allow usage upto 16 MB. _regionBytesAllocated represents memory allocated using TR_MemorySegments which are currently 64 KB in size. Because of much lower granularity, this variable is a much better approximation for the actualy physical memory usage in scrach space segments and therefore it should be used for imposing the scratch space limit. Signed-off-by: Ashutosh Mehra --- doc/compiler/memory/MemoryManager.md | 19 ++++++++++++++++++- .../compiler/env/SystemSegmentProvider.cpp | 10 +++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/doc/compiler/memory/MemoryManager.md b/doc/compiler/memory/MemoryManager.md index 6c77fe5a334..7bb8bf0899f 100644 --- a/doc/compiler/memory/MemoryManager.md +++ b/doc/compiler/memory/MemoryManager.md @@ -1,5 +1,5 @@ + ^os.zos,bits.64,^arch.aarch64 extended From f347ec29240bd9101ab2810e2e5b7d1597685718 Mon Sep 17 00:00:00 2001 From: Akira Saitoh Date: Tue, 7 Apr 2020 17:50:32 +0900 Subject: [PATCH 57/61] AArch64: Fix jitCalleeSavedRegisterList This commit adds r29-r31 to `jitCalleeSavedRegisterList` for aarch64 because `CLEAR_LOCAL_REGISTER_MAP_ENTRIES` expects `jitCalleeSavedRegisterList` to have (`J9SW_POTENTIAL_SAVED_REGISTERS` - `J9SW_JIT_CALLEE_PRESERVED_SIZE`) elements. Signed-off-by: Akira Saitoh --- .../src/com/ibm/j9ddr/vm29/j9/stackwalker/JITRegMap.java | 5 ++++- runtime/util/jitregs.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITRegMap.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITRegMap.java index 1a371bd5e29..bdf8fdabe84 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITRegMap.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITRegMap.java @@ -429,7 +429,10 @@ public class JITRegMap { 0x11, /* jit_r17 */ 0x12, /* jit_r18 */ 0x13, /* jit_r19 */ - 0x14 /* jit_r20 */ + 0x14, /* jit_r20 */ + 0x1D, /* jit_r29 */ + 0x1E, /* jit_r30 */ + 0x1F /* jit_r31 */ }; jitCalleeSavedRegisterList = new int[] { diff --git a/runtime/util/jitregs.c b/runtime/util/jitregs.c index 50f15953df2..225ab30d5ab 100644 --- a/runtime/util/jitregs.c +++ b/runtime/util/jitregs.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2019 IBM Corp. and others + * Copyright (c) 2016, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -389,6 +389,9 @@ U_8 jitCalleeDestroyedRegisterList[] = { 0x12, /* jit_r18 */ 0x13, /* jit_r19 */ 0x14, /* jit_r20 */ + 0x1D, /* jit_r29 */ + 0x1E, /* jit_r30 */ + 0x1F /* jit_r31 */ }; U_8 jitCalleeSavedRegisterList[] = { 0x15, /* jit_r21 */ From 5705b0964a1bc3ba5b5c7c7e94d795afa2a7ab21 Mon Sep 17 00:00:00 2001 From: Tobi Ajila Date: Tue, 12 Nov 2019 07:19:21 -0800 Subject: [PATCH 58/61] ACMP support for value types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for substitutability test in the acmp* bytecodes which is needed to support value types. Overview: ----------- Instead of doing a reference comparison when the ifacmp* bytecodes are executed with valueType operands, as is the case with reference type today, valueTypes will perform a structural comparison instead (substitutability test). This overload of the ifacmp* bytecodes is required because valueTypes subclass java.lang.Object and use a* bytecodes. It is possible for the static type of a valueType to be a reference type (see example below) but the reflexive properties of the `==` must still be maintained. Object p = (Object) Point.makePoint(1, 2); if (p == p) //must be true The original acmp (legacy acmp) operation in the ifacmp* bytecodes performs a simple ref comparison, lhs == rhs. This must be updated to check if both operands are valueTypes, and  if they are of the same type. If that is the case a structural comparison must be performed. Example below: ``` acmpSub(lhs, rhs) {         if (lhs == rhs) return true         if ((lhs == NULL) || (rhs == NULL)) return false         if ((lhs.class == rhs.class) && (lhs.isValue)) return isSubstitutable(lhs, rhs)         return false } ``` The structural comparison must iterate through each field and perform an equality comparison. If the field is byte, short, char, int the comparison in icmp_eq is performed. If the field is a long the comparison in lcmp is performed. If the field is a float an icmp comparison of Float.floatToIntBits of both values is performed. If the field is a double an lcmp comparison of Double.doubleToLongBits of both values is performed. Note: this behaviour differs from the float f = ...; f == f case which performs a fcmp* operation. If the field is a reference type that is java.lang.Object or an Interface or any type that may contain a valueType (i.e InlineObject, Object, restricted-abstract classes or interfaces) or if the field is a value type and both values are not NULL a recursive acmpSub is performed. For all other types the legacy acmp is performed. Example is below: ``` isSubstitutable(lhs, rhs) {         for each primitive perform primitive comparison (icmp, lcmp, Float.floatToIntBits then icmp, )         for each ref that is j.l.Object, interface, a valueType and both operands are not NULL perform acmSub (recursive)         for all other refs perform legacy acmp         return result } ``` There are cases where the JVM may optimize the individual field comparisons of the substitutability test and simply perform a memcmp over the range of the operands. This optimization is possible in cases where the substitutability test will not require recursion and there are no floating point types. The acmpSub will check to see if the fast comparison flag exists, if so it will perform a memcmp with both operands that does something like memcmp(lhs, rhs, lhs.size). This is based on Adithya's work in https://github.com/eclipse/openj9/pull/8133 Signed-off-by: Tobi Ajila --- runtime/vm/BytecodeInterpreter.hpp | 58 +-- runtime/vm/CMakeLists.txt | 2 +- runtime/vm/ValueTypeHelpers.cpp | 200 +++++++++ runtime/vm/ValueTypeHelpers.hpp | 99 +++++ runtime/vm/valueTypeHelpers.cpp | 83 ---- runtime/vm/valueTypeHelpers.hpp | 52 --- .../openj9/test/lworld/ValueTypeTests.java | 402 ++++++++++++++++-- 7 files changed, 672 insertions(+), 224 deletions(-) create mode 100644 runtime/vm/ValueTypeHelpers.cpp create mode 100644 runtime/vm/ValueTypeHelpers.hpp delete mode 100644 runtime/vm/valueTypeHelpers.cpp delete mode 100644 runtime/vm/valueTypeHelpers.hpp diff --git a/runtime/vm/BytecodeInterpreter.hpp b/runtime/vm/BytecodeInterpreter.hpp index d8fb7e8991a..f7247c19090 100644 --- a/runtime/vm/BytecodeInterpreter.hpp +++ b/runtime/vm/BytecodeInterpreter.hpp @@ -48,6 +48,7 @@ #include "MHInterpreter.hpp" #include "ObjectAccessBarrierAPI.hpp" #include "ObjectHash.hpp" +#include "ValueTypeHelpers.hpp" #include "VMHelpers.hpp" #include "VMAccess.hpp" #include "ObjectAllocationAPI.hpp" @@ -7323,56 +7324,6 @@ class INTERPRETER_CLASS return rc; } - /* - * Determine if the two objects are substitutable - * - * @param[in] lhs the lhs object of acmp bytecodes - * @param[in] rhs the rhs object of acmp bytecodes - * return true if they are substitutable and false otherwise - */ - VMINLINE bool - acmp(j9object_t lhs, j9object_t rhs) - { -#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES) - bool acmpResult = false; - if (rhs == lhs) { - acmpResult = true; - } else if ((NULL == rhs) || (NULL == lhs)) { - acmpResult = false; - } else { - J9Class * lhsClass = J9OBJECT_CLAZZ(_currentThread, lhs); - J9Class * rhsClass = J9OBJECT_CLAZZ(_currentThread, rhs); - if ((J9_IS_J9CLASS_VALUETYPE(rhsClass) - && J9_IS_J9CLASS_VALUETYPE(lhsClass)) - && (rhsClass == lhsClass) - ) { - acmpResult = isSubstitutable(lhs, rhs); - } - } - return acmpResult; -#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */ - return (rhs == lhs); -#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */ - } - -#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES) - /* - * Determine if the two valueTypes are substitutable when rhs.class equals lhs.class - * - * @param[in] lhs the lhs object of acmp bytecodes and it's a valueType - * @param[in] rhs the rhs object of acmp bytecodes and it's a valueType - * return true if they are substitutable and false otherwise - */ - VMINLINE bool - isSubstitutable(j9object_t lhs, j9object_t rhs) - { - /* - * TODO: this will be updated in a future PR. - */ - return false; - } -#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */ - /* ..., lhs, rhs => ... */ VMINLINE VM_BytecodeAction ifacmpeq(REGISTER_ARGS_LIST) @@ -7382,7 +7333,7 @@ class INTERPRETER_CLASS j9object_t lhs = *(j9object_t*)(_sp + 1); U_8 *profilingCursor = startProfilingRecord(REGISTER_ARGS, sizeof(U_8)); _sp += 2; - if(acmp(lhs, rhs)) { + if(VM_ValueTypeHelpers::acmp(_currentThread, _objectAccessBarrier, lhs, rhs)) { _pc += *(I_16*)(_pc + 1); if (NULL != profilingCursor) { *profilingCursor = 1; @@ -7406,7 +7357,7 @@ class INTERPRETER_CLASS j9object_t lhs = *(j9object_t*)(_sp + 1); U_8 *profilingCursor = startProfilingRecord(REGISTER_ARGS, sizeof(U_8)); _sp += 2; - if(!acmp(lhs, rhs)) { + if(!VM_ValueTypeHelpers::acmp(_currentThread, _objectAccessBarrier, lhs, rhs)) { _pc += *(I_16*)(_pc + 1); if (NULL != profilingCursor) { *profilingCursor = 1; @@ -8519,7 +8470,8 @@ class INTERPRETER_CLASS goto done; } - copyObjectRef = _objectAllocate.inlineAllocateObject(_currentThread, objectRefClass, false, false); + /* need to zero memset the memory so padding bytes are zeroed for memcmp-like comparisons */ + copyObjectRef = _objectAllocate.inlineAllocateObject(_currentThread, objectRefClass, true, false); if (NULL == copyObjectRef) { buildGenericSpecialStackFrame(REGISTER_ARGS, 0); pushObjectInSpecialFrame(REGISTER_ARGS, originalObjectRef); diff --git a/runtime/vm/CMakeLists.txt b/runtime/vm/CMakeLists.txt index 8c92ef56b45..abe5b7959a8 100644 --- a/runtime/vm/CMakeLists.txt +++ b/runtime/vm/CMakeLists.txt @@ -108,7 +108,7 @@ add_library(j9vm SHARED threadhelp.cpp threadpark.c throwexception.c - valueTypeHelpers.cpp + ValueTypeHelpers.cpp visible.c VMAccess.cpp vmbootlib.c diff --git a/runtime/vm/ValueTypeHelpers.cpp b/runtime/vm/ValueTypeHelpers.cpp new file mode 100644 index 00000000000..c793b4c1fb7 --- /dev/null +++ b/runtime/vm/ValueTypeHelpers.cpp @@ -0,0 +1,200 @@ +/******************************************************************************* + * Copyright (c) 2019, 2020 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ + +#include "ValueTypeHelpers.hpp" + +#include "j9.h" +#include "ut_j9vm.h" +#include "ObjectAccessBarrierAPI.hpp" + +/* + * Determine if the two valueTypes are substitutable when rhs.class equals lhs.class + * and rhs and lhs are not null + * + * @param[in] lhs the lhs object address + * @param[in] rhs the rhs object address + * @param[in] startOffset the initial offset for the object + * @param[in] clazz the value type class + * return true if they are substitutable and false otherwise + */ +bool +VM_ValueTypeHelpers::isSubstitutable(J9VMThread *currentThread, MM_ObjectAccessBarrierAPI objectAccessBarrier, j9object_t lhs, j9object_t rhs, UDATA startOffset, J9Class *clazz) +{ +#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES) + J9JavaVM *vm = currentThread->javaVM; + U_32 walkFlags = J9VM_FIELD_OFFSET_WALK_INCLUDE_INSTANCE; + J9ROMFieldOffsetWalkState state; + J9ROMFieldOffsetWalkResult *result = fieldOffsetsStartDo(vm, clazz->romClass, VM_VMHelpers::getSuperclass(clazz), &state, walkFlags, clazz->flattenedClassCache); + bool rc = true; + + Assert_VM_notNull(lhs); + Assert_VM_notNull(rhs); + Assert_VM_true(J9OBJECT_CLAZZ(currentThread, lhs) == J9OBJECT_CLAZZ(currentThread, rhs)); + + /* If J9ClassCanSupportFastSubstitutability is set, we can use the barrier version of memcmp, + * else we recursively check the fields manually. */ + if (J9_ARE_ALL_BITS_SET(clazz->classFlags, J9ClassCanSupportFastSubstitutability)) { + rc = objectAccessBarrier.structuralFlattenedCompareObjects(currentThread, clazz, lhs, rhs, startOffset); + } else { + while (NULL != result->field) { + J9UTF8 *signature = J9ROMNAMEANDSIGNATURE_SIGNATURE(&result->field->nameAndSignature); + U_8 *sigChar = J9UTF8_DATA(signature); + + switch (*sigChar) { + case 'Z': /* boolean */ + case 'B': /* byte */ + case 'C': /* char */ + case 'I': /* int */ + case 'S': { /* short */ + I_32 lhsValue = objectAccessBarrier.inlineMixedObjectReadI32(currentThread, lhs, startOffset + result->offset); + I_32 rhsValue = objectAccessBarrier.inlineMixedObjectReadI32(currentThread, rhs, startOffset + result->offset); + if (lhsValue != rhsValue) { + rc = false; + goto done; + } + break; + } + case 'J': { /* long */ + I_64 lhsValue = objectAccessBarrier.inlineMixedObjectReadI64(currentThread, lhs, startOffset + result->offset); + I_64 rhsValue = objectAccessBarrier.inlineMixedObjectReadI64(currentThread, rhs, startOffset + result->offset); + if (lhsValue != rhsValue) { + rc = false; + goto done; + } + break; + } + case 'D': { /* double */ + U_64 lhsValue = objectAccessBarrier.inlineMixedObjectReadU64(currentThread, lhs, startOffset + result->offset); + U_64 rhsValue = objectAccessBarrier.inlineMixedObjectReadU64(currentThread, rhs, startOffset + result->offset); + + if (!checkDoubleEquality(lhsValue, rhsValue)) { + rc = false; + goto done; + } + break; + } + case 'F': { /* float */ + U_32 lhsValue = objectAccessBarrier.inlineMixedObjectReadU32(currentThread, lhs, startOffset + result->offset); + U_32 rhsValue = objectAccessBarrier.inlineMixedObjectReadU32(currentThread, rhs, startOffset + result->offset); + + if (!checkFloatEquality(lhsValue, rhsValue)) { + rc = false; + goto done; + } + break; + } + case '[': { /* Array */ + j9object_t lhsObject = objectAccessBarrier.inlineMixedObjectReadObject(currentThread, lhs, startOffset + result->offset); + j9object_t rhsObject = objectAccessBarrier.inlineMixedObjectReadObject(currentThread, rhs, startOffset + result->offset); + if (lhsObject != rhsObject) { + rc = false; + goto done; + } + break; + } + case 'L': { /* Nullable class type or interface type */ + j9object_t lhsObject = objectAccessBarrier.inlineMixedObjectReadObject(currentThread, lhs, startOffset + result->offset); + j9object_t rhsObject = objectAccessBarrier.inlineMixedObjectReadObject(currentThread, rhs, startOffset + result->offset); + + if (!VM_ValueTypeHelpers::acmp(currentThread, objectAccessBarrier, lhsObject, rhsObject)) { + rc = false; + goto done; + } + break; + } + case 'Q': { /* Null-free class type */ + J9Class *fieldClass = findJ9ClassInFlattenedClassCache(clazz->flattenedClassCache, sigChar + 1, J9UTF8_LENGTH(signature) - 2); + rc = false; + + if (J9_IS_J9CLASS_FLATTENED(fieldClass)) { + rc = isSubstitutable(currentThread, objectAccessBarrier, lhs, rhs, startOffset + result->offset, fieldClass); + } else { + j9object_t lhsFieldObject = objectAccessBarrier.inlineMixedObjectReadObject(currentThread, lhs, startOffset + result->offset); + j9object_t rhsFieldObject = objectAccessBarrier.inlineMixedObjectReadObject(currentThread, rhs, startOffset + result->offset); + + if (lhsFieldObject == rhsFieldObject) { + rc = true; + } else { + /* When unflattened, we get our object from the specified offset, then increment past the header to the first field. */ + rc = isSubstitutable(currentThread, objectAccessBarrier, lhsFieldObject, rhsFieldObject, J9VMTHREAD_OBJECT_HEADER_SIZE(currentThread), fieldClass); + } + } + + if (false == rc) { + goto done; + } + break; + } + default: + Assert_VM_unreachable(); + } /* switch */ + + result = fieldOffsetsNextDo(&state); + } + } + +done: + return rc; +#else /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */ + Assert_VM_unreachable(); + return true; +#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */ +} + +extern "C" { +void +defaultValueWithUnflattenedFlattenables(J9VMThread *currentThread, J9Class *clazz, j9object_t instance) +{ + J9FlattenedClassCacheEntry * entry = NULL; + J9Class * entryClazz = NULL; + UDATA length = clazz->flattenedClassCache->numberOfEntries; + UDATA const objectHeaderSize = J9VMTHREAD_OBJECT_HEADER_SIZE(currentThread); + for (UDATA index = 0; index < length; index++) { + entry = J9_VM_FCC_ENTRY_FROM_CLASS(clazz, index); + entryClazz = entry->clazz; + if (J9_ARE_NO_BITS_SET(J9ClassIsFlattened, entryClazz->classFlags)) { + if (entry->offset == UDATA_MAX) { + J9Class *definingClass = NULL; + J9ROMFieldShape *field = NULL; + J9ROMFieldShape *entryField = entry->field; + J9UTF8 *name = J9ROMFIELDSHAPE_NAME(entryField); + J9UTF8 *signature = J9ROMFIELDSHAPE_SIGNATURE(entryField); + entry->offset = instanceFieldOffset(currentThread, clazz, J9UTF8_DATA(name), J9UTF8_LENGTH(name), J9UTF8_DATA(signature), J9UTF8_LENGTH(signature), &definingClass, (UDATA *)&field, 0); + Assert_VM_notNull(field); + } + MM_ObjectAccessBarrierAPI objectAccessBarrier(currentThread); + objectAccessBarrier.inlineMixedObjectStoreObject(currentThread, + instance, + entry->offset + objectHeaderSize, + entryClazz->flattenedClassCache->defaultValue, + false); + } + } +} + +BOOLEAN +valueTypeCapableAcmp(J9VMThread *currentThread, j9object_t lhs, j9object_t rhs) +{ + MM_ObjectAccessBarrierAPI objectAccessBarrier(currentThread); + return VM_ValueTypeHelpers::acmp(currentThread, objectAccessBarrier, lhs, rhs); +} +} /* extern "C" */ diff --git a/runtime/vm/ValueTypeHelpers.hpp b/runtime/vm/ValueTypeHelpers.hpp new file mode 100644 index 00000000000..92ca2b89e05 --- /dev/null +++ b/runtime/vm/ValueTypeHelpers.hpp @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2019, 2020 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ + +#if !defined(VALUETYPEHELPERS_HPP_) +#define VALUETYPEHELPERS_HPP_ + +#include "j9.h" +#include "fltconst.h" + +#include "ObjectAccessBarrierAPI.hpp" +#include "VMHelpers.hpp" + +class VM_ValueTypeHelpers { + /* + * Data members + */ +private: + +protected: + +public: + + /* + * Function members + */ +private: + static bool + isSubstitutable(J9VMThread *currentThread, MM_ObjectAccessBarrierAPI objectAccessBarrier, j9object_t lhs, j9object_t rhs, UDATA startOffset, J9Class *clazz); + + static VMINLINE bool + checkDoubleEquality(U_64 a, U_64 b) + { + bool result = false; + + if (a == b) { + result = true; + } else if (IS_NAN_DBL(*(jdouble*)&a) && IS_NAN_DBL(*(jdouble*)&b)) { + result = true; + } + return result; + } + + static VMINLINE bool + checkFloatEquality(U_32 a, U_32 b) + { + bool result = false; + + if (a == b) { + result = true; + } else if (IS_NAN_SNGL(*(jfloat*)&a) && IS_NAN_SNGL(*(jfloat*)&b)) { + result = true; + } + return result; + } +protected: + +public: + static VMINLINE bool + acmp(J9VMThread *currentThread, MM_ObjectAccessBarrierAPI objectAccessBarrier, j9object_t lhs, j9object_t rhs) + { + bool acmpResult = (rhs == lhs); +#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES) + if (!acmpResult) { + if ((NULL != rhs) && (NULL != lhs)) { + J9Class * lhsClass = J9OBJECT_CLAZZ(_currentThread, lhs); + J9Class * rhsClass = J9OBJECT_CLAZZ(_currentThread, rhs); + if (J9_IS_J9CLASS_VALUETYPE(lhsClass) + && (rhsClass == lhsClass) + ) { + acmpResult = VM_ValueTypeHelpers::isSubstitutable(currentThread, objectAccessBarrier, lhs, rhs, J9VMTHREAD_OBJECT_HEADER_SIZE(currentThread), lhsClass); + } + } + } +#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */ + return acmpResult; + } + +}; + +#endif /* VALUETYPEHELPERS_HPP_ */ diff --git a/runtime/vm/valueTypeHelpers.cpp b/runtime/vm/valueTypeHelpers.cpp deleted file mode 100644 index 089f71bc2e7..00000000000 --- a/runtime/vm/valueTypeHelpers.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019, 2020 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -#include "j9.h" -#include "ut_j9vm.h" -#include "ObjectAccessBarrierAPI.hpp" -#include "valueTypeHelpers.hpp" - -extern "C" { -void -defaultValueWithUnflattenedFlattenables(J9VMThread *currentThread, J9Class *clazz, j9object_t instance) -{ - J9FlattenedClassCacheEntry * entry = NULL; - J9Class * entryClazz = NULL; - UDATA length = clazz->flattenedClassCache->numberOfEntries; - UDATA const objectHeaderSize = J9VMTHREAD_OBJECT_HEADER_SIZE(currentThread); - for (UDATA index = 0; index < length; index++) { - entry = J9_VM_FCC_ENTRY_FROM_CLASS(clazz, index); - entryClazz = entry->clazz; - if (J9_ARE_NO_BITS_SET(J9ClassIsFlattened, entryClazz->classFlags)) { - if (entry->offset == UDATA_MAX) { - J9Class *definingClass = NULL; - J9ROMFieldShape *field = NULL; - J9ROMFieldShape *entryField = entry->field; - J9UTF8 *name = J9ROMFIELDSHAPE_NAME(entryField); - J9UTF8 *signature = J9ROMFIELDSHAPE_SIGNATURE(entryField); - entry->offset = instanceFieldOffset(currentThread, clazz, J9UTF8_DATA(name), J9UTF8_LENGTH(name), J9UTF8_DATA(signature), J9UTF8_LENGTH(signature), &definingClass, (UDATA *)&field, 0); - Assert_VM_notNull(field); - } - MM_ObjectAccessBarrierAPI objectAccessBarrier(currentThread); - objectAccessBarrier.inlineMixedObjectStoreObject(currentThread, - instance, - entry->offset + objectHeaderSize, - entryClazz->flattenedClassCache->defaultValue, - false); - } - } -} - -BOOLEAN -valueTypeCapableAcmp(J9VMThread *currentThread, j9object_t lhs, j9object_t rhs) -{ -#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES) - bool acmpResult = false; - if (rhs == lhs) { - acmpResult = true; - } else { - if ((NULL != rhs) && (NULL != lhs)) { - J9Class * lhsClass = J9OBJECT_CLAZZ(_currentThread, lhs); - J9Class * rhsClass = J9OBJECT_CLAZZ(_currentThread, rhs); - if ((J9_IS_J9CLASS_VALUETYPE(rhsClass) - && J9_IS_J9CLASS_VALUETYPE(lhsClass)) - && (rhsClass == lhsClass) - ) { - acmpResult = ValueTypeHelpers::isSubstitutable(currentThread, lhs, rhs, J9VMTHREAD_OBJECT_HEADER_SIZE(_currentThread), lhsClass); - } - } - } - return acmpResult; -#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */ - return (rhs == lhs); -#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */ -} -} /* extern "C" */ diff --git a/runtime/vm/valueTypeHelpers.hpp b/runtime/vm/valueTypeHelpers.hpp deleted file mode 100644 index 9e47c6c9944..00000000000 --- a/runtime/vm/valueTypeHelpers.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2020, 2020 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -#if !defined(VALUETYPEHELPERS_HPP_) -#define VALUETYPEHELPERS_HPP_ - -class ValueTypeHelpers { - /* - * Data members - */ -private: - -protected: - -public: - - /* - * Function members - */ -private: - -protected: - -public: - static bool - isSubstitutable(J9VMThread *currentThread, j9object_t lhs, j9object_t rhs, UDATA startOffset, J9Class *clazz) - { - return false; - } - -}; - -#endif /* VALUETYPEHELPERS_HPP_ */ diff --git a/test/functional/Valhalla/src/org/openj9/test/lworld/ValueTypeTests.java b/test/functional/Valhalla/src/org/openj9/test/lworld/ValueTypeTests.java index 1a218e7c9aa..b8bc0303457 100644 --- a/test/functional/Valhalla/src/org/openj9/test/lworld/ValueTypeTests.java +++ b/test/functional/Valhalla/src/org/openj9/test/lworld/ValueTypeTests.java @@ -569,41 +569,372 @@ static public void testWithFieldOnNonExistentClass() throws Throwable { } catch (NoClassDefFoundError e) {} } - /* - * TODO: behaviour of the test between two valueTypes will depend on the new spec(not finalized) - * - * Test ifacmp on value class - * - * class TestIfacmpOnValueClass {} - * - * - * @Test(priority=2) - * static public void TestIfacmpOnValueClass() throws Throwable { - * int x = 0; - * int y = 0; - * - * Object valueType = makePoint2D.invoke(x, y); - * Object refType = (Object) x; - * - * Assert.assertFalse((valueType == refType), "An identity (==) comparison that contains a valueType should always return false"); - * - * Assert.assertFalse((refType == valueType), "An identity (==) comparison that contains a valueType should always return false"); - * - * Assert.assertFalse((valueType == valueType), "An identity (==) comparison that contains a valueType should always return false"); - * - * Assert.assertTrue((refType == refType), "An identity (==) comparison on the same refType should always return true"); - * - * Assert.assertTrue((valueType != refType), "An identity (!=) comparison that contains a valueType should always return true"); - * - * Assert.assertTrue((refType != valueType), "An identity (!=) comparison that contains a valueType should always return true"); - * - * Assert.assertTrue((valueType != valueType), "An identity (!=) comparison that contains a valueType should always return true"); - * - * Assert.assertFalse((refType != refType), "An identity (!=) comparison on the same refType should always return false"); - * } - */ + + @Test(priority=2) + static public void testBasicACMPTestOnIdentityTypes() throws Throwable { + + Object identityType1 = new String(); + Object identityType2 = new String(); + Object nullPointer = null; + + /* sanity test on identity classes */ + Assert.assertTrue((identityType1 == identityType1), "An identity (==) comparison on the same identityType should always return true"); + + Assert.assertFalse((identityType2 == identityType1), "An identity (==) comparison on different identityTypes should always return false"); + + Assert.assertFalse((identityType2 == nullPointer), "An identity (==) comparison on different identityTypes should always return false"); + + Assert.assertTrue((nullPointer == nullPointer), "An identity (==) comparison on the same identityType should always return true"); + + Assert.assertFalse((identityType1 != identityType1), "An identity (!=) comparison on the same identityType should always return false"); + + Assert.assertTrue((identityType2 != identityType1), "An identity (!=) comparison on different identityTypes should always return true"); + + Assert.assertTrue((identityType2 != nullPointer), "An identity (!=) comparison on different identityTypes should always return true"); + + Assert.assertFalse((nullPointer != nullPointer), "An identity (!=) comparison on the same identityType should always return false"); + + } + + @Test(priority=2) + static public void testBasicACMPTestOnValueTypes() throws Throwable { + Object valueType1 = makePoint2D.invoke(1, 2); + Object valueType2 = makePoint2D.invoke(1, 2); + Object newValueType = makePoint2D.invoke(2, 1); + Object identityType = new String(); + Object nullPointer = null; + + Assert.assertTrue((valueType1 == valueType1), "A substitutability (==) test on the same value should always return true"); + + Assert.assertTrue((valueType1 == valueType2), "A substitutability (==) test on different value the same contents should always return true"); + + Assert.assertFalse((valueType1 == newValueType), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((valueType1 == identityType), "A substitutability (==) test on different value with identity type should always return false"); + + Assert.assertFalse((valueType1 == nullPointer), "A substitutability (==) test on different value with null pointer should always return false"); + + Assert.assertFalse((valueType1 != valueType1), "A substitutability (!=) test on the same value should always return false"); + + Assert.assertFalse((valueType1 != valueType2), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertTrue((valueType1 != newValueType), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((valueType1 != identityType), "A substitutability (!=) test on different value with identity type should always return true"); + + Assert.assertTrue((valueType1 != nullPointer), "A substitutability (!=) test on different value with null pointer should always return true"); + } + + @Test(priority=4) + static public void testACMPTestOnFastSubstitutableValueTypes() throws Throwable { + Object valueType1 = createTriangle2D(defaultTrianglePositions); + Object valueType2 = createTriangle2D(defaultTrianglePositions); + Object newValueType = createTriangle2D(defaultTrianglePositionsNew); + Object identityType = new String(); + Object nullPointer = null; + + Assert.assertTrue((valueType1 == valueType1), "A substitutability (==) test on the same value should always return true"); + + Assert.assertTrue((valueType1 == valueType2), "A substitutability (==) test on different value the same contents should always return true"); + + Assert.assertFalse((valueType1 == newValueType), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((valueType1 == identityType), "A substitutability (==) test on different value with identity type should always return false"); + + Assert.assertFalse((valueType1 == nullPointer), "A substitutability (==) test on different value with null pointer should always return false"); + + Assert.assertFalse((valueType1 != valueType1), "A substitutability (!=) test on the same value should always return false"); + + Assert.assertFalse((valueType1 != valueType2), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertTrue((valueType1 != newValueType), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((valueType1 != identityType), "A substitutability (!=) test on different value with identity type should always return true"); + + Assert.assertTrue((valueType1 != nullPointer), "A substitutability (!=) test on different value with null pointer should always return true"); + } + + @Test(priority=3) + static public void testACMPTestOnFastSubstitutableValueTypesVer2() throws Throwable { + /* these VTs will have array refs */ + String fields[] = {"x:I", "y:I", "z:I", "arr:[Ljava/lang/Object;"}; + Class fastSubVT = ValueTypeGenerator.generateValueClass("FastSubVT", fields); + + MethodHandle makeFastSubVT = lookup.findStatic(fastSubVT, "makeValue", MethodType.methodType(fastSubVT, int.class, int.class, int.class, Object[].class)); + + Object[] arr = {"foo", "bar", "baz"}; + Object[] arr2 = {"foozo", "barzo", "bazzo"}; + Object valueType1 = makeFastSubVT.invoke(1, 2, 3, arr); + Object valueType2 = makeFastSubVT.invoke(1, 2, 3, arr); + Object newValueType = makeFastSubVT.invoke(3, 2, 1, arr2); + Object identityType = new String(); + Object nullPointer = null; + + Assert.assertTrue((valueType1 == valueType1), "A substitutability (==) test on the same value should always return true"); + + Assert.assertTrue((valueType1 == valueType2), "A substitutability (==) test on different value the same contents should always return true"); + + Assert.assertFalse((valueType1 == newValueType), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((valueType1 == identityType), "A substitutability (==) test on different value with identity type should always return false"); + + Assert.assertFalse((valueType1 == nullPointer), "A substitutability (==) test on different value with null pointer should always return false"); + + Assert.assertFalse((valueType1 != valueType1), "A substitutability (!=) test on the same value should always return false"); + + Assert.assertFalse((valueType1 != valueType2), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertTrue((valueType1 != newValueType), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((valueType1 != identityType), "A substitutability (!=) test on different value with identity type should always return true"); + + Assert.assertTrue((valueType1 != nullPointer), "A substitutability (!=) test on different value with null pointer should always return true"); + } + + @Test(priority=3) + static public void testACMPTestOnRecursiveValueTypes() throws Throwable { + String fields[] = {"l:J", "next:Ljava/lang/Object;", "i:I"}; + Class nodeClass = ValueTypeGenerator.generateValueClass("Node", fields); + MethodHandle makeNode = lookup.findStatic(nodeClass, "makeValue", MethodType.methodType(nodeClass, long.class, Object.class, int.class)); + + Object list1 = makeNode.invoke(3, null, 3); + Object list2 = makeNode.invoke(3, null, 3); + Object list3sameAs1 = makeNode.invoke(3, null, 3); + Object list4 = makeNode.invoke(3, null, 3); + Object list5null = makeNode.invoke(3, null, 3); + Object list6null = makeNode.invoke(3, null, 3); + Object list7obj = makeNode.invoke(3, new Object(), 3); + Object list8str = makeNode.invoke(3, "foo", 3); + Object identityType = new String(); + Object nullPointer = null; + + for (int i = 0; i < 100; i++) { + list1 = makeNode.invoke(3, list1, i); + list2 = makeNode.invoke(3, list2, i + 1); + list3sameAs1 = makeNode.invoke(3, list3sameAs1, i); + } + for (int i = 0; i < 50; i++) { + list4 = makeNode.invoke(3, list4, i); + } + + Assert.assertTrue((list1 == list1), "A substitutability (==) test on the same value should always return true"); + + Assert.assertTrue((list5null == list5null), "A substitutability (==) test on the same value should always return true"); + + Assert.assertTrue((list1 == list3sameAs1), "A substitutability (==) test on different value the same contents should always return true"); + + Assert.assertTrue((list5null == list6null), "A substitutability (==) test on different value the same contents should always return true"); + + Assert.assertFalse((list1 == list2), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((list1 == list4), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((list1 == list5null), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((list1 == list7obj), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((list1 == list8str), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((list7obj == list8str), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((list1 == identityType), "A substitutability (==) test on different value with identity type should always return false"); + + Assert.assertFalse((list1 == nullPointer), "A substitutability (==) test on different value with null pointer should always return false"); + + Assert.assertFalse((list1 != list1), "A substitutability (!=) test on the same value should always return false"); + + Assert.assertFalse((list5null != list5null), "A substitutability (!=) test on the same value should always return false"); + + Assert.assertFalse((list1 != list3sameAs1), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertFalse((list5null != list6null), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertTrue((list1 != list2), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((list1 != list4), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((list1 != list5null), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((list1 != list7obj), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((list1 != list8str), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((list7obj != list8str), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((list1 != identityType), "A substitutability (!=) test on different value with identity type should always return true"); + + Assert.assertTrue((list1 != nullPointer), "A substitutability (!=) test on different value with null pointer should always return true"); + + } + + @Test(priority=3) + static public void testACMPTestOnValueFloat() throws Throwable { + Object float1 = makeValueFloat.invoke(1.1f); + Object float2 = makeValueFloat.invoke(-1.1f); + Object float3 = makeValueFloat.invoke(12341.112341234f); + Object float4sameAs1 = makeValueFloat.invoke(1.1f); + Object nan = makeValueFloat.invoke(Float.NaN); + Object nan2 = makeValueFloat.invoke(Float.NaN); + Object positiveZero = makeValueFloat.invoke(0.0f); + Object negativeZero = makeValueFloat.invoke(-0.0f); + Object positiveInfinity = makeValueFloat.invoke(Float.POSITIVE_INFINITY); + Object negativeInfinity = makeValueFloat.invoke(Float.NEGATIVE_INFINITY); + + Assert.assertTrue((float1 == float1), "A substitutability (==) test on the same value should always return true"); + + Assert.assertTrue((float1 == float4sameAs1), "A substitutability (==) test on different value the same contents should always return true"); + + Assert.assertTrue((nan == nan2), "A substitutability (==) test on different value the same contents should always return true"); + + Assert.assertFalse((float1 == float2), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((float1 == float3), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((float1 == nan), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((float1 == positiveZero), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((float1 == negativeZero), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((float1 == positiveInfinity), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((float1 == negativeInfinity), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((positiveInfinity == negativeInfinity), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((positiveZero == negativeZero), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((float1 != float1), "A substitutability (!=) test on the same value should always return false"); + + Assert.assertFalse((float1 != float4sameAs1), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertFalse((nan != nan2), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertTrue((float1 != float2), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((float1 != float3), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((float1 != nan), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((float1 != positiveZero), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((float1 != negativeZero), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((float1 != positiveInfinity), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((float1 != negativeInfinity), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((positiveInfinity != negativeInfinity), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((positiveZero != negativeZero), "A substitutability (!=) test on different value should always return true"); + + } + + @Test(priority=3) + static public void testACMPTestOnValueDouble() throws Throwable { + Object double1 = makeValueDouble.invoke(1.1d); + Object double2 = makeValueDouble.invoke(-1.1d); + Object double3 = makeValueDouble.invoke(12341.112341234d); + Object double4sameAs1 = makeValueDouble.invoke(1.1d); + Object nan = makeValueDouble.invoke(Double.NaN); + Object nan2 = makeValueDouble.invoke(Double.NaN); + Object positiveZero = makeValueDouble.invoke(0.0f); + Object negativeZero = makeValueDouble.invoke(-0.0f); + Object positiveInfinity = makeValueDouble.invoke(Double.POSITIVE_INFINITY); + Object negativeInfinity = makeValueDouble.invoke(Double.NEGATIVE_INFINITY); + + Assert.assertTrue((double1 == double1), "A substitutability (==) test on the same value should always return true"); + + Assert.assertTrue((double1 == double4sameAs1), "A substitutability (==) test on different value the same contents should always return true"); - /* + Assert.assertTrue((nan == nan2), "A substitutability (==) test on different value the same contents should always return true"); + + Assert.assertFalse((double1 == double2), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((double1 == double3), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((double1 == nan), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((double1 == positiveZero), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((double1 == negativeZero), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((double1 == positiveInfinity), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((double1 == negativeInfinity), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((positiveInfinity == negativeInfinity), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((positiveZero == negativeZero), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((double1 != double1), "A substitutability (!=) test on the same value should always return false"); + + Assert.assertFalse((double1 != double4sameAs1), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertFalse((nan != nan2), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertTrue((double1 != double2), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((double1 != double3), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((double1 != nan), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((double1 != positiveZero), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((double1 != negativeZero), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((double1 != positiveInfinity), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((double1 != negativeInfinity), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((positiveInfinity != negativeInfinity), "A substitutability (!=) test on different value should always return true"); + + Assert.assertTrue((positiveZero != negativeZero), "A substitutability (!=) test on different value should always return true"); + } + + @Test(priority=6) + static public void testACMPTestOnAssortedValues() throws Throwable { + Object assortedValueWithLongAlignment = createAssorted(makeAssortedValueWithLongAlignment, typeWithLongAlignmentFields); + Object assortedValueWithLongAlignment2 = createAssorted(makeAssortedValueWithLongAlignment, typeWithLongAlignmentFields); + Object assortedValueWithLongAlignment3 = createAssorted(makeAssortedValueWithLongAlignment, typeWithLongAlignmentFields); + assortedValueWithLongAlignment3 = checkFieldAccessMHOfAssortedType(assortedValueWithLongAlignmentGetterAndWither, assortedValueWithLongAlignment3, typeWithLongAlignmentFields, true); + + Object assortedValueWithObjectAlignment = createAssorted(makeAssortedValueWithObjectAlignment, typeWithObjectAlignmentFields); + Object assortedValueWithObjectAlignment2 = createAssorted(makeAssortedValueWithObjectAlignment, typeWithObjectAlignmentFields); + Object assortedValueWithObjectAlignment3 = createAssorted(makeAssortedValueWithObjectAlignment, typeWithObjectAlignmentFields); + assortedValueWithObjectAlignment3 = checkFieldAccessMHOfAssortedType(assortedValueWithObjectAlignmentGetterAndWither, assortedValueWithObjectAlignment3, typeWithObjectAlignmentFields, true); + + Assert.assertTrue((assortedValueWithLongAlignment == assortedValueWithLongAlignment), "A substitutability (==) test on the same value should always return true"); + + Assert.assertTrue((assortedValueWithObjectAlignment == assortedValueWithObjectAlignment), "A substitutability (==) test on the same value should always return true"); + + Assert.assertTrue((assortedValueWithLongAlignment == assortedValueWithLongAlignment2), "A substitutability (==) test on different value the same contents should always return true"); + + Assert.assertTrue((assortedValueWithObjectAlignment == assortedValueWithObjectAlignment2), "A substitutability (==) test on different value the same contents should always return true"); + + Assert.assertFalse((assortedValueWithLongAlignment == assortedValueWithLongAlignment3), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((assortedValueWithLongAlignment == assortedValueWithObjectAlignment), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((assortedValueWithObjectAlignment == assortedValueWithObjectAlignment3), "A substitutability (==) test on different value should always return false"); + + Assert.assertFalse((assortedValueWithLongAlignment != assortedValueWithLongAlignment), "A substitutability (!=) test on the same value should always return false"); + + Assert.assertFalse((assortedValueWithObjectAlignment != assortedValueWithObjectAlignment), "A substitutability (!=) test on the same value should always return false"); + + Assert.assertFalse((assortedValueWithLongAlignment != assortedValueWithLongAlignment2), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertFalse((assortedValueWithObjectAlignment != assortedValueWithObjectAlignment2), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertTrue((assortedValueWithLongAlignment != assortedValueWithLongAlignment3), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertTrue((assortedValueWithLongAlignment != assortedValueWithObjectAlignment), "A substitutability (!=) test on different value the same contents should always return false"); + + Assert.assertTrue((assortedValueWithObjectAlignment != assortedValueWithObjectAlignment3), "A substitutability (!=) test on different value the same contents should always return false"); + + } + + /* * Test monitorEnter on valueType * * class TestMonitorEnterOnValueType { @@ -1916,7 +2247,7 @@ static void initializeStaticFields(Class clazz, MethodHandle[][] getterAndSetter } } - static void checkFieldAccessMHOfAssortedType(MethodHandle[][] fieldAccessMHs, Object instance, String[] fields, + static Object checkFieldAccessMHOfAssortedType(MethodHandle[][] fieldAccessMHs, Object instance, String[] fields, boolean ifValue) throws Throwable { for (int i = 0; i < fields.length; i++) { @@ -2017,6 +2348,7 @@ static void checkFieldAccessMHOfAssortedType(MethodHandle[][] fieldAccessMHs, Ob break; } } + return instance; } static void checkFieldAccessMHOfStaticType(MethodHandle[][] fieldAccessMHs, String[] fields) From 5cd0ba6ab6499c77250dd20eca910dc4c3005a50 Mon Sep 17 00:00:00 2001 From: KONNO Kazuhiro Date: Fri, 6 Mar 2020 14:06:11 +0900 Subject: [PATCH 59/61] Enable DDR tests for AArch64 again This commit enables DDR tests that were disabled for AArch64 in #8569. Signed-off-by: KONNO Kazuhiro --- test/functional/DDR_Test/playlist.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/DDR_Test/playlist.xml b/test/functional/DDR_Test/playlist.xml index 3dd6321280f..99ef07f4233 100644 --- a/test/functional/DDR_Test/playlist.xml +++ b/test/functional/DDR_Test/playlist.xml @@ -118,7 +118,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti -Dtest.list=$(Q)TestJITExt$(Q) -DADDITIONALEXPORTS=$(ADDEXPORTS_JDKASM_UNNAMED) -DEXTRADUMPOPT=$(Q)-Xjit:count=0$(Q) -f $(Q)$(TEST_RESROOT)$(D)tck_ddrext.xml$(Q); \ $(TEST_STATUS) - ^os.zos,^arch.aarch64 + ^os.zos extended From 7c558d4715ab78d164efb2e5cafff15c582441c6 Mon Sep 17 00:00:00 2001 From: XuechunHou Date: Wed, 8 Apr 2020 21:25:24 -0600 Subject: [PATCH 60/61] addressed feedback --- .../compiler/control/BasePersistentLogger.hpp | 2 - runtime/compiler/control/CassandraLogger.cpp | 55 +++++++------------ runtime/compiler/control/CassandraLogger.hpp | 5 -- runtime/compiler/control/J9Options.cpp | 18 +++--- .../control/JITServerCompilationThread.cpp | 4 +- runtime/compiler/control/LoadDBLibs.cpp | 2 +- runtime/compiler/control/MongoLogger.cpp | 22 ++++++++ runtime/compiler/control/MongoLogger.hpp | 22 ++++++++ runtime/compiler/env/J9PersistentInfo.hpp | 6 +- 9 files changed, 79 insertions(+), 57 deletions(-) diff --git a/runtime/compiler/control/BasePersistentLogger.hpp b/runtime/compiler/control/BasePersistentLogger.hpp index d18cc955ca8..fe25cdf9e83 100644 --- a/runtime/compiler/control/BasePersistentLogger.hpp +++ b/runtime/compiler/control/BasePersistentLogger.hpp @@ -10,11 +10,9 @@ class BasePersistentLogger const char* _databaseUsername; const char* _databasePassword; const char* _databaseName; - public: virtual bool connect() = 0; virtual void disconnect() = 0; - BasePersistentLogger(const char * databaseIP, uint32_t databasePort, const char * databaseName) { _databaseIP = databaseIP; diff --git a/runtime/compiler/control/CassandraLogger.cpp b/runtime/compiler/control/CassandraLogger.cpp index f505ac8a361..da007e4b714 100644 --- a/runtime/compiler/control/CassandraLogger.cpp +++ b/runtime/compiler/control/CassandraLogger.cpp @@ -1,11 +1,10 @@ #include #include - #include "CassandraLogger.hpp" +#include "j9.h" #include "LoadDBLibs.hpp" -CassandraLogger::CassandraLogger(const char *databaseIP, -uint32_t databasePort, -const char *databaseName): BasePersistentLogger(databaseIP, databasePort, databaseName) +CassandraLogger::CassandraLogger(const char *databaseIP, uint32_t databasePort, + const char *databaseName): BasePersistentLogger(databaseIP, databasePort, databaseName) { _session = NULL; _connectFuture = NULL; @@ -26,7 +25,6 @@ bool CassandraLogger::createKeySpace() char queryString[256]; snprintf(queryString, 256, "CREATE KEYSPACE IF NOT EXISTS %s WITH REPLICATION = {'class':'SimpleStrategy','replication_factor':1};", _databaseName); OCassStatement* statement = Ocass_statement_new(queryString, 0); - OCassFuture* queryFuture = Ocass_session_execute(_session, statement); Ocass_statement_free(statement); if (Ocass_future_error_code(queryFuture) != 0) @@ -36,14 +34,11 @@ bool CassandraLogger::createKeySpace() size_t messageLength; Ocass_future_error_message(queryFuture, &message, &messageLength); fprintf(stderr, "PersistentLogging - Cassandra Database Keyspace Creation Error: '%.*s'\n", (int)messageLength, message); - Ocass_future_free(queryFuture); return false; } - Ocass_future_free(queryFuture); return true; - } bool CassandraLogger::createTable(const char *tableName) { @@ -59,11 +54,9 @@ bool CassandraLogger::createTable(const char *tableName) size_t messageLength; Ocass_future_error_message(queryFuture, &message, &messageLength); fprintf(stderr, "Persistent Logging - Cassandra Database Table Creation Error: '%.*s'\n", (int)messageLength, message); - Ocass_future_free(queryFuture); return false; } - Ocass_future_free(queryFuture); return true; } @@ -82,9 +75,7 @@ bool CassandraLogger::connect() Ocass_session_free(_session); Ocass_cluster_free(_cluster); return false; - } - /* Add contact points */ int rc_set_ip = Ocass_cluster_set_contact_points(_cluster, _databaseIP); if (rc_set_ip != 0) @@ -93,9 +84,7 @@ bool CassandraLogger::connect() Ocass_session_free(_session); Ocass_cluster_free(_cluster); return false; - } - /*Set port number*/ int rc_set_port = Ocass_cluster_set_port(_cluster, _databasePort); if (rc_set_port != 0) @@ -103,14 +92,10 @@ bool CassandraLogger::connect() fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_port)); Ocass_session_free(_session); Ocass_cluster_free(_cluster); - return false; - } - /* Provide the cluster object as configuration to connect the session */ _connectFuture = Ocass_session_connect(_session, _cluster); - if (Ocass_future_error_code(_connectFuture) != 0) { /* Display connection error message */ @@ -124,23 +109,20 @@ bool CassandraLogger::connect() return false; } return true; - } bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const char *logContent) { - // create table space and table first - if (!createKeySpace()) return false; + if (!createKeySpace()) + return false; const char* tableName = "logs"; - if (!createTable(tableName)) return false; + if (!createTable(tableName)) + return false; char queryString[256]; - snprintf(queryString, 256, "INSERT INTO %s.%s (clientID, methodName, logContent, insertionDate, insertionTime) VALUES (?, ?, ?, ?, ?)", _databaseName,tableName); - OCassStatement* statement - = Ocass_statement_new(queryString, 5); - + OCassStatement* statement = Ocass_statement_new(queryString, 5); /* Bind the values using the indices of the bind variables */ char strClientID[64]; snprintf(strClientID, 64, "%lu", clientID); @@ -151,7 +133,6 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha Ocass_statement_free(statement); return false; } - int rc_set_bind_method = Ocass_statement_bind_string(statement, 1, method); if (rc_set_bind_pk != 0) { @@ -160,7 +141,6 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha return false; } int rc_set_bind_log_content = Ocass_statement_bind_string(statement, 2, logContent); - if (rc_set_bind_log_content != 0) { fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n",Ocass_error_desc(rc_set_bind_log_content)); @@ -168,15 +148,26 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha return false; } + // J9PortLibraryVersion portLibraryVersion; + // J9PortLibrary portLibrary; + // J9PORT_SET_VERSION(&portLibraryVersion, J9PORT_CAPABILITY_MASK); + // if (j9port_init_library(&portLibrary, &portLibraryVersion, sizeof(J9PortLibrary)) != 0) + // { + // fprintf(stderr, "Persistent Logging - Cassandra Database Init J9port Library Error\n"); + // Ocass_statement_free(statement); + // return false; + // } + // UDATA success = 0; + // PORT_ACCESS_FROM_PORT(&portLibrary); + // uint64_t current_time = j9time_current_time_nanos(&success); + // printf("what is my time here %lu\n",current_time); time_t now = time(NULL); /* Time in seconds from Epoch */ /* Converts the time since the Epoch in seconds to the 'date' type */ Ocass_uint32_t year_month_day_of_insertion = Ocass_date_from_epoch(now); /* Converts the time since the Epoch in seconds to the 'time' type */ Ocass_int64_t time_of_insertion = Ocass_time_from_epoch(now); - /* 'date' uses an unsigned 32-bit integer */ int rc_set_bind_insertion_date = Ocass_statement_bind_uint32(statement, 3, year_month_day_of_insertion); - if (rc_set_bind_insertion_date != 0) { fprintf(stderr, "Persistent Logging - Cassandra Database Error: %s\n", Ocass_error_desc(rc_set_bind_insertion_date)); @@ -191,9 +182,7 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha Ocass_statement_free(statement); return false; } - OCassFuture* queryFuture = Ocass_session_execute(_session, statement); - /* Statement objects can be freed immediately after being executed */ Ocass_statement_free(statement); if (Ocass_future_error_code(queryFuture) != 0) @@ -206,12 +195,10 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha Ocass_future_free(queryFuture); return false; } - Ocass_future_free(queryFuture); return true; } - void CassandraLogger::disconnect() { Ocass_future_free(_connectFuture); diff --git a/runtime/compiler/control/CassandraLogger.hpp b/runtime/compiler/control/CassandraLogger.hpp index 358028eb74f..2f19d03a6c9 100644 --- a/runtime/compiler/control/CassandraLogger.hpp +++ b/runtime/compiler/control/CassandraLogger.hpp @@ -5,24 +5,19 @@ #include "BasePersistentLogger.hpp" class CassandraLogger : public BasePersistentLogger { - private: OCassCluster* _cluster; OCassSession* _session; OCassFuture* _connectFuture; bool createKeySpace(); bool createTable(const char *tableName); - - public: - bool connect() override; void disconnect() override; CassandraLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName, const char *databaseUsername, const char *databasePassword); CassandraLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName); bool logMethod(const char *method, uint64_t clientID, const char *logContent) override; - }; #endif // CASSANDRALOGGER_H \ No newline at end of file diff --git a/runtime/compiler/control/J9Options.cpp b/runtime/compiler/control/J9Options.cpp index eb73c497691..0ef54f214d5 100644 --- a/runtime/compiler/control/J9Options.cpp +++ b/runtime/compiler/control/J9Options.cpp @@ -1092,17 +1092,6 @@ static void JITServerParseCommonOptions(J9JavaVM *vm, TR::CompilationInfo *compI int32_t xxJITServerPersistentLoggingDatabaseNameArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseNameOption, 0); int32_t xxJITServerPersistentLoggingDatabaseUsernameArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabaseUsernameOption, 0); int32_t xxJITServerPersistentLoggingDatabasePasswordArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerPersistentLoggingDatabasePasswordOption, 0); -#endif // defined(MONGO_LOGGER) || ... - - if (xxJITServerPortArgIndex >= 0) - { - uint32_t port=0; - IDATA ret = GET_INTEGER_VALUE(xxJITServerPortArgIndex, xxJITServerPortOption, port); - if (ret == OPTION_OK) - compInfo->getPersistentInfo()->setJITServerPort(port); - } - -#if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) if (xxJITServerPersistentLoggingArgIndex >= 0) { bool enable = false; @@ -1144,6 +1133,13 @@ static void JITServerParseCommonOptions(J9JavaVM *vm, TR::CompilationInfo *compI compInfo->getPersistentInfo()->setJITServerPersistentLoggingDatabaseAddress(address); } #endif // defined(MONGO_LOGGER) || ... + if (xxJITServerPortArgIndex >= 0) + { + uint32_t port=0; + IDATA ret = GET_INTEGER_VALUE(xxJITServerPortArgIndex, xxJITServerPortOption, port); + if (ret == OPTION_OK) + compInfo->getPersistentInfo()->setJITServerPort(port); + } if (xxJITServerTimeoutArgIndex >= 0) { diff --git a/runtime/compiler/control/JITServerCompilationThread.cpp b/runtime/compiler/control/JITServerCompilationThread.cpp index 954edec882e..1e699b39f10 100644 --- a/runtime/compiler/control/JITServerCompilationThread.cpp +++ b/runtime/compiler/control/JITServerCompilationThread.cpp @@ -125,7 +125,9 @@ outOfProcessCompilationEnd( logger.disconnect(); } else - fprintf(stderr, "JITServer: Persistent Logging Error - Database connection failed.\n"); + { + fprintf(stderr, "JITServer: Persistent Logging Error - Database connection failed.\n"); + } } #endif // defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) diff --git a/runtime/compiler/control/LoadDBLibs.cpp b/runtime/compiler/control/LoadDBLibs.cpp index d9060997f57..c5f6d089d4b 100644 --- a/runtime/compiler/control/LoadDBLibs.cpp +++ b/runtime/compiler/control/LoadDBLibs.cpp @@ -101,7 +101,7 @@ namespace JITServer handle = loadLibmongoc(); if (!handle) { - printf("#JITServer: Failed to load libmongoc\n"); + fprintf(stderr, "#JITServer: Failed to load libmongoc\n"); return false; } diff --git a/runtime/compiler/control/MongoLogger.cpp b/runtime/compiler/control/MongoLogger.cpp index ba8be02ab0d..8fb06733a8e 100644 --- a/runtime/compiler/control/MongoLogger.cpp +++ b/runtime/compiler/control/MongoLogger.cpp @@ -1,3 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2020, 2020 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ + #include "MongoLogger.hpp" #include #include diff --git a/runtime/compiler/control/MongoLogger.hpp b/runtime/compiler/control/MongoLogger.hpp index ce793e3b462..05e9186e34b 100644 --- a/runtime/compiler/control/MongoLogger.hpp +++ b/runtime/compiler/control/MongoLogger.hpp @@ -1,3 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2020, 2020 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ + #ifndef MONGOLOGGER_HPP #define MONGOLOGGER_HPP diff --git a/runtime/compiler/env/J9PersistentInfo.hpp b/runtime/compiler/env/J9PersistentInfo.hpp index b9a94014d66..b6da7a19907 100644 --- a/runtime/compiler/env/J9PersistentInfo.hpp +++ b/runtime/compiler/env/J9PersistentInfo.hpp @@ -135,11 +135,11 @@ class PersistentInfo : public OMR::PersistentInfoConnector _JITServerPort(38400), #if defined(MONGO_LOGGER) || defined(CASSANDRA_LOGGER) _JITServerPersistentLogging(false), - #if defined(CASSANDRA_LOGGER) +#if defined(CASSANDRA_LOGGER) _JITServerPersistentLoggingDatabasePort(9042), - #elif defined(MONGO_LOGGER) +#elif defined(MONGO_LOGGER) _JITServerPersistentLoggingDatabasePort(27017), - #endif //MONGO_LOGGER elif CASSANDRA_LOGGER +#endif //MONGO_LOGGER elif CASSANDRA_LOGGER _JITServerPersistentLoggingDatabaseAddress("127.0.0.1"), _JITServerPersistentLoggingDatabaseUsername("admin"), _JITServerPersistentLoggingDatabaseName("jitserver_logs"), From 81dfd12de64618e104166405ea12d0b8ae0b8d42 Mon Sep 17 00:00:00 2001 From: XuechunHou Date: Thu, 9 Apr 2020 12:10:41 -0600 Subject: [PATCH 61/61] replaced time function from time.h with omr time function from j9.h --- .../compiler/control/BasePersistentLogger.hpp | 3 ++- runtime/compiler/control/CassandraLogger.cpp | 21 +++---------------- runtime/compiler/control/CassandraLogger.hpp | 2 +- .../control/JITServerCompilationThread.cpp | 2 +- runtime/compiler/control/MongoLogger.cpp | 2 +- runtime/compiler/control/MongoLogger.hpp | 2 +- 6 files changed, 9 insertions(+), 23 deletions(-) diff --git a/runtime/compiler/control/BasePersistentLogger.hpp b/runtime/compiler/control/BasePersistentLogger.hpp index fe25cdf9e83..206be9abe6b 100644 --- a/runtime/compiler/control/BasePersistentLogger.hpp +++ b/runtime/compiler/control/BasePersistentLogger.hpp @@ -1,6 +1,7 @@ #ifndef JITSERVERLOGGER_BASEPERSISTENTLOGGER_H #define JITSERVERLOGGER_BASEPERSISTENTLOGGER_H #include +#include "j9.h" class BasePersistentLogger { @@ -30,7 +31,7 @@ class BasePersistentLogger _databaseUsername = databaseUsername; _databasePassword = databasePassword; } - virtual bool logMethod(const char* method, uint64_t clientID, const char *logContent) = 0; + virtual bool logMethod(const char* method, uint64_t clientID, const char *logContent, J9JITConfig* j9JitConfig) = 0; }; #endif //JITSERVERLOGGER_BASEPERSISTENTLOGGER_H diff --git a/runtime/compiler/control/CassandraLogger.cpp b/runtime/compiler/control/CassandraLogger.cpp index da007e4b714..95429935926 100644 --- a/runtime/compiler/control/CassandraLogger.cpp +++ b/runtime/compiler/control/CassandraLogger.cpp @@ -1,7 +1,5 @@ -#include #include #include "CassandraLogger.hpp" -#include "j9.h" #include "LoadDBLibs.hpp" CassandraLogger::CassandraLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName): BasePersistentLogger(databaseIP, databasePort, databaseName) @@ -112,7 +110,7 @@ bool CassandraLogger::connect() } -bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const char *logContent) +bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const char *logContent, J9JITConfig* j9JitConfig) { // create table space and table first if (!createKeySpace()) @@ -147,21 +145,8 @@ bool CassandraLogger::logMethod(const char *method, uint64_t clientID, const cha Ocass_statement_free(statement); return false; } - - // J9PortLibraryVersion portLibraryVersion; - // J9PortLibrary portLibrary; - // J9PORT_SET_VERSION(&portLibraryVersion, J9PORT_CAPABILITY_MASK); - // if (j9port_init_library(&portLibrary, &portLibraryVersion, sizeof(J9PortLibrary)) != 0) - // { - // fprintf(stderr, "Persistent Logging - Cassandra Database Init J9port Library Error\n"); - // Ocass_statement_free(statement); - // return false; - // } - // UDATA success = 0; - // PORT_ACCESS_FROM_PORT(&portLibrary); - // uint64_t current_time = j9time_current_time_nanos(&success); - // printf("what is my time here %lu\n",current_time); - time_t now = time(NULL); /* Time in seconds from Epoch */ + PORT_ACCESS_FROM_JITCONFIG(j9JitConfig); + uint64_t now = j9time_current_time_millis() / 1000; /* Time in seconds from Epoch */ /* Converts the time since the Epoch in seconds to the 'date' type */ Ocass_uint32_t year_month_day_of_insertion = Ocass_date_from_epoch(now); /* Converts the time since the Epoch in seconds to the 'time' type */ diff --git a/runtime/compiler/control/CassandraLogger.hpp b/runtime/compiler/control/CassandraLogger.hpp index 2f19d03a6c9..6c7b4a80d74 100644 --- a/runtime/compiler/control/CassandraLogger.hpp +++ b/runtime/compiler/control/CassandraLogger.hpp @@ -17,7 +17,7 @@ class CassandraLogger : public BasePersistentLogger CassandraLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName, const char *databaseUsername, const char *databasePassword); CassandraLogger(const char *databaseIP, uint32_t databasePort, const char *databaseName); - bool logMethod(const char *method, uint64_t clientID, const char *logContent) override; + bool logMethod(const char *method, uint64_t clientID, const char *logContent, J9JITConfig* j9JitConfig) override; }; #endif // CASSANDRALOGGER_H \ No newline at end of file diff --git a/runtime/compiler/control/JITServerCompilationThread.cpp b/runtime/compiler/control/JITServerCompilationThread.cpp index 1e699b39f10..ab0f97d05f0 100644 --- a/runtime/compiler/control/JITServerCompilationThread.cpp +++ b/runtime/compiler/control/JITServerCompilationThread.cpp @@ -120,7 +120,7 @@ outOfProcessCompilationEnd( bool isConnected = logger.connect(); if (isConnected) { - if (!logger.logMethod(methodSignature, clientUID, logFileStr.c_str())) + if (!logger.logMethod(methodSignature, clientUID, logFileStr.c_str(),compInfoPT->getJitConfig())) fprintf(stderr, "JITServer: Persistent Logging Error - Database insert failed, skipping persistent logging."); logger.disconnect(); } diff --git a/runtime/compiler/control/MongoLogger.cpp b/runtime/compiler/control/MongoLogger.cpp index 8fb06733a8e..ace05753a42 100644 --- a/runtime/compiler/control/MongoLogger.cpp +++ b/runtime/compiler/control/MongoLogger.cpp @@ -147,7 +147,7 @@ void MongoLogger::disconnect() return; } -bool MongoLogger::logMethod(const char* method, uint64_t clientID, const char* logContent) +bool MongoLogger::logMethod(const char* method, uint64_t clientID, const char* logContent, J9JITConfig* j9JitConfig) { struct timespec t; clock_gettime(CLOCK_REALTIME, &t); diff --git a/runtime/compiler/control/MongoLogger.hpp b/runtime/compiler/control/MongoLogger.hpp index 05e9186e34b..be5fc177e97 100644 --- a/runtime/compiler/control/MongoLogger.hpp +++ b/runtime/compiler/control/MongoLogger.hpp @@ -52,7 +52,7 @@ class MongoLogger : public BasePersistentLogger ~MongoLogger(); - bool logMethod(const char* method, uint64_t clientID, const char* logContent) override; + bool logMethod(const char* method, uint64_t clientID, const char* logContent, J9JITConfig* j9JitConfig) override; }; #endif //MONGOLOGGER_HPP