diff --git a/.hgtags b/.hgtags index 575470bdd00..9d9472b8350 100644 --- a/.hgtags +++ b/.hgtags @@ -648,3 +648,5 @@ f143729ca00ec14a98ea5c7f73acba88da97746e jdk-15+23 4a485c89d5a08b495961835f5308a96038678aeb jdk-16+1 06c9f89459daba98395fad726100feb44f89ba71 jdk-15+28 bcbe7b8a77b8971bc221c0be1bd2abb6fb68c2d0 jdk-16+2 +b58fc60580550a4a587cab729d8fd87223ad6932 jdk-15+29 +76810b3a88c8c641ae3850a8dfd7c40c984aea9d jdk-16+3 diff --git a/bin/nashorn/fixwhitespace.sh b/bin/nashorn/fixwhitespace.sh deleted file mode 100644 index d3274700f71..00000000000 --- a/bin/nashorn/fixwhitespace.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -fix() { - #convert tabs to spaces - find . -name $1 -exec sed -i "" 's/ / /g' {} \; - #remove trailing whitespace - find . -name $1 -exec sed -i "" 's/[ ]*$//' \{} \; -} - -if [ ! -z $1 ]; then - fix $1; -else - fix "*.java" - fix "*.js" -fi diff --git a/bin/nashorn/runopt.sh b/bin/nashorn/runopt.sh deleted file mode 100644 index bc99095721d..00000000000 --- a/bin/nashorn/runopt.sh +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -########################################################################################### -# This is a helper script to evaluate nashorn with optimistic types -# it produces a flight recording for every run, and uses the best -# known flags for performance for the current configration -########################################################################################### - -# Flags to enable assertions, we need the system assertions too, since -# this script runs Nashorn in the BCP to override any nashorn.jar that might -# reside in your $JAVA_HOME/jre/lib/ext/nashorn.jar -# -ENABLE_ASSERTIONS_FLAGS="-ea -esa" - -# Flags to instrument lambdaform computation, caching, interpretation and compilation -# Default compile threshold for lambdaforms is 30 -# -#LAMBDAFORM_FLAGS="\ -# -Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 \ -# -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true \ -# -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true \ -# -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true" - -# Flags to run trusted tests from the Nashorn test suite -# -#TRUSTED_TEST_FLAGS="\ -#-Djava.security.manager \ -#-Djava.security.policy=../build/nashorn.policy -Dnashorn.debug" - -# Testing out new code optimizations using the generic hotspot "new code" parameter -# -#USE_NEW_CODE_FLAGS=-XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode - -# -#-Dnashorn.typeInfo.disabled=false \ -# and for Nashorn options: -# --class-cache-size=0 --persistent-code-cache=false - -# Unique timestamped file name for JFR recordings. For JFR, we also have to -# crank up the stack cutoff depth to 1024, because of ridiculously long lambda form -# stack traces. -# -# It is also recommended that you go into $JAVA_HOME/jre/lib/jfr/default.jfc and -# set the "method-sampling-interval" Normal and Maximum sample time as low as you -# can go (10 ms on most platforms). The default is normally higher. The increased -# sampling overhead is usually negligible for Nashorn runs, but the data is better - -if [ -z $JFR_FILENAME ]; then - JFR_FILENAME="./nashorn_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr" -fi - -# Flight recorder -# -# see above - already in place, copy the flags down here to disable -ENABLE_FLIGHT_RECORDER_FLAGS="\ - -XX:+FlightRecorder \ - -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$JFR_FILENAME,stackdepth=1024" - -# Type specialization and math intrinsic replacement should be enabled by default in 8u20 and nine, -# keeping this flag around for experimental reasons. Replace + with - to switch it off -# -#ENABLE_TYPE_SPECIALIZATION_FLAGS=-XX:+UseTypeSpeculation - -# Same with math intrinsics. They should be enabled by default in 8u20 and 9, so -# this disables them if needed -# -#DISABLE_MATH_INTRINSICS_FLAGS=-XX:-UseMathExactIntrinsics - -# Add timing to time the compilation phases. -#ENABLE_TIME_FLAGS=--log=time - -# Add ShowHiddenFrames to get lambda form internals on the stack traces -#ENABLE_SHOW_HIDDEN_FRAMES_FLAGS=-XX:+ShowHiddenFrames - -# Add print optoassembly to get an asm dump. This requires 1) a debug build, not product, -# That tired compilation is switched off, for C2 only output and that the number of -# compiler threads is set to 1 for determinsm. -# -#PRINT_ASM_FLAGS=-XX:+PrintOptoAssembly -XX:-TieredCompilation -XX:CICompilerCount=1 \ - -# Tier compile threasholds. Default value is 10. (1-100 is useful for experiments) -#TIER_COMPILATION_THRESHOLD_FLAGS=-XX:IncreaseFirstTierCompileThresholdAt=10 - -# Directory where to look for nashorn.jar in a dist folder. The default is "..", assuming -# that we run the script from the make dir -DIR=.. -NASHORN_JAR=$DIR/dist/nashorn.jar - - -# The built Nashorn jar is placed first in the bootclasspath to override the JDK -# nashorn.jar in $JAVA_HOME/jre/lib/ext. Thus, we also need -esa, as assertions in -# nashorn count as system assertions in this configuration - -# Type profiling default level is 111, 222 adds some compile time, but is faster - -$JAVA_HOME/bin/java \ -$ENABLE_ASSERTIONS_FLAGS \ -$LAMBDAFORM_FLAGS \ -$TRUSTED_FLAGS \ -$USE_NEW_CODE_FLAGS \ -$ENABLE_SHOW_HIDDEN_FRAMES_FLAGS \ -$ENABLE_FLIGHT_RECORDER_FLAGS \ -$ENABLE_TYPE_SPECIALIZATION_FLAGS \ -$TIERED_COMPILATION_THRESOLD_FLAGS \ -$DISABLE_MATH_INTRINSICS_FLAGS \ -$PRINT_ASM_FLAGS \ --Xbootclasspath/p:$NASHORN_JAR \ --Xms2G -Xmx2G \ --XX:TypeProfileLevel=222 \ --cp $CLASSPATH:../build/test/classes/ \ -jdk.nashorn.tools.Shell $ENABLE_TIME_FLAGS ${@} - - diff --git a/doc/nashorn/DEVELOPER_README b/doc/nashorn/DEVELOPER_README deleted file mode 100644 index 78f50823494..00000000000 --- a/doc/nashorn/DEVELOPER_README +++ /dev/null @@ -1,631 +0,0 @@ -This document describes system properties that are used for internal -debugging and instrumentation purposes, along with the system loggers, -which are used for the same thing. - -This document is intended as a developer resource, and it is not -needed as Nashorn documentation for normal usage. Flags and system -properties described herein are subject to change without notice. - -===================================== -1. System properties used internally -===================================== - -This documentation of the system property flags assume that the -default value of the flag is false, unless otherwise specified. - -SYSTEM PROPERTY: -Dnashorn.args= - -This property takes as its value a space separated list of Nashorn -command line options that should be passed to Nashorn. This might be -useful in environments where it is hard to tell how a nashorn.jar is -launched. - -Example: - -> java -Dnashorn.args="--lazy-complation --log=compiler" large-java-app-with-nashorn.jar -> ant -Dnashorn.args="--log=codegen" antjob - -SYSTEM PROPERTY: -Dnashorn.args.prepend= - -This property behaves like nashorn.args, but adds the given arguments -before the existing ones instead of after them. Later arguments will -overwrite earlier ones, so this is useful for setting default arguments -that can be overwritten. - - -SYSTEM PROPERTY: -Dnashorn.unstable.relink.threshold=x - -NOTE: This property is deprecated in favor of the -"--unstable-relink-threshold" command line option. It controls how many -call site misses are allowed before a callsite is relinked with "apply" -semantics to never change again. In the case of megamorphic callsites, -this is necessary, or the program would spend all its time swapping out -callsite targets. When neither the system property nor the command line -option are specified, defaults to 8, or 16 with optimistic types turned -on. - - -SYSTEM PROPERTY: -Dnashorn.compiler.splitter.threshold=x - -This will change the node weight that requires a subgraph of the IR to -be split into several classes in order not to run out of bytecode space. -The default value is 0x8000 (32768). - - -SYSTEM PROPERTY: -Dnashorn.serialize.compression= - -This property sets the compression level used when deflating serialized -AST structures of anonymous split functions. Valid values range from 0 to 9, -the default value is 4. Higher values will reduce memory size of serialized -AST but increase CPU usage required for compression. - - -SYSTEM PROPERTY: -Dnashorn.codegen.debug.trace= - -See the description of the codegen logger below. - - -SYSTEM PROPERTY: -Dnashorn.fields.objects, -Dnashorn.fields.dual - -When the nashorn.fields.objects property is true, Nashorn will always -use object fields for AccessorProperties, requiring boxing for all -primitive property values. When nashorn.fields.dual is set, Nashorn -will always use dual long/object fields, which allows primitives to be -stored without boxing. When neither system property is set, Nashorn -chooses a setting depending on the optimistic types setting (dual -fields when optimistic types are enabled, object-only fields otherwise). - -With dual fields, Nashorn uses long fields to store primitive values. -Ints are represented as the 32 low bits of the long fields. Doubles -are represented as the doubleToLongBits of their value. This way a -single field can be used for all primitive types. Packing and -unpacking doubles to their bit representation is intrinsified by -the JVM and extremely fast. - -In the future, this might complement or be replaced by experimental -feature sun.misc.TaggedArray, which has been discussed on the mlvm -mailing list. TaggedArrays are basically a way to share data space -between primitives and references, and have the GC understand this. - - -SYSTEM PROPERTY: -Dnashorn.compiler.symbol.trace=[[,*]], - -Dnashorn.compiler.symbol.stacktrace=[[,*]] - -When this property is set, creation and manipulation of any symbol -named "x" will show information about when the compiler changes its -type assumption, bytecode local variable slot assignment and other -data. This is useful if, for example, a symbol shows up as an Object, -when you believe it should be a primitive. Usually there is an -explanation for this, for example that it exists in the global scope -and type analysis has to be more conservative. - -Several symbols names to watch can be specified by comma separation. - -If no variable name is specified (and no equals sign), all symbols -will be watched - -By using "stacktrace" instead of or together with "trace", stack -traces will be displayed upon symbol changes according to the same -semantics. - - -SYSTEM PROPERTY: -Dnashorn.lexer.xmlliterals - -If this property it set, it means that the Lexer should attempt to -parse XML literals, which would otherwise generate syntax -errors. Warning: there are currently no unit tests for this -functionality. - -XML literals, when this is enabled, end up as standard LiteralNodes in -the IR. - - -SYSTEM_PROPERTY: -Dnashorn.debug - -If this property is set to true, Nashorn runs in Debug mode. Debug -mode is slightly slower, as for example statistics counters are enabled -during the run. Debug mode makes available a NativeDebug instance -called "Debug" in the global space that can be used to print property -maps and layout for script objects, as well as a "dumpCounters" method -that will print the current values of the previously mentioned stats -counters. - -These functions currently exists for Debug: - -"map" - print(Debug.map(x)) will dump the PropertyMap for object x to -stdout (currently there also exist functions called "embedX", where X -is a value from 0 to 3, that will dump the contents of the embed pool -for the first spill properties in any script object and "spill", that -will dump the contents of the growing spill pool of spill properties -in any script object. This is of course subject to change without -notice, should we change the script object layout. - -"methodHandle" - this method returns the method handle that is used -for invoking a particular script function. - -"identical" - this method compares two script objects for reference -equality. It is a == Java comparison - -"equals" - Returns true if two objects are either referentially -identical or equal as defined by java.lang.Object.equals. - -"dumpCounters" - will dump the debug counters' current values to -stdout. - -Currently we count number of ScriptObjects in the system, number of -Scope objects in the system, number of ScriptObject listeners added, -removed and dead (without references). - -We also count number of ScriptFunctions, ScriptFunction invocations -and ScriptFunction allocations. - -Furthermore we count PropertyMap statistics: how many property maps -exist, how many times were property maps cloned, how many times did -the property map history cache hit, prevent new allocations, how many -prototype invalidations were done, how many time the property map -proto cache hit. - -Finally we count callsite misses on a per callsite bases, which occur -when a callsite has to be relinked, due to a previous assumption of -object layout being invalidated. - -"getContext" - return the current Nashorn context. - -"equalWithoutType" - Returns true if if the two objects are both -property maps, and they have identical properties in the same order, -but allows the properties to differ in their types. - -"diffPropertyMaps" Returns a diagnostic string representing the difference -of two property maps. - -"getClass" - Returns the Java class of an object, or undefined if null. - -"toJavaString" - Returns the Java toString representation of an object. - -"toIdentString" - Returns a string representation of an object consisting -of its java class name and hash code. - -"getListenerCount" - Return the number of property listeners for a -script object. - -"getEventQueueCapacity" - Get the capacity of the event queue. - -"setEventQueueCapacity" - Set the event queue capacity. - -"addRuntimeEvent" - Add a runtime event to the runtime event queue. -The queue has a fixed size (see -Dnashorn.runtime.event.queue.size) -and the oldest entry will be thrown out of the queue is about to overflow. - -"expandEventQueueCapacity" - Expands the event queue capacity, -or truncates if capacity is lower than current capacity. Then only -the newest entries are kept. - -"clearRuntimeEvents" - Clear the runtime event queue. - -"removeRuntimeEvent" - Remove a specific runtime event from the event queue. - -"getRuntimeEvents" - Return all runtime events in the queue as an array. - -"getLastRuntimeEvent" - Return the last runtime event in the queue. - - -SYSTEM PROPERTY: -Dnashorn.methodhandles.debug.stacktrace - -This enhances methodhandles logging (see below) to also dump the -stack trace for every instrumented method handle operation. -Warning: This is enormously verbose, but provides a pretty -decent "grep:able" picture of where the calls are coming from. - - -SYSTEM PROPERTY: -Dnashorn.cce - -Setting this system property causes the Nashorn linker to rely on -ClassCastExceptions for triggering a callsite relink. If not set, the linker -will add an explicit instanceof guard. - - -SYSTEM PROPERTY: -Dnashorn.spill.threshold= - -This property sets the number of fields in an object from which to use -generic array based spill storage instead of Java fields. The default value -is 256. - - -SYSTEM PROPERTY: -Dnashorn.tcs.miss.samplePercent= - -When running with the trace callsite option (-tcs), Nashorn will count -and instrument any callsite misses that require relinking. As the -number of relinks is large and usually produces a lot of output, this -system property can be used to constrain the percentage of misses that -should be logged. Typically this is set to 1 or 5 (percent). 1% is the -default value. - -SYSTEM PROPERTY: -Dnashorn.persistent.code.cache - -This property can be used to set the directory where Nashorn stores -serialized script classes generated with the -pcc/--persistent-code-cache -option. The default directory name is "nashorn_code_cache". - - -SYSTEM PROPERTY: -Dnashorn.typeInfo.maxFiles - -Maximum number of files to store in the type info cache. The type info cache -is used to cache type data of JavaScript functions when running with -optimistic types (-ot/--optimistic-types). There is one file per JavaScript -function in the cache. - -The default value is 0 which means the feature is disabled. Setting this -to something like 20000 is probably good enough for most applications and -will usually cap the cache directory to about 80MB presuming a 4kB -filesystem allocation unit. Set this to "unlimited" to run without limit. - -If the value is not 0 or "unlimited", Nashorn will spawn a cleanup thread -that makes sure the number of files in the cache does not exceed the given -value by deleting the least recently modified files. - - -SYSTEM PROPERTY: -Dnashorn.typeInfo.cacheDir - -This property can be used to set the directory where Nashorn stores the -type info cache when -Dnashorn.typeInfo.maxFiles is set to a nonzero -value. The default location is platform specific. On Windows, it is -"${java.io.tmpdir}\com.oracle.java.NashornTypeInfo". On Linux and -Solaris it is "~/.cache/com.oracle.java.NashornTypeInfo". On Mac OS X, -it is "~/Library/Caches/com.oracle.java.NashornTypeInfo". - - -SYSTEM PROPERTY: -Dnashorn.typeInfo.cleanupDelaySeconds= - -This sets the delay between cleanups of the typeInfo cache, in seconds. -The default delay is 20 seconds. - - -SYSTEM PROPERTY: -Dnashorn.profilefile= - -When running with the profile callsite options (-pcs), Nashorn will -dump profiling data for all callsites to stderr as a shutdown hook. To -instead redirect this to a file, specify the path to the file using -this system property. - - -SYSTEM_PROPERTY: -Dnashorn.regexp.impl=[jdk|joni] - -This property defines the regular expression engine to be used by -Nashorn. Set this flag to "jdk" to get an implementation based on the -JDK's java.util.regex package. Set this property to "joni" to install -an implementation based on Joni, the regular expression engine used by -the JRuby project. The default value for this flag is "joni" - -SYSTEM PROPERTY: -Dnashorn.runtime.event.queue.size= - -Nashorn provides a fixed sized runtime event queue for debugging purposes. -See -Dnashorn.debug for methods to access the event queue. -The default value is 1024. - -SYSTEM PROPERTY: -Dnashorn.anonymous.classes.threshold= - -Nashorn can use anonymous classes for loading compiled scripts, depending -on the --anonymous-classes=[auto|true|false] option. Anonymous classes load -faster, but the loaded classes get less optimization applied to them and -therefore usually run slower. In the default "auto" setting, scripts are -loaded as anonymous classes if the script size does not exceed 512 bytes. -The above system property allows to set this threshold to a user defined -value. - -=============== -2. The loggers. -=============== - -It is very simple to create your own logger. Use the DebugLogger class -and give the subsystem name as a constructor argument. - -The Nashorn loggers can be used to print per-module or per-subsystem -debug information with different levels of verbosity. The loggers for -a given subsystem are available are enabled by using - ---log=[:] - -on the command line. - -Here identifies the name of the subsystem to be logged -and the optional colon and level argument is a standard -java.util.logging.Level name (severe, warning, info, config, fine, -finer, finest). If the level is left out for a particular subsystem, -it defaults to "info". Any log message logged as the level or a level -that is more important will be output to stderr by the logger. - -Several loggers can be enabled by a single command line option, by -putting a comma after each subsystem/level tuple (or each subsystem if -level is unspecified). The --log option can also be given multiple -times on the same command line, with the same effect. - -For example: --log=codegen,fields:finest is equivalent to ---log=codegen:info --log=fields:finest - -The following is an incomplete list of subsystems that currently -support logging. Look for classes implementing -jdk.nashorn.internal.runtime.logging.Loggable for more loggers. - - -* compiler - -The compiler is in charge of turning source code and function nodes -into byte code, and installs the classes into a class loader -controlled from the Context. Log messages are, for example, about -things like new compile units being allocated. The compiler has global -settings that all the tiers of codegen (e.g. Lower and CodeGenerator) -use.s - - -* recompile - -This logger shows information about recompilation of scripts and -functions at runtime. Recompilation may happen because a function -was called with different parameter types, or because an optimistic -assumption failed while executing a function with -ot/--optimistic-types. - - -* codegen - -The code generator is the emitter stage of the code pipeline, and -turns the lowest tier of a FunctionNode into bytecode. Codegen logging -shows byte codes as they are being emitted, line number information -and jumps. It also shows the contents of the bytecode stack prior to -each instruction being emitted. This is a good debugging aid. For -example: - -[codegen] #41 line:2 (f)_afc824e -[codegen] #42 load symbol x slot=2 -[codegen] #43 {1:O} load int 0 -[codegen] #44 {2:I O} dynamic_runtime_call GT:ZOI_I args=2 returnType=boolean -[codegen] #45 signature (Ljava/lang/Object;I)Z -[codegen] #46 {1:Z} ifeq ternary_false_5402fe28 -[codegen] #47 load symbol x slot=2 -[codegen] #48 {1:O} goto ternary_exit_107c1f2f -[codegen] #49 ternary_false_5402fe28 -[codegen] #50 load symbol x slot=2 -[codegen] #51 {1:O} convert object -> double -[codegen] #52 {1:D} neg -[codegen] #53 {1:D} convert double -> object -[codegen] #54 {1:O} ternary_exit_107c1f2f -[codegen] #55 {1:O} return object - -shows a ternary node being generated for the sequence "return x > 0 ? -x : -x" - -The first number on the log line is a unique monotonically increasing -emission id per bytecode. There is no guarantee this is the same id -between runs. depending on non deterministic code -execution/compilation, but for small applications it usually is. If -the system variable -Dnashorn.codegen.debug.trace= is set, where x -is a bytecode emission id, a stack trace will be shown as the -particular bytecode is about to be emitted. This can be a quick way to -determine where it comes from without attaching the debugger. "Who -generated that neg?" - -The --log=codegen option is equivalent to setting the system variable -"nashorn.codegen.debug" to true. - -* fold - -Shows constant folding taking place before lowering - -* lower - -This is the first lowering pass. - -Lower is a code generation pass that turns high level IR nodes into -lower level one, for example substituting comparisons to RuntimeNodes -and inlining finally blocks. - -Lower is also responsible for determining control flow information -like end points. - -* symbols - -The symbols logger tracks the assignment os symbols to identifiers. - -* scopedepths - -This logs the calculation of scope depths for non-local symbols. - -* fields - -The --log=fields option (at info level) is equivalent to setting the -system variable "nashorn.fields.debug" to true. At the info level it -will only show info about type assumptions that were invalidated. If -the level is set to finest, it will also trace every AccessorProperty -getter and setter in the program, show arguments, return values -etc. It will also show the internal representation of respective field -(Object in the normal case, unless running with the dual field -representation) - -* time - -This enables timers for various phases of script compilation. The timers -will be dumped when the Nashorn process exits. We see a percentage value -of how much time was spent not executing bytecode (i.e. compilation and -internal tasks) at the end of the report. - -A finer level than "info" will show individual compilation timings as they -happen. - -Here is an example: - -[time] Accumulated complation phase Timings: -[time] -[time] 'JavaScript Parsing' 1076 ms -[time] 'Constant Folding' 159 ms -[time] 'Control Flow Lowering' 303 ms -[time] 'Program Point Calculation' 282 ms -[time] 'Builtin Replacement' 71 ms -[time] 'Code Splitting' 670 ms -[time] 'Symbol Assignment' 474 ms -[time] 'Scope Depth Computation' 249 ms -[time] 'Optimistic Type Assignment' 186 ms -[time] 'Local Variable Type Calculation' 526 ms -[time] 'Bytecode Generation' 5177 ms -[time] 'Class Installation' 1854 ms -[time] -[time] Total runtime: 11994 ms (Non-runtime: 11027 ms [91%]) - -* methodhandles - -If this logger is enabled, each MethodHandle related call that uses -the java.lang.invoke package gets its MethodHandle intercepted and an -instrumentation printout of arguments and return value appended to -it. This shows exactly which method handles are executed and from -where. (Also MethodTypes and SwitchPoints). - -* classcache - -This logger shows information about reusing code classes using the -in-memory class cache. Nashorn will try to avoid compilation of -scripts by using existing classes. This can significantly improve -performance when repeatedly evaluating the same script. - -======================= -3. Undocumented options -======================= - -Here follows a short description of undocumented options for Nashorn. -To see a list of all undocumented options, use the (undocumented) flag -"-xhelp". - -i.e. jjs -xhelp or java -jar nashorn.jar -xhelp - -Undocumented options are not guaranteed to work, run correctly or be -bug free. They are experimental and for internal or debugging use. -They are also subject to change without notice. - -In practice, though, all options below not explicitly documented as -EXPERIMENTAL can be relied upon, for example --dump-on-error is useful -for any JavaScript/Nashorn developer, but there is no guarantee. - -A short summary follows: - - -D (-Dname=value. Set a system property. This option can be repeated.) - - -ccs, --class-cache-size (Size of the Class cache size per global scope.) - - -cp, -classpath (-cp path. Specify where to find user class files.) - - -co, --compile-only (Compile without running.) - param: [true|false] default: false - - -d, --dump-debug-dir (specify a destination directory to dump class files.) - param: - - --debug-lines (Generate line number table in .class files.) - param: [true|false] default: true - - --debug-locals (Generate local variable table in .class files.) - param: [true|false] default: false - - -doe, -dump-on-error (Dump a stack trace on errors.) - param: [true|false] default: false - - --early-lvalue-error (invalid lvalue expressions should be reported as early errors.) - param: [true|false] default: true - - --empty-statements (Preserve empty statements in AST.) - param: [true|false] default: false - - -fv, -fullversion (Print full version info of Nashorn.) - param: [true|false] default: false - - --function-statement-error (Report an error when function declaration is used as a statement.) - param: [true|false] default: false - - --function-statement-warning (Warn when function declaration is used as a statement.) - param: [true|false] default: false - - -fx (Launch script as an fx application.) - param: [true|false] default: false - - --global-per-engine (Use single Global instance per script engine instance.) - param: [true|false] default: false - - -h, -help (Print help for command line flags.) - param: [true|false] default: false - - --loader-per-compile (Create a new class loader per compile.) - param: [true|false] default: true - - -l, --locale (Set Locale for script execution.) - param: default: en-US - - --log (Enable logging of a given level for a given number of sub systems. - [for example: --log=fields:finest,codegen:info].) - param: ,* - - -nj, --no-java (Disable Java support.) - param: [true|false] default: false - - -nse, --no-syntax-extensions (Disallow non-standard syntax extensions.) - param: [true|false] default: false - - -nta, --no-typed-arrays (Disable typed arrays support.) - param: [true|false] default: false - - --parse-only (Parse without compiling.) - param: [true|false] default: false - - --print-ast (Print abstract syntax tree.) - param: [true|false] default: false - - -pc, --print-code (Print generated bytecode. If a directory is specified, nothing will - be dumped to stderr. Also, in that case, .dot files will be generated - for all functions or for the function with the specified name only.) - param: [dir:,function:] - - --print-lower-ast (Print lowered abstract syntax tree.) - param: [true|false] default: false - - -plp, --print-lower-parse (Print the parse tree after lowering.) - param: [true|false] default: false - - --print-no-newline (Print function will not print new line char.) - param: [true|false] default: false - - -pp, --print-parse (Print the parse tree.) - param: [true|false] default: false - - --print-symbols (Print the symbol table.) - param: [true|false] default: false - - -pcs, --profile-callsites (Dump callsite profile data.) - param: [true|false] default: false - - -scripting (Enable scripting features.) - param: [true|false] default: false - - --stderr (Redirect stderr to a filename or to another tty, e.g. stdout.) - param: - - --stdout (Redirect stdout to a filename or to another tty, e.g. stderr.) - param: - - -strict (Run scripts in strict mode.) - param: [true|false] default: false - - -t, -timezone (Set timezone for script execution.) - param: default: Europe/Stockholm - - -tcs, --trace-callsites (Enable callsite trace mode. Options are: miss [trace callsite misses] - enterexit [trace callsite enter/exit], objects [print object properties].) - param: [=[option,]*] - - -urt, --unstable-relink-threshold (Number of times a dynamic call site has to be relinked before it - is considered unstable, when the runtime will try to link it as - if it is megamorphic.) - - --verify-code (Verify byte code before running.) - param: [true|false] default: false - - -v, -version (Print version info of Nashorn.) - param: [true|false] default: false - - -xhelp (Print extended help for command line flags.) - param: [true|false] default: false - diff --git a/doc/nashorn/JavaScriptingProgrammersGuide.html b/doc/nashorn/JavaScriptingProgrammersGuide.html deleted file mode 100644 index ae56c3fadf6..00000000000 --- a/doc/nashorn/JavaScriptingProgrammersGuide.html +++ /dev/null @@ -1,988 +0,0 @@ - - - - -Java Scripting Programmer's Guide - - - - - - - - -
- -

Java Scripting Programmer's Guide

- -
- - - -

Who is the Java Scripting API For?

-Some useful characteristics of scripting languages -are: -
    -
  • Convenience: Most scripting languages are -dynamically typed. You can usually create new variables without -declaring the variable type, and you can reuse variables to store -objects of different types. Also, scripting languages tend to -perform many type conversions automatically, for example, -converting the number 10 to the text "10" as necessary.
  • -
  • Developing rapid prototypes: You can avoid the -edit-compile-run cycle and just use edit-run!
  • -
  • Application extension/customization: You can -"externalize" parts of your application - like configuration -scripts, business logic/rules and math expressions for financial -applications.
  • -
  • "Command line" shells for applications -for -debugging, runtime/deploy time configuration etc. Most applications -have a web-based GUI configuaration tool these days. But -sysadmins/deployers frequently prefer command line tools. Instead -of inventing ad-hoc scripting language for that purpose, a -"standard" scripting language can be used.
  • -
-

The JavaTM Scripting API -is a scripting language indepedent framework for using script -engines from Java code. With the Java Scripting API, it is possible -to write customizable/extendable applications in the Java language -and leave the customization scripting language choice to the end -user. The Java application developer need not choose the extension -language during development. If you write your application with -JSR-223 API, then your users can use any JSR-223 compliant -scripting language.

-
- -

Scripting Package

-

The Java Scripting functionality is in the javax.script -package. This is a relatively small, simple API. The starting point -of the scripting API is the ScriptEngineManager class. -A ScriptEngineManager object can discover script engines through -the jar file service discovery mechanism. It can also instantiate -ScriptEngine objects that interpret scripts written in a specific -scripting language. The simplest way to use the scripting API is as -follows:

-
    -
  1. Create a ScriptEngineManager -object.
  2. -
  3. Get a ScriptEngine object from the -manager.
  4. -
  5. Evaluate script using the ScriptEngine's -eval methods.
  6. -
-

Now, it is time to look at some sample code. While it is -not mandatory, it may be useful to know a bit of JavaScript to read -these examples.

-
- -

Examples

- -

"Hello, World"

-

From the ScriptEngineManager instance, we -request a JavaScript engine instance using -getEngineByName method. On the script engine, the -eval method is called to execute a given String as -JavaScript code! For brevity, in this as well as in subsequent -examples, we have not shown exception handling. There are checked -and runtime exceptions thrown from javax.script API. -Needless to say, you have to handle the exceptions -appropriately.

-
-
-// EvalScript.java
-
-import javax.script.*;
-public class EvalScript {
-    public static void main(String[] args) throws Exception {
-        // create a script engine manager
-        ScriptEngineManager factory = new ScriptEngineManager();
-        // create a JavaScript engine
-        ScriptEngine engine = factory.getEngineByName("nashorn");
-        // evaluate JavaScript code from String
-        engine.eval("print('Hello, World')");
-    }
-}
-
-
-
- -

Evaluating a Script File

-

In this example, we call the eval method that -accepts java.io.Reader for the input source. The -script read by the given reader is executed. This way it is -possible to execute scripts from files, URLs and resources by -wrapping the relevant input stream objects as readers.

-
-
-// EvalFile.java
-
-import javax.script.*;
-
-public class EvalFile {
-    public static void main(String[] args) throws Exception {
-        // create a script engine manager
-        ScriptEngineManager factory = new ScriptEngineManager();
-        // create JavaScript engine
-        ScriptEngine engine = factory.getEngineByName("nashorn");
-        // evaluate JavaScript code from given file - specified by first argument
-        engine.eval(new java.io.FileReader(args[0]));
-    }
-}
-
-
-Let us assume that we have the file named test.js with the -following text: -

-print("This is hello from test.js");
-
-
-We can run the above Java as -

-java EvalFile test.js
-
-
-
- -

Script Variables

-

When you embed script engines and scripts with your Java -application, you may want to expose your application objects as -global variables to scripts. This example demonstrates how you can -expose your application objects as global variables to a script. We -create a java.io.File in the application and expose -the same as a global variable with the name "file". The script can -access the variable - for example, it can call public methods on -it. Note that the syntax to access Java objects, methods and fields -is dependent on the scripting language. JavaScript supports the -most "natural" Java-like syntax.

-

-Nashorn script engine pre-defines two global variables named "context" -and "engine". The "context" variable is of type javax.script.ScriptContext -and refers to the current ScriptContext instance passed to script engine's -eval method. The "engine" variable is of type javax.script.ScriptEngine and -refers to the current nashorn script engine instance evaluating the script. -Both of these variables are non-writable, non-enumerable and non-configurable -- which implies script code can not write overwrite the value, for..loop iteration -on global object will not iterate these variables and these variables can not be -deleted by script. -


-// ScriptVars.java
-
-import javax.script.*;
-import java.io.*;
-
-public class ScriptVars { 
-    public static void main(String[] args) throws Exception {
-        ScriptEngineManager manager = new ScriptEngineManager();
-        ScriptEngine engine = manager.getEngineByName("nashorn");
-
-        File f = new File("test.txt");
-        // expose File object as variable to script
-        engine.put("file", f);
-
-        // evaluate a script string. The script accesses "file" 
-        // variable and calls method on it
-        engine.eval("print(file.getAbsolutePath())");
-    }
-}
-
-
-
-
- -

Invoking Script Functions and Methods

-

Sometimes you may want to call a specific scripting function -repeatedly - for example, your application menu functionality might -be implemented by a script. In your menu's action event handler you -may want to call a specific script function. The following example -demonstrates invoking a specific script function from Java -code.

-

-// InvokeScriptFunction.java
-
-import javax.script.*;
-
-public class InvokeScriptFunction {
-    public static void main(String[] args) throws Exception {
-        ScriptEngineManager manager = new ScriptEngineManager();
-        ScriptEngine engine = manager.getEngineByName("nashorn");
-
-        // JavaScript code in a String
-        String script = "function hello(name) { print('Hello, ' + name); }";
-        // evaluate script
-        engine.eval(script);
-
-        // javax.script.Invocable is an optional interface.
-        // Check whether your script engine implements it or not!
-        // Note that the JavaScript engine implements Invocable interface.
-        Invocable inv = (Invocable) engine;
-
-        // invoke the global function named "hello"
-        inv.invokeFunction("hello", "Scripting!!" );
-    }
-}
-
-
-
-

If your scripting language is object based (like JavaScript) or -object-oriented, then you can invoke a script method on a script -object.

-

-// InvokeScriptMethod.java
-
-import javax.script.*;
-
-public class InvokeScriptMethod {
-    public static void main(String[] args) throws Exception {
-        ScriptEngineManager manager = new ScriptEngineManager();
-        ScriptEngine engine = manager.getEngineByName("nashorn");
-
-        // JavaScript code in a String. This code defines a script object 'obj'
-        // with one method called 'hello'.        
-        String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
-        // evaluate script
-        engine.eval(script);
-
-        // javax.script.Invocable is an optional interface.
-        // Check whether your script engine implements or not!
-        // Note that the JavaScript engine implements Invocable interface.
-        Invocable inv = (Invocable) engine;
-
-        // get script object on which we want to call the method
-        Object obj = engine.get("obj");
-
-        // invoke the method named "hello" on the script object "obj"
-        inv.invokeMethod(obj, "hello", "Script Method !!" );
-    }
-}
-
-
-
-
- -

Implementing Java Interfaces by Scripts

-

Instead of calling specific script functions from Java, -sometimes it is convenient to implement a Java interface by script -functions or methods. Also, by using interfaces we can avoid having -to use the javax.script API in many places. We can get -an interface implementor object and pass it to various Java APIs. -The following example demonstrates implementing the -java.lang.Runnable interface with a script.

-

-// RunnableImpl.java
-
-import javax.script.*;
-
-public class RunnableImpl {
-    public static void main(String[] args) throws Exception {
-        ScriptEngineManager manager = new ScriptEngineManager();
-        ScriptEngine engine = manager.getEngineByName("nashorn");
-
-        // JavaScript code in a String
-        String script = "function run() { print('run called'); }";
-
-        // evaluate script
-        engine.eval(script);
-
-        Invocable inv = (Invocable) engine;
-
-        // get Runnable interface object from engine. This interface methods
-        // are implemented by script functions with the matching name.
-        Runnable r = inv.getInterface(Runnable.class);
-
-        // start a new thread that runs the script implemented
-        // runnable interface
-        Thread th = new Thread(r);
-        th.start();
-        th.join();
-    }
-}
-
-
-

If your scripting language is object-based or object-oriented, -it is possible to implement a Java interface by script methods on -script objects. This avoids having to call script global functions -for interface methods. The script object can store the "state" -associated with the interface implementor.

-

-// RunnableImplObject.java
-
-import javax.script.*;
-
-public class RunnableImplObject {
-    public static void main(String[] args) throws Exception {
-        ScriptEngineManager manager = new ScriptEngineManager();
-        ScriptEngine engine = manager.getEngineByName("nashorn");
-
-        // JavaScript code in a String
-        String script = "var obj = new Object(); obj.run = function() { print('run method called'); }";
-
-        // evaluate script
-        engine.eval(script);
-
-        // get script object on which we want to implement the interface with
-        Object obj = engine.get("obj");
-
-        Invocable inv = (Invocable) engine;
-
-        // get Runnable interface object from engine. This interface methods
-        // are implemented by script methods of object 'obj'
-        Runnable r = inv.getInterface(obj, Runnable.class);
-
-        // start a new thread that runs the script implemented
-        // runnable interface
-        Thread th = new Thread(r);
-        th.start();
-        th.join();
-    }
-}
-
-
-
- -

Multiple Scopes for Scripts

-

In the script variables example, we -saw how to expose application objects as script global variables. -It is possible to expose multiple global "scopes" for scripts. A -single scope is an instance of javax.script.Bindings. -This interface is derived from java.util.Map<String, -Object>. A scope a set of name-value pairs where name is -any non-empty, non-null String. -javax.script.ScriptContext interface supports multiple -scopes with associated Bindings for each -scope. By default, every script engine has a default script -context. The default script context has atleast one scope called -"ENGINE_SCOPE". Various scopes supported by a script context are -available through getScopes method.

-

-// MultiScopes.java
-
-import javax.script.*;
-
-public class MultiScopes {
-    public static void main(String[] args) throws Exception {
-        ScriptEngineManager manager = new ScriptEngineManager();
-        ScriptEngine engine = manager.getEngineByName("nashorn");
-
-        engine.put("x", "hello");
-        // print global variable "x"
-        engine.eval("print(x);");
-        // the above line prints "hello"
-
-        // Now, pass a different script context
-        ScriptContext newContext = new SimpleScriptContext();
-        newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
-        Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
-
-        // add new variable "x" to the new engineScope        
-        engineScope.put("x", "world");
-
-        // execute the same script - but this time pass a different script context
-        engine.eval("print(x);", newContext);
-        // the above line prints "world"
-    }
-}
-
-
-
-
- -

JavaScript Script Engine

-

Oracle's implementation of JDK 8 is co-bundled with the Nashorn ECMAScript -script engine. -


- -

JavaScript to Java Communication

-

For the most part, accessing Java classes, objects and methods -is straightforward. In particular field and method access from -JavaScript is the same as it is from Java. We highlight important -aspects of JavaScript Java access here. -The following examples are JavaScript snippets accessing Java. This -section requires knowledge of JavaScript. This section can be -skipped if you are planning to use some other JSR-223 scripting -language rather than JavaScript.

-
- -

Accessing Java Classes

-
-
-// javatypes.js
-
- var arrayListType = Java.type("java.util.ArrayList")
- var intType = Java.type("int")
- var stringArrayType = Java.type("java.lang.String[]")
- var int2DArrayType = Java.type("int[][]")
-
-
- -Note that the name of the type is always a string for a fully qualified name. You can use any of these expressions to create new instances, e.g.: - -

- var anArrayList = new (Java.type("java.util.ArrayList"))
-
- -or - -

- var ArrayList = Java.type("java.util.ArrayList")
- var anArrayList = new ArrayList
- var anArrayListWithSize = new ArrayList(16)
-
- -In the special case of inner classes, you can either use the JVM fully qualified name, meaning using the dollar sign in the class name, or you can use the dot: - -

- var ftype = Java.type("java.awt.geom.Arc2D$Float")
-
- -and - -

- var ftype = Java.type("java.awt.geom.Arc2D.Float")
-
- -both work. Note however that using the dollar sign is faster, as Java.type first tries to resolve the class name as it is originally specified, and the internal JVM names for inner classes use the dollar sign. If you use the dot, Java.type will internally get a ClassNotFoundException and subsequently retry by changing the last dot to dollar sign. As a matter of fact, it'll keep replacing dots with dollar signs until it either successfully loads the class or runs out of all dots in the name. This way it can correctly resolve and load even multiply nested inner classes with the dot notation. Again, this will be slower than using the dollar signs in the name. An alternative way to access the inner class is as a property of the outer class: - -

- var arctype = Java.type("java.awt.geom.Arc2D")
- var ftype = arctype.Float
-
-

-You can access both static and non-static inner classes. If you want to create an instance of a non-static inner class, remember to pass an instance of its outer class as the first argument to the constructor. -

-

-In addition to creating new instances, the type objects returned from Java.type calls can also be used to access the -static fields and methods of the classes: -


- var File = Java.type("java.io.File")
- File.createTempFile("nashorn", ".tmp")
-
-

-Methods with names of the form isXxx(), getXxx(), and setXxx() can also be used as properties, for both instances and statics. -

-

-A type object returned from Java.type is distinct from a java.lang.Class object. You can obtain one from the other using properties class and static on them. -


- var ArrayList = Java.type("java.util.ArrayList")
- var a = new ArrayList
-
- // All of the following print true:
- print("Type acts as target of instanceof: " + (a instanceof ArrayList))
- print("Class doesn't act as target of instanceof: " + !(a instanceof a.getClass()))
- print("Type is not same as instance's getClass(): " + (a.getClass() !== ArrayList))
- print("Type's `class` property is same as instance getClass(): " + (a.getClass() === ArrayList.class))
- print("Type is same as instance getClass()'s `static` property: " + (a.getClass().static === ArrayList))
-
-

-You can think of the type object as similar to the class names as used in Java source code: you use them as the -arguments to the new and instanceof operators and as the namespace for the static fields -and methods, but they are different than the runtime Class objects returned by getClass() calls. -Syntactically and semantically, this separation produces code that is most similar to Java code, where a distinction -between compile-time class expressions and runtime class objects also exists. (Also, Java can't have the equivalent of static -property on a Class object since compile-time class expressions are never reified as objects). -

-
- -

Importing Java Packages, Classes

-

The built-in functions importPackage (in compatibility script) and -importClass can be used to import Java packages and -classes.

-

-
-// importpackageclass.js
-
-// load compatibility script
-load("nashorn:mozilla_compat.js");
-// Import Java packages and classes 
-// like import package.*; in Java
-importPackage(java.awt);
-// like import java.awt.Frame in Java
-importClass(java.awt.Frame);
-// Create Java Objects by "new ClassName"
-var frame = new java.awt.Frame("hello");
-// Call Java public methods from script
-frame.setVisible(true);
-// Access "JavaBean" properties like "fields"
-print(frame.title);
-
-
-

The Packages global variable can -be used to access Java packages. Examples: -Packages.java.util.Vector, -Packages.javax.swing.JFrame. Please note that "java" -is a shortcut for "Packages.java". There are equivalent shortcuts -for javax, org, edu, com, net prefixes, so pratically all JDK -platform classes can be accessed without the "Packages" prefix.

-

Note that java.lang is not imported by default (unlike Java) -because that would result in conflicts with JavaScript's built-in -Object, Boolean, Math and so on.

-

importPackage and importClass -functions "pollute" the global variable scope of JavaScript. To -avoid that, you may use JavaImporter.

-

-
-// javaimporter.js
-
-// create JavaImporter with specific packages and classes to import
-
-var SwingGui = new JavaImporter(javax.swing,
-                            javax.swing.event,
-                            javax.swing.border,
-                            java.awt.event);
-with (SwingGui) {
-    // within this 'with' statement, we can access Swing and AWT
-    // classes by unqualified (simple) names.
-
-    var mybutton = new JButton("test");
-    var myframe = new JFrame("test");
-}
-
-
-
-
- -

Creating, Converting and Using Java Arrays

-

-Array element access or length access is the same as in Java.

-

-// javaarray.js
-
-// create Java String array of 5 elements
-var StringArray = Java.type("java.lang.String[]");
-var a = new StringArray(5);
-
-// Accessing elements and length access is by usual Java syntax
-a[0] = "scripting is great!";
-print(a.length);
-print(a[0]);
-
-
-

-It is also possible to convert between JavaScript and Java arrays. -Given a JavaScript array and a Java type, Java.to returns a Java array with the same initial contents, and with the specified array type. -

-

- var anArray = [1, "13", false]
- var javaIntArray = Java.to(anArray, "int[]")
- print(javaIntArray[0]) // prints 1
- print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
- print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
-
-

-You can use either a string or a type object returned from Java.type() to specify the type of the array. -You can also omit the array type, in which case a Object[] will be created. -

-

-Given a Java array or Collection, Java.from returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method. -

-

-var File = Java.type("java.io.File");
-var listCurDir = new File(".").listFiles();
-var jsList = Java.from(listCurDir);
-print(jsList);
-
-
- -

Implementing Java interfaces

-

A Java interface can be implemented in JavaScript by using a -Java anonymous class-like syntax:

-

-// runnable.js
-
-var r  = new java.lang.Runnable() {
-    run: function() {
-        print("running...\n");
-    }
-};
-
-// "r" can be passed to Java methods that expect java.lang.Runnable
-var th = new java.lang.Thread(r);
-th.start();
-th.join();
-
-
-

When an interface with a single method is expected, you can pass -a script function directly.(auto conversion)

-

-// samfunc.js
-
-function func() {
-     print("I am func!");
-}
-
-// pass script function for java.lang.Runnable argument
-var th = new java.lang.Thread(func);
-th.start();
-th.join();
-
-
-
- -

Extending Abstract Java Classes

-

-If a Java class is abstract, you can instantiate an anonymous subclass of it using an argument list that is applicable to any of its public or protected constructors, but inserting a JavaScript object with functions properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the JavaScript function will provide implementation for all overloads. E.g.: -

- -

- var TimerTask =  Java.type("java.util.TimerTask")
- var task = new TimerTask({ run: function() { print("Hello World!") } })
-
- -Nashorn supports a syntactic extension where a "new" expression followed by an argument is identical to invoking the constructor and passing the argument to it, so you can write the above example also as: - -

- var task = new TimerTask {
-     run: function() {
-       print("Hello World!")
-     }
- }
-
- -which is very similar to Java anonymous inner class definition. On the other hand, if the type is an abstract type with a single abstract method (commonly referred to as a "SAM type") or all abstract methods it has share the same overloaded name), then instead of an object, you can just pass a function, so the above example can become even more simplified to: - -

- var task = new TimerTask(function() { print("Hello World!") })
-
- -

-Note that in every one of these cases if you are trying to instantiate an abstract class that has constructors that take some arguments, you can invoke those simply by specifying the arguments after the initial implementation object or function. -

-

-The use of functions can be taken even further; if you are invoking a Java method that takes a SAM type, you can just pass in a function object, and Nashorn will know what you meant: -

-
- Java.type("java.util.Timer")
- timer.schedule(function() { print("Hello World!") })
-
- -Here, Timer.schedule() expects a TimerTask as its argument, so Nashorn creates an instance of a TimerTask subclass and uses the passed function to implement its only abstract method, run(). In this usage though, you can't use non-default constructors; the type must be either an interface, or must have a protected or public no-arg constructor. - -
- -

Extending Concrete Java Classes

-

-To extend a concrete Java class, you have to use Java.extend function. -Java.extend returns a type object for a subclass of the specified Java class (or implementation of the specified interface) that acts as a script-to-Java adapter for it. -

-

-// javaextend.js
-
-var ArrayList = Java.type("java.util.ArrayList")
-var ArrayListExtender = Java.extend(ArrayList)
-var printSizeInvokedArrayList = new ArrayListExtender() {
-    size: function() { print("size invoked!"); }
-}
-var printAddInvokedArrayList = new ArrayListExtender() {
-    add: function(x, y) {
-        if(typeof(y) === "undefined") {
-            print("add(e) invoked!");
-        } else {
-            print("add(i, e) invoked!");
-        }
-    }
-};
-printSizeInvokedArrayList.size();
-printAddInvokedArrayList.add(33, 33);
-
-

-The reason you must use Java.extend() with concrete classes is that with concrete classes, there can be a -syntactic ambiguity if you just invoke their constructor. Consider this example: -

-

-var t = new java.lang.Thread({ run: function() { print("Hello!") } })
-
-

-If we allowed subclassing of concrete classes with constructor syntax, Nashorn couldn't tell if you're creating a new -Thread and passing it a Runnable at this point, or you are subclassing Thread and -passing it a new implementation for its own run() method. -

-
- -

Implementing Multiple Interfaces

-

-Java.extend can in fact take a list of multiple types. At most one of the types can be a class, and the rest must -be interfaces (the class doesn't have to be the first in the list). You will get back an object that extends the class and -implements all the interfaces. (Obviously, if you only specify interfaces and no class, the object will extend java.lang.Object). -


- -

Class-Bound Implementations

-

-The methods shown so far for extending Java classes and implementing interfaces – passing an implementation JavaScript object -or function to a constructor, or using Java.extend with new – all produce classes that take an -extra JavaScript object parameter in their constructors that specifies the implementation. The implementation is therefore always bound -to the actual instance being created with new, and not to the whole class. This has some advantages, for example in the -memory footprint of the runtime, as Nashorn can just create a single "universal adapter" for every combination of types being implemented. -In reality, the below code shows that different instantiations of, say, Runnable have the same class regardless of them having -different JavaScript implementation objects: -

-

-var Runnable = java.lang.Runnable;
-var r1 = new Runnable(function() { print("I'm runnable 1!") })
-var r2 = new Runnable(function() { print("I'm runnable 2!") })
-r1.run()
-r2.run()
-print("We share the same class: " + (r1.class === r2.class))
-
-

-prints: -

-

-I'm runnable 1!
-I'm runnable 2!
-We share the same class: true
-
-

-Sometimes, however, you'll want to extend a Java class or implement an interface with implementation bound to the class, not to -its instances. Such a need arises, for example, when you need to pass the class for instantiation to an external API; prime example -of this is the JavaFX framework where you need to pass an Application class to the FX API and let it instantiate it. -

-

-Fortunately, there's a solution for that: Java.extend() – aside from being able to take any number of type parameters -denoting a class to extend and interfaces to implement – can also take one last argument that has to be a JavaScript object -that serves as the implementation for the methods. In this case, Java.extend() will create a class that has the same -constructors as the original class had, as they don't need to take an an extra implementation object parameter. The example below -shows how you can create class-bound implementations, and shows that in this case, the implementation classes for different invocations -are indeed different: -

-

-var RunnableImpl1 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") })
-var RunnableImpl2 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 2!") })
-var r1 = new RunnableImpl1()
-var r2 = new RunnableImpl2()
-r1.run()
-r2.run()
-print("We share the same class: " + (r1.class === r2.class))
-
-

-prints: -

-

-I'm runnable 1!
-I'm runnable 2!
-We share the same class: false
-
-

-As you can see, the major difference here is that we moved the implementation object into the invocation of Java.extend -from the constructor invocations – indeed the constructor invocations now don't even need to take an extra parameter! Since -the implementations are bound to a class, the two classes obviously can't be the same, and we indeed see that the two runnables no -longer share the same class – every invocation of Java.extend() with a class-specific implementation object triggers -the creation of a new Java adapter class. -

-

-Finally, the adapter classes with class-bound implementations can still take an additional constructor parameter to further -override the behavior on a per-instance basis. Thus, you can even combine the two approaches: you can provide part of the implementation -in a class-based JavaScript implementation object passed to Java.extend, and part in another object passed to the constructor. -Whatever functions are provided by the constructor-passed object will override the functions in the class-bound object. -

-

-var RunnableImpl = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") })
-var r1 = new RunnableImpl()
-var r2 = new RunnableImpl(function() { print("I'm runnable 2!") })
-r1.run()
-r2.run()
-print("We share the same class: " + (r1.class === r2.class))
-
-

-prints: -

-

-I'm runnable 1!
-I'm runnable 2!
-We share the same class: true
-
-
- -

Overload Resolution

-

Java methods can be overloaded by argument types. In Java, -overload resolution occurs at compile time (performed by javac). -When calling Java methods from Nashorn, the appropriate method will be -selected based on the argument types at invocation time. You do not need -to do anything special – the correct Java method overload variant -is selected based automatically. You still have the option of explicitly -specifying a particular overload variant. Reasons for this include -either running into a genuine ambiguity with actual argument types, or -rarely reasons of performance – if you specify the actual overload -then the engine doesn't have to perform resolution during invocation. -Individual overloads of a Java methods are exposed as special properties -with the name of the method followed with its signature in parentheses. -You can invoke them like this:

-

-// overload.js
-
-var out = java.lang.System.out;
-
-// select a particular print function 
-out["println(Object)"]("hello");
-
-
-

-Note that you normally don't even have to use qualified class names in -the signatures as long as the unqualified name of the type is sufficient -for uniquely identifying the signature. In practice this means that only -in the extremely unlikely case that two overloads only differ in -parameter types that have identical unqualified names but come from -different packages would you need to use the fully qualified name of the -class. -

-
- -

Mapping of Data Types Between Java and JavaScript

-

-We have previously shown some of the data type mappings between Java and JavaScript. -We saw that arrays need to be explicitly converted. We have also shown that JavaScript functions -are automatically converted to SAM types when passed as parameters to Java methods. Most other -conversions work as you would expect. -

-

-Every JavaScript object is also a java.util.Map so APIs receiving maps will receive them directly. -

-

-When numbers are passed to a Java API, they will be converted to the expected target numeric type, either boxed or -primitive, but if the target type is less specific, say Number or Object, you can only -count on them being a Number, and have to test specifically for whether it's a boxed Double, -Integer, Long, etc. – it can be any of these due to internal optimizations. Also, you -can pass any JavaScript value to a Java API expecting either a boxed or primitive number; the JavaScript specification's -ToNumber conversion algorithm will be applied to the value. -

-

-In a similar vein, if a Java method expects a String or a Boolean, the values will be -converted using all conversions allowed by the JavaScript specification's ToString and ToBoolean -conversions. -

-

-Finally, a word of caution about strings. Due to internal performance optimizations of string operations, JavaScript strings are -not always necessarily of type java.lang.String, but they will always be of type java.lang.CharSequence. -If you pass them to a Java method that expects a java.lang.String parameter, then you will naturally receive a Java -String, but if the signature of your method is more generic, i.e. it receives a java.lang.Object parameter, you can -end up with an object of private engine implementation class that implements CharSequence but is not a Java String. -

-
- -

Implementing Your Own Script Engine

-

We will not cover implementation of JSR-223 compliant script -engines in detail. Minimally, you need to implement the -javax.script.ScriptEngine and -javax.script.ScriptEngineFactory interfaces. The -abstract class javax.script.AbstractScriptEngine -provides useful defaults for a few methods of the -ScriptEngine interface.

-

Before starting to implement a JSR-223 engine, you may want to -check http://java.net/projects/Scripting -project. This project maintains JSR-223 implementations for many -popular open source scripting languages.

-
- -

References

- - - - -

- - - - - - - -
Oracle and/or its affiliates
- Java Technology
-

-Copyright © 2013, Oracle and/or its affiliates. All rights reserved. -

-
-

Contact Us

-
-

- - - - - - - - - - - - - - - diff --git a/doc/nashorn/source/EvalFile.java b/doc/nashorn/source/EvalFile.java deleted file mode 100644 index b12e91bb53f..00000000000 --- a/doc/nashorn/source/EvalFile.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; - -@SuppressWarnings("javadoc") -public class EvalFile { - public static void main(final String[] args) throws Exception { - // create a script engine manager - final ScriptEngineManager factory = new ScriptEngineManager(); - // create JavaScript engine - final ScriptEngine engine = factory.getEngineByName("nashorn"); - // evaluate JavaScript code from given file - specified by first argument - engine.eval(new java.io.FileReader(args[0])); - } -} - diff --git a/doc/nashorn/source/EvalScript.java b/doc/nashorn/source/EvalScript.java deleted file mode 100644 index 49f581deabc..00000000000 --- a/doc/nashorn/source/EvalScript.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; - -@SuppressWarnings("javadoc") -public class EvalScript { - public static void main(final String[] args) throws Exception { - // create a script engine manager - final ScriptEngineManager factory = new ScriptEngineManager(); - // create a JavaScript engine - final ScriptEngine engine = factory.getEngineByName("nashorn"); - // evaluate JavaScript code from String - engine.eval("print('Hello, World')"); - } -} - diff --git a/doc/nashorn/source/InvokeScriptFunction.java b/doc/nashorn/source/InvokeScriptFunction.java deleted file mode 100644 index 5ce1cae0a42..00000000000 --- a/doc/nashorn/source/InvokeScriptFunction.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; - -@SuppressWarnings("javadoc") -public class InvokeScriptFunction { - public static void main(final String[] args) throws Exception { - final ScriptEngineManager manager = new ScriptEngineManager(); - final ScriptEngine engine = manager.getEngineByName("nashorn"); - - // JavaScript code in a String - final String script = "function hello(name) { print('Hello, ' + name); }"; - // evaluate script - engine.eval(script); - - // javax.script.Invocable is an optional interface. - // Check whether your script engine implements or not! - // Note that the JavaScript engine implements Invocable interface. - final Invocable inv = (Invocable) engine; - - // invoke the global function named "hello" - inv.invokeFunction("hello", "Scripting!!" ); - } -} - - - diff --git a/doc/nashorn/source/InvokeScriptMethod.java b/doc/nashorn/source/InvokeScriptMethod.java deleted file mode 100644 index d3cc788d09d..00000000000 --- a/doc/nashorn/source/InvokeScriptMethod.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; - -@SuppressWarnings("javadoc") -public class InvokeScriptMethod { - public static void main(final String[] args) throws Exception { - final ScriptEngineManager manager = new ScriptEngineManager(); - final ScriptEngine engine = manager.getEngineByName("nashorn"); - - // JavaScript code in a String. This code defines a script object 'obj' - // with one method called 'hello'. - final String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }"; - // evaluate script - engine.eval(script); - - // javax.script.Invocable is an optional interface. - // Check whether your script engine implements or not! - // Note that the JavaScript engine implements Invocable interface. - final Invocable inv = (Invocable) engine; - - // get script object on which we want to call the method - final Object obj = engine.get("obj"); - - // invoke the method named "hello" on the script object "obj" - inv.invokeMethod(obj, "hello", "Script Method !!" ); - } -} diff --git a/doc/nashorn/source/MultiScopes.java b/doc/nashorn/source/MultiScopes.java deleted file mode 100644 index ff4f65b4684..00000000000 --- a/doc/nashorn/source/MultiScopes.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import javax.script.Bindings; -import javax.script.ScriptContext; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.SimpleScriptContext; - -@SuppressWarnings("javadoc") -public class MultiScopes { - public static void main(final String[] args) throws Exception { - final ScriptEngineManager manager = new ScriptEngineManager(); - final ScriptEngine engine = manager.getEngineByName("nashorn"); - - engine.put("x", "hello"); - // print global variable "x" - engine.eval("print(x);"); - // the above line prints "hello" - - // Now, pass a different script context - final ScriptContext newContext = new SimpleScriptContext(); - newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE); - final Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE); - - // add new variable "x" to the new engineScope - engineScope.put("x", "world"); - - // execute the same script - but this time pass a different script context - engine.eval("print(x);", newContext); - // the above line prints "world" - } -} - - diff --git a/doc/nashorn/source/RunnableImpl.java b/doc/nashorn/source/RunnableImpl.java deleted file mode 100644 index 2b5113b103c..00000000000 --- a/doc/nashorn/source/RunnableImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; - -@SuppressWarnings("javadoc") -public class RunnableImpl { - public static void main(final String[] args) throws Exception { - final ScriptEngineManager manager = new ScriptEngineManager(); - final ScriptEngine engine = manager.getEngineByName("nashorn"); - - // JavaScript code in a String - final String script = "function run() { print('run called'); }"; - - // evaluate script - engine.eval(script); - - final Invocable inv = (Invocable) engine; - - // get Runnable interface object from engine. This interface methods - // are implemented by script functions with the matching name. - final Runnable r = inv.getInterface(Runnable.class); - - // start a new thread that runs the script implemented - // runnable interface - final Thread th = new Thread(r); - th.start(); - th.join(); - } -} diff --git a/doc/nashorn/source/RunnableImplObject.java b/doc/nashorn/source/RunnableImplObject.java deleted file mode 100644 index 0d5f5032e89..00000000000 --- a/doc/nashorn/source/RunnableImplObject.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; - -@SuppressWarnings("javadoc") -public class RunnableImplObject { - public static void main(final String[] args) throws Exception { - final ScriptEngineManager manager = new ScriptEngineManager(); - final ScriptEngine engine = manager.getEngineByName("nashorn"); - - // JavaScript code in a String - final String script = "var obj = new Object(); obj.run = function() { print('run method called'); }"; - - // evaluate script - engine.eval(script); - - // get script object on which we want to implement the interface with - final Object obj = engine.get("obj"); - - final Invocable inv = (Invocable) engine; - - // get Runnable interface object from engine. This interface methods - // are implemented by script methods of object 'obj' - final Runnable r = inv.getInterface(obj, Runnable.class); - - // start a new thread that runs the script implemented - // runnable interface - final Thread th = new Thread(r); - th.start(); - th.join(); - } -} diff --git a/doc/nashorn/source/ScriptVars.java b/doc/nashorn/source/ScriptVars.java deleted file mode 100644 index c697431dc18..00000000000 --- a/doc/nashorn/source/ScriptVars.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import java.io.File; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; - -@SuppressWarnings("javadoc") -public class ScriptVars { - public static void main(final String[] args) throws Exception { - final ScriptEngineManager manager = new ScriptEngineManager(); - final ScriptEngine engine = manager.getEngineByName("nashorn"); - - final File f = new File("test.txt"); - // expose File object as variable to script - engine.put("file", f); - - // evaluate a script string. The script accesses "file" - // variable and calls method on it - engine.eval("print(file.getAbsolutePath())"); - } -} - - - diff --git a/doc/nashorn/source/importpackageclass.js b/doc/nashorn/source/importpackageclass.js deleted file mode 100644 index 224debd6e4a..00000000000 --- a/doc/nashorn/source/importpackageclass.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// load compatibility script -load("nashorn:mozilla_compat.js"); - -// Import Java packages and classes -// like import package.*; in Java -importPackage(java.awt); -// like import java.awt.Frame in Java -importClass(java.awt.Frame); -// Create Java Objects by "new ClassName" -var frame = new java.awt.Frame("hello"); -// Call Java public methods from script -frame.setVisible(true); -// Access "JavaBean" properties like "fields" -print(frame.title); diff --git a/doc/nashorn/source/javaarray.js b/doc/nashorn/source/javaarray.js deleted file mode 100644 index 659619107fc..00000000000 --- a/doc/nashorn/source/javaarray.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// create Java String array of 5 elements -var StringArray = Java.type("java.lang.String[]"); -var a = new StringArray(5); - -// Accessing elements and length access is by usual Java syntax -a[0] = "scripting is great!"; -print(a.length); -print(a[0]); - -// convert a script array to Java array -var anArray = [1, "13", false]; -var javaIntArray = Java.to(anArray, "int[]"); -print(javaIntArray[0]);// prints 1 -print(javaIntArray[1]); // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion -print(javaIntArray[2]);// prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion - -// convert a Java array to a JavaScript array -var File = Java.type("java.io.File"); -var listCurDir = new File(".").listFiles(); -var jsList = Java.from(listCurDir); -print(jsList); diff --git a/doc/nashorn/source/javaextend.js b/doc/nashorn/source/javaextend.js deleted file mode 100644 index f1c6256b012..00000000000 --- a/doc/nashorn/source/javaextend.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -var ArrayList = Java.type("java.util.ArrayList") -var ArrayListExtender = Java.extend(ArrayList) -var printSizeInvokedArrayList = new ArrayListExtender() { - size: function() { print("size invoked!"); } -} -var printAddInvokedArrayList = new ArrayListExtender() { - add: function(x, y) { - if(typeof(y) === "undefined") { - print("add(e) invoked!"); - } else { - print("add(i, e) invoked!"); - } - } -}; -printSizeInvokedArrayList.size(); -printAddInvokedArrayList.add(33, 33); diff --git a/doc/nashorn/source/javaimporter.js b/doc/nashorn/source/javaimporter.js deleted file mode 100644 index 5004ce889d1..00000000000 --- a/doc/nashorn/source/javaimporter.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// create JavaImporter with specific packages and classes to import - -var SwingGui = new JavaImporter(javax.swing, - javax.swing.event, - javax.swing.border, - java.awt.event); -with (SwingGui) { - // within this 'with' statement, we can access Swing and AWT - // classes by unqualified (simple) names. - - var mybutton = new JButton("test"); - print(mybutton); - var myframe = new JFrame("test"); - print(myframe); -} - - diff --git a/doc/nashorn/source/javatypes.js b/doc/nashorn/source/javatypes.js deleted file mode 100644 index 82392ec4495..00000000000 --- a/doc/nashorn/source/javatypes.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -// accessing java types -var arrayListType = Java.type("java.util.ArrayList") -var intType = Java.type("int") -var stringArrayType = Java.type("java.lang.String[]") -var int2DArrayType = Java.type("int[][]") - -// Using java types -var ArrayList = Java.type("java.util.ArrayList") -var anArrayList = new ArrayList -var anArrayListWithSize = new ArrayList(16) - -// fully qualified name -var ftype = Java.type("java.awt.geom.Arc2D$Float") - -// inner class property -var arctype = Java.type("java.awt.geom.Arc2D") -var ftype = arctype.Float - diff --git a/doc/nashorn/source/overload.js b/doc/nashorn/source/overload.js deleted file mode 100644 index a2905f94d3c..00000000000 --- a/doc/nashorn/source/overload.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -var out = java.lang.System.out; - -// select a particular print function -out["println(java.lang.Object)"]("hello"); - diff --git a/doc/nashorn/source/runnable.js b/doc/nashorn/source/runnable.js deleted file mode 100644 index 346c2522a36..00000000000 --- a/doc/nashorn/source/runnable.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -var r = new java.lang.Runnable() { - run: function() { - print("running...\n"); - } -}; - -// "r" can be passed to Java methods that expect java.lang.Runnable -var th = new java.lang.Thread(r); -th.start(); -th.join(); diff --git a/doc/nashorn/source/samfunc.js b/doc/nashorn/source/samfunc.js deleted file mode 100644 index dbb321d0f55..00000000000 --- a/doc/nashorn/source/samfunc.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -function func() { - print("I am func!"); -} - -// pass script function for java.lang.Runnable argument -var th = new java.lang.Thread(func); -th.start(); -th.join(); diff --git a/doc/nashorn/source/test.js b/doc/nashorn/source/test.js deleted file mode 100644 index 56e96ef26ad..00000000000 --- a/doc/nashorn/source/test.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -print("This is hello from test.js"); diff --git a/doc/testing.html b/doc/testing.html index ae38528722f..49227421dcf 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -137,6 +137,8 @@

JOBS

TIMEOUT_FACTOR

The timeout factor (-timeoutFactor).

Defaults to 4.

+

FAILURE_HANDLER_TIMEOUT

+

Sets the argument -timeoutHandlerTimeout for JTReg. The default value is 0. This is only valid if the failure handler is built.

TEST_MODE

The test mode (agentvm or othervm).

Defaults to agentvm.

@@ -153,8 +155,10 @@

MAX_MEM

Limit memory consumption (-Xmx and -vmoption:-Xmx, or none).

Limit memory consumption for JTReg test framework and VM under test. Set to 0 to disable the limits.

Defaults to 512m, except for hotspot, where it defaults to 0 (no limit).

+

MAX_OUTPUT

+

Set the property javatest.maxOutputSize for the launcher, to change the default JTReg log limit.

KEYWORDS

-

JTReg kewords sent to JTReg using -k. Please be careful in making sure that spaces and special characters (like !) are properly quoted. To avoid some issues, the special value %20 can be used instead of space.

+

JTReg keywords sent to JTReg using -k. Please be careful in making sure that spaces and special characters (like !) are properly quoted. To avoid some issues, the special value %20 can be used instead of space.

EXTRA_PROBLEM_LISTS

Use additional problem lists file or files, in addition to the default ProblemList.txt located at the JTReg test roots.

If multiple file names are specified, they should be separated by space (or, to help avoid quoting issues, the special value %20).

@@ -170,6 +174,8 @@

JAVA_OPTIONS

VM_OPTIONS

Additional Java options to be used when compiling and running classes (sent to JTReg as -vmoption).

This option is only needed in special circumstances. To pass Java options to your test classes, use JAVA_OPTIONS.

+

LAUNCHER_OPTIONS

+

Additional Java options that are sent to the java launcher that starts the JTReg harness.

AOT_MODULES

Generate AOT modules before testing for the specified module, or set of modules. If multiple modules are specified, they should be separated by space (or, to help avoid quoting issues, the special value %20).

RETRY_COUNT

@@ -205,14 +211,19 @@

Docker Tests

Docker tests with default parameters may fail on systems with glibc versions not compatible with the one used in the default docker image (e.g., Oracle Linux 7.6 for x86). For example, they pass on Ubuntu 16.04 but fail on Ubuntu 18.04 if run like this on x86:

$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker"

To run these tests correctly, additional parameters for the correct docker image are required on Ubuntu 18.04 by using JAVA_OPTIONS.

-
$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"
+
$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" \
+    JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu
+    -Djdk.test.docker.image.version=latest"

Non-US locale

-

If your locale is non-US, some tests are likely to fail. To work around this you can set the locale to US. On Unix platforms simply setting LANG="en_US" in the environment before running tests should work. On Windows, setting JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" helps for most, but not all test cases. For example:

+

If your locale is non-US, some tests are likely to fail. To work around this you can set the locale to US. On Unix platforms simply setting LANG="en_US" in the environment before running tests should work. On Windows, setting JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" helps for most, but not all test cases.

+

For example:

$ export LANG="en_US" && make test TEST=...
 $ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=...

PKCS11 Tests

-

It is highly recommended to use the latest NSS version when running PKCS11 tests. Improper NSS version may lead to unexpected failures which are hard to diagnose. For example, sun/security/pkcs11/Secmod/AddTrustedCert.java may fail on Ubuntu 18.04 with the default NSS version in the system. To run these tests correctly, the system property test.nss.lib.paths is required on Ubuntu 18.04 to specify the alternative NSS lib directories. For example:

-
$ make test TEST="jtreg:sun/security/pkcs11/Secmod/AddTrustedCert.java" JTREG="JAVA_OPTIONS=-Dtest.nss.lib.paths=/path/to/your/latest/NSS-libs"
+

It is highly recommended to use the latest NSS version when running PKCS11 tests. Improper NSS version may lead to unexpected failures which are hard to diagnose. For example, sun/security/pkcs11/Secmod/AddTrustedCert.java may fail on Ubuntu 18.04 with the default NSS version in the system. To run these tests correctly, the system property test.nss.lib.paths is required on Ubuntu 18.04 to specify the alternative NSS lib directories.

+

For example:

+
$ make test TEST="jtreg:sun/security/pkcs11/Secmod/AddTrustedCert.java" \
+    JTREG="JAVA_OPTIONS=-Dtest.nss.lib.paths=/path/to/your/latest/NSS-libs"

For more notes about the PKCS11 tests, please refer to test/jdk/sun/security/pkcs11/README.

Client UI Tests

Some Client UI tests use key sequences which may be reserved by the operating system. Usually that causes the test failure. So it is highly recommended to disable system key shortcuts prior testing. The steps to access and disable system key shortcuts for various platforms are provided below.

diff --git a/doc/testing.md b/doc/testing.md index 8a42ea92e69..0d09491be6e 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -37,11 +37,11 @@ Note that this option should point to the JTReg home, i.e. the top directory, containing `lib/jtreg.jar` etc. (An alternative is to set the `JT_HOME` environment variable to point to the JTReg home before running `configure`.) -To be able to run microbenchmarks, `configure` needs to know where to find -the JMH dependency. Use `--with-jmh=` to point to a directory -containing the core JMH and transitive dependencies. The recommended dependencies -can be retrieved by running `sh make/devkit/createJMHBundle.sh`, after which -`--with-jmh=build/jmh/jars` should work. +To be able to run microbenchmarks, `configure` needs to know where to find the +JMH dependency. Use `--with-jmh=` to point to a directory +containing the core JMH and transitive dependencies. The recommended +dependencies can be retrieved by running `sh make/devkit/createJMHBundle.sh`, +after which `--with-jmh=build/jmh/jars` should work. ## Test selection @@ -182,10 +182,10 @@ variables. These variables use a keyword=value approach to allow multiple values to be set. So, for instance, `JTREG="JOBS=1;TIMEOUT_FACTOR=8"` will set the JTReg concurrency level to 1 and the timeout factor to 8. This is equivalent to -setting `JTREG_JOBS=1 JTREG_TIMEOUT_FACTOR=8`, but using the keyword format means that -the `JTREG` variable is parsed and verified for correctness, so -`JTREG="TMIEOUT_FACTOR=8"` would give an error, while `JTREG_TMIEOUT_FACTOR=8` would just -pass unnoticed. +setting `JTREG_JOBS=1 JTREG_TIMEOUT_FACTOR=8`, but using the keyword format +means that the `JTREG` variable is parsed and verified for correctness, so +`JTREG="TMIEOUT_FACTOR=8"` would give an error, while `JTREG_TMIEOUT_FACTOR=8` +would just pass unnoticed. To separate multiple keyword=value pairs, use `;` (semicolon). Since the shell normally eats `;`, the recommended usage is to write the assignment inside @@ -203,9 +203,10 @@ test suites. ### General keywords (TEST_OPTS) -Some keywords are valid across different test suites. If you want to run -tests from multiple test suites, or just don't want to care which test suite specific -control variable to use, then you can use the general TEST_OPTS control variable. +Some keywords are valid across different test suites. If you want to run tests +from multiple test suites, or just don't want to care which test suite specific +control variable to use, then you can use the general TEST_OPTS control +variable. There are also some keywords that applies globally to the test runner system, not to any specific test suites. These are also available as TEST_OPTS keywords. @@ -252,12 +253,13 @@ for only recently changed code. JCOV_DIFF_CHANGESET specifies a source revision. A textual report will be generated showing coverage of the diff between the specified revision and the repository tip. -The report is stored in `build/$BUILD/test-results/jcov-output/diff_coverage_report` -file. +The report is stored in +`build/$BUILD/test-results/jcov-output/diff_coverage_report` file. ### JTReg keywords #### JOBS + The test concurrency (`-concurrency`). Defaults to TEST_JOBS (if set by `--with-test-jobs=`), otherwise it defaults to @@ -265,32 +267,43 @@ JOBS, except for Hotspot, where the default is *number of CPU cores/2*, but never more than *memory size in GB/2*. #### TIMEOUT_FACTOR + The timeout factor (`-timeoutFactor`). Defaults to 4. +#### FAILURE_HANDLER_TIMEOUT + +Sets the argument `-timeoutHandlerTimeout` for JTReg. The default value is 0. +This is only valid if the failure handler is built. + #### TEST_MODE + The test mode (`agentvm` or `othervm`). Defaults to `agentvm`. #### ASSERT + Enable asserts (`-ea -esa`, or none). Set to `true` or `false`. If true, adds `-ea -esa`. Defaults to true, except for hotspot. #### VERBOSE + The verbosity level (`-verbose`). Defaults to `fail,error,summary`. #### RETAIN + What test data to retain (`-retain`). Defaults to `fail,error`. #### MAX_MEM + Limit memory consumption (`-Xmx` and `-vmoption:-Xmx`, or none). Limit memory consumption for JTReg test framework and VM under test. Set to 0 @@ -298,9 +311,14 @@ to disable the limits. Defaults to 512m, except for hotspot, where it defaults to 0 (no limit). +#### MAX_OUTPUT + +Set the property `javatest.maxOutputSize` for the launcher, to change the +default JTReg log limit. + #### KEYWORDS -JTReg kewords sent to JTReg using `-k`. Please be careful in making sure that +JTReg keywords sent to JTReg using `-k`. Please be careful in making sure that spaces and special characters (like `!`) are properly quoted. To avoid some issues, the special value `%20` can be used instead of space. @@ -323,23 +341,30 @@ Set to `true` or `false`. If `true`, JTReg will use `-match:` option, otherwise `-exclude:` will be used. Default is `false`. - #### OPTIONS + Additional options to the JTReg test framework. Use `JTREG="OPTIONS=--help all"` to see all available JTReg options. #### JAVA_OPTIONS + Additional Java options for running test classes (sent to JTReg as `-javaoption`). #### VM_OPTIONS + Additional Java options to be used when compiling and running classes (sent to JTReg as `-vmoption`). This option is only needed in special circumstances. To pass Java options to your test classes, use `JAVA_OPTIONS`. +#### LAUNCHER_OPTIONS + +Additional Java options that are sent to the java launcher that starts the +JTReg harness. + #### AOT_MODULES Generate AOT modules before testing for the specified module, or set of @@ -353,6 +378,7 @@ Retry failed tests up to a set number of times. Defaults to 0. ### Gtest keywords #### REPEAT + The number of times to repeat the tests (`--gtest_repeat`). Default is 1. Set to -1 to repeat indefinitely. This can be especially useful @@ -360,6 +386,7 @@ combined with `OPTIONS=--gtest_break_on_failure` to reproduce an intermittent problem. #### OPTIONS + Additional options to the Gtest test framework. Use `GTEST="OPTIONS=--help"` to see all available Gtest options. @@ -373,98 +400,127 @@ modules. If multiple modules are specified, they should be separated by space ### Microbenchmark keywords #### FORK + Override the number of benchmark forks to spawn. Same as specifying `-f `. #### ITER + Number of measurement iterations per fork. Same as specifying `-i `. #### TIME + Amount of time to spend in each measurement iteration, in seconds. Same as specifying `-r ` #### WARMUP_ITER + Number of warmup iterations to run before the measurement phase in each fork. Same as specifying `-wi `. #### WARMUP_TIME + Amount of time to spend in each warmup iteration. Same as specifying `-w `. #### RESULTS_FORMAT + Specify to have the test run save a log of the values. Accepts the same values as `-rff`, i.e., `text`, `csv`, `scsv`, `json`, or `latex`. #### VM_OPTIONS + Additional VM arguments to provide to forked off VMs. Same as `-jvmArgs ` #### OPTIONS + Additional arguments to send to JMH. ## Notes for Specific Tests ### Docker Tests -Docker tests with default parameters may fail on systems with glibc versions not -compatible with the one used in the default docker image (e.g., Oracle Linux 7.6 for x86). -For example, they pass on Ubuntu 16.04 but fail on Ubuntu 18.04 if run like this on x86: +Docker tests with default parameters may fail on systems with glibc versions +not compatible with the one used in the default docker image (e.g., Oracle +Linux 7.6 for x86). For example, they pass on Ubuntu 16.04 but fail on Ubuntu +18.04 if run like this on x86: - $ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" +``` +$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" +``` -To run these tests correctly, additional parameters for the correct docker image are -required on Ubuntu 18.04 by using `JAVA_OPTIONS`. +To run these tests correctly, additional parameters for the correct docker +image are required on Ubuntu 18.04 by using `JAVA_OPTIONS`. - $ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest" +``` +$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" \ + JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu + -Djdk.test.docker.image.version=latest" +``` ### Non-US locale -If your locale is non-US, some tests are likely to fail. To work around this you can -set the locale to US. On Unix platforms simply setting `LANG="en_US"` in the -environment before running tests should work. On Windows, setting -`JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"` helps for most, but not all test cases. +If your locale is non-US, some tests are likely to fail. To work around this +you can set the locale to US. On Unix platforms simply setting `LANG="en_US"` +in the environment before running tests should work. On Windows, setting +`JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"` helps for most, but +not all test cases. + For example: - $ export LANG="en_US" && make test TEST=... - $ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=... +``` +$ export LANG="en_US" && make test TEST=... +$ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=... +``` ### PKCS11 Tests -It is highly recommended to use the latest NSS version when running PKCS11 tests. -Improper NSS version may lead to unexpected failures which are hard to diagnose. -For example, sun/security/pkcs11/Secmod/AddTrustedCert.java may fail on Ubuntu -18.04 with the default NSS version in the system. -To run these tests correctly, the system property `test.nss.lib.paths` is required -on Ubuntu 18.04 to specify the alternative NSS lib directories. +It is highly recommended to use the latest NSS version when running PKCS11 +tests. Improper NSS version may lead to unexpected failures which are hard to +diagnose. For example, sun/security/pkcs11/Secmod/AddTrustedCert.java may fail +on Ubuntu 18.04 with the default NSS version in the system. To run these tests +correctly, the system property `test.nss.lib.paths` is required on Ubuntu 18.04 +to specify the alternative NSS lib directories. + For example: - $ make test TEST="jtreg:sun/security/pkcs11/Secmod/AddTrustedCert.java" JTREG="JAVA_OPTIONS=-Dtest.nss.lib.paths=/path/to/your/latest/NSS-libs" +``` +$ make test TEST="jtreg:sun/security/pkcs11/Secmod/AddTrustedCert.java" \ + JTREG="JAVA_OPTIONS=-Dtest.nss.lib.paths=/path/to/your/latest/NSS-libs" +``` -For more notes about the PKCS11 tests, please refer to test/jdk/sun/security/pkcs11/README. +For more notes about the PKCS11 tests, please refer to +test/jdk/sun/security/pkcs11/README. ### Client UI Tests Some Client UI tests use key sequences which may be reserved by the operating -system. Usually that causes the test failure. So it is highly recommended to disable -system key shortcuts prior testing. The steps to access and disable system key shortcuts -for various platforms are provided below. +system. Usually that causes the test failure. So it is highly recommended to +disable system key shortcuts prior testing. The steps to access and disable +system key shortcuts for various platforms are provided below. #### MacOS + Choose Apple menu; System Preferences, click Keyboard, then click Shortcuts; select or deselect desired shortcut. -For example, test/jdk/javax/swing/TooltipManager/JMenuItemToolTipKeyBindingsTest/JMenuItemToolTipKeyBindingsTest.java fails -on MacOS because it uses `CTRL + F1` key sequence to show or hide tooltip message -but the key combination is reserved by the operating system. To run the test correctly -the default global key shortcut should be disabled using the steps described above, and then deselect -"Turn keyboard access on or off" option which is responsible for `CTRL + F1` combination. +For example, +test/jdk/javax/swing/TooltipManager/JMenuItemToolTipKeyBindingsTest/JMenuItemToolTipKeyBindingsTest.java +fails on MacOS because it uses `CTRL + F1` key sequence to show or hide tooltip +message but the key combination is reserved by the operating system. To run the +test correctly the default global key shortcut should be disabled using the +steps described above, and then deselect "Turn keyboard access on or off" +option which is responsible for `CTRL + F1` combination. #### Linux -Open the Activities overview and start typing Settings; Choose Settings, click Devices, -then click Keyboard; set or override desired shortcut. + +Open the Activities overview and start typing Settings; Choose Settings, click +Devices, then click Keyboard; set or override desired shortcut. #### Windows -Type `gpedit` in the Search and then click Edit group policy; navigate to -User Configuration -> Administrative Templates -> Windows Components -> File Explorer; -in the right-side pane look for "Turn off Windows key hotkeys" and double click on it; -enable or disable hotkeys. + +Type `gpedit` in the Search and then click Edit group policy; navigate to User +Configuration -> Administrative Templates -> Windows Components -> File +Explorer; in the right-side pane look for "Turn off Windows key hotkeys" and +double click on it; enable or disable hotkeys. Note: restart is required to make the settings take effect. diff --git a/make/Global.gmk b/make/Global.gmk index 34a1125a1c9..f9200d16851 100644 --- a/make/Global.gmk +++ b/make/Global.gmk @@ -101,9 +101,9 @@ help: $(info $(_) # method is 'auto', 'ignore' or 'fail' (default)) $(info $(_) TEST="test1 ..." # Use the given test descriptor(s) for testing, e.g.) $(info $(_) # make test TEST="jdk_lang gtest:all") - $(info $(_) JTREG="OPT1=x;OPT2=y" # Control the JTREG test harness) - $(info $(_) GTEST="OPT1=x;OPT2=y" # Control the GTEST test harness) - $(info $(_) MICRO="OPT1=x;OPT2=y" # Control the MICRO test harness) + $(info $(_) JTREG="OPT1=x;OPT2=y" # Control the JTREG test harness, use 'help' to list) + $(info $(_) GTEST="OPT1=x;OPT2=y" # Control the GTEST test harness, use 'help' to list) + $(info $(_) MICRO="OPT1=x;OPT2=y" # Control the MICRO test harness, use 'help' to list) $(info $(_) TEST_OPTS="OPT1=x;..." # Generic control of all test harnesses) $(info $(_) TEST_VM_OPTS="ARG ..." # Same as setting TEST_OPTS to VM_OPTIONS="ARG ...") $(info ) diff --git a/make/Init.gmk b/make/Init.gmk index 932286a58b1..1df133eeef0 100644 --- a/make/Init.gmk +++ b/make/Init.gmk @@ -197,7 +197,7 @@ ifeq ($(HAS_SPEC),) COMPARE_BUILD="$(COMPARE_BUILD)" pre-compare-build && \ $(MAKE) $(MFLAGS) $(MAKE_LOG_FLAGS) -r -R -j 1 -f $(topdir)/make/Init.gmk \ SPEC=$(spec) HAS_SPEC=true $(MAKE_INIT_WITH_SPEC_ARGUMENTS) \ - COMPARE_BUILD="$(COMPARE_BUILD)" main && \ + COMPARE_BUILD="$(COMPARE_BUILD):NODRYRUN=true" main && \ $(MAKE) $(MFLAGS) $(MAKE_LOG_FLAGS) -r -R -f $(topdir)/make/Init.gmk \ SPEC=$(spec) HAS_SPEC=true ACTUAL_TOPDIR=$(topdir) \ COMPARE_BUILD="$(COMPARE_BUILD)" post-compare-build && \ diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index 6dbc963ba8c..8ee2e9098ba 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -350,6 +350,9 @@ else # $(HAS_SPEC)=true $$(if $$(filter FAIL=%, $$(part)), \ $$(eval COMPARE_BUILD_FAIL=$$(strip $$(subst +, , $$(patsubst FAIL=%, %, $$(part))))) \ ) \ + $$(if $$(filter NODRYRUN=%, $$(part)), \ + $$(eval COMPARE_BUILD_NODRYRUN=$$(strip $$(subst +, , $$(patsubst NODRYRUN=%, %, $$(part))))) \ + ) \ ) else # Separate handling for single field case, to allow for spaces in values. @@ -372,9 +375,11 @@ else # $(HAS_SPEC)=true else ifeq ($$(wildcard $$(COMPARE_BUILD_PATCH)), ) $$(error Patch file $$(COMPARE_BUILD_PATCH) does not exist) endif - PATCH_DRY_RUN := $$(shell cd $$(topdir) && $$(PATCH) --dry-run -p1 < $$(COMPARE_BUILD_PATCH) > /dev/null 2>&1 || $$(ECHO) FAILED) - ifeq ($$(PATCH_DRY_RUN), FAILED) - $$(error Patch file $$(COMPARE_BUILD_PATCH) does not apply cleanly) + ifneq ($$(COMPARE_BUILD_NODRYRUN), true) + PATCH_DRY_RUN := $$(shell cd $$(topdir) && $$(PATCH) --dry-run -p1 < $$(COMPARE_BUILD_PATCH) > /dev/null 2>&1 || $$(ECHO) FAILED) + ifeq ($$(PATCH_DRY_RUN), FAILED) + $$(error Patch file $$(COMPARE_BUILD_PATCH) does not apply cleanly) + endif endif endif ifneq ($$(COMPARE_BUILD_FAIL), true) diff --git a/make/RunTests.gmk b/make/RunTests.gmk index f2f1877fff1..721bb827639 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -143,9 +143,6 @@ endif # Optionally create AOT libraries for specified modules before running tests. # Note, this could not be done during JDK build time. ################################################################################ - -# Note, this could not be done during JDK build time. - # Parameter 1 is the name of the rule. # # Remaining parameters are named arguments. @@ -198,6 +195,10 @@ define SetupAotModuleBody $1_AOT_TARGETS += $$($1_AOT_LIB) endef +################################################################################ +# Optionally create AOT libraries before running tests. +# Note, this could not be done during JDK build time. +################################################################################ # Parameter 1 is the name of the rule. # # Remaining parameters are named arguments. @@ -291,9 +292,9 @@ $(eval $(call SetTestOpt,FAILURE_HANDLER_TIMEOUT,JTREG)) $(eval $(call ParseKeywordVariable, JTREG, \ SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR FAILURE_HANDLER_TIMEOUT \ TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM RUN_PROBLEM_LISTS \ - RETRY_COUNT, \ + RETRY_COUNT MAX_OUTPUT, \ STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS KEYWORDS \ - EXTRA_PROBLEM_LISTS AOT_MODULES, \ + EXTRA_PROBLEM_LISTS AOT_MODULES LAUNCHER_OPTIONS, \ )) ifneq ($(JTREG), ) @@ -844,6 +845,14 @@ define SetupRunJtregTestBody JTREG_RUN_PROBLEM_LISTS ?= false JTREG_RETRY_COUNT ?= 0 + ifneq ($$(JTREG_LAUNCHER_OPTIONS), ) + $1_JTREG_LAUNCHER_OPTIONS += $$(JTREG_LAUNCHER_OPTIONS) + endif + + ifneq ($$(JTREG_MAX_OUTPUT), ) + $1_JTREG_LAUNCHER_OPTIONS += -Djavatest.maxOutputSize=$$(JTREG_MAX_OUTPUT) + endif + ifneq ($$($1_JTREG_MAX_MEM), 0) $1_JTREG_BASIC_OPTIONS += -vmoption:-Xmx$$($1_JTREG_MAX_MEM) $1_JTREG_LAUNCHER_OPTIONS += -Xmx$$($1_JTREG_MAX_MEM) diff --git a/make/autoconf/basic_windows.m4 b/make/autoconf/basic_windows.m4 index 310f58adf43..cadc53b6754 100644 --- a/make/autoconf/basic_windows.m4 +++ b/make/autoconf/basic_windows.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -150,10 +150,10 @@ AC_DEFUN_ONCE([BASIC_COMPILE_FIXPATH], fi FIXPATH_SRC_W="$FIXPATH_SRC" FIXPATH_BIN_W="$FIXPATH_BIN" - UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([FIXPATH_SRC_W]) - UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([FIXPATH_BIN_W]) $RM -rf $FIXPATH_BIN $FIXPATH_DIR $MKDIR -p $FIXPATH_DIR $CONFIGURESUPPORT_OUTPUTDIR/bin + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([FIXPATH_SRC_W]) + UTIL_REWRITE_AS_WINDOWS_MIXED_PATH([FIXPATH_BIN_W]) cd $FIXPATH_DIR $CC $FIXPATH_SRC_W -Fe$FIXPATH_BIN_W > $FIXPATH_DIR/fixpath1.log 2>&1 cd $CONFIGURE_START_DIR diff --git a/make/autoconf/util_windows.m4 b/make/autoconf/util_windows.m4 index bc3cd0ed96a..5ccc6e93e7b 100644 --- a/make/autoconf/util_windows.m4 +++ b/make/autoconf/util_windows.m4 @@ -52,7 +52,15 @@ AC_DEFUN([UTIL_REWRITE_AS_WINDOWS_MIXED_PATH], windows_path=`cmd //c echo $unix_path` $1="$windows_path" elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl"; then - windows_path=`$WSLPATH -m "$unix_path"` + windows_path=`$WSLPATH -m "$unix_path" 2>/dev/null` + if test $? -ne 0; then + dir=`dirname "$unix_path"` + base=`basename "$unix_path"` + windows_path=`$WSLPATH -m "$dir"`/"$base" + if test $? -ne 0; then + AC_MSG_ERROR([Cannot convert \"$unix_path\" to Windows path]) + fi + fi $1="$windows_path" fi ]) diff --git a/make/common/Utils.gmk b/make/common/Utils.gmk index 794d5789ebc..8f6f40c2657 100644 --- a/make/common/Utils.gmk +++ b/make/common/Utils.gmk @@ -220,6 +220,10 @@ define ParseKeywordVariableBody $$(eval mangled_part_eval := $$(call DoubleDollar, $$(mangled_part))) \ $$(eval part := $$$$(subst ||||,$$$$(SPACE),$$$$(mangled_part_eval))) \ $$(eval $1_NO_MATCH := true) \ + $$(if $$(filter help, $$(part)), \ + $$(info Valid keywords for $1:) \ + $$(info $$($1_SINGLE_KEYWORDS) $$($1_STRING_KEYWORDS).) \ + $$(error Re-run without 'help' to continue)) \ $$(foreach keyword, $$($1_SINGLE_KEYWORDS), \ $$(eval keyword_eval := $$(call DoubleDollar, $$(keyword))) \ $$(if $$(filter $$(keyword)=%, $$(part)), \ diff --git a/make/hotspot/lib/CompileGtest.gmk b/make/hotspot/lib/CompileGtest.gmk index bf3a9e2ba24..03c4de783cd 100644 --- a/make/hotspot/lib/CompileGtest.gmk +++ b/make/hotspot/lib/CompileGtest.gmk @@ -38,9 +38,8 @@ endif ################################################################################ -# Disabling all warnings in gtest source code -$(eval $(call SetupNativeCompilation, BUILD_GTEST_LIBGTEST, \ +$(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBGTEST, \ NAME := gtest, \ TYPE := STATIC_LIBRARY, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ @@ -50,8 +49,9 @@ $(eval $(call SetupNativeCompilation, BUILD_GTEST_LIBGTEST, \ $(GTEST_FRAMEWORK_SRC)/googletest/src \ $(GTEST_FRAMEWORK_SRC)/googlemock/src, \ INCLUDE_FILES := gtest-all.cc gmock-all.cc, \ - CFLAGS := $(filter-out $(WARNING_CFLAGS_JVM), $(JVM_CFLAGS)) \ - -w \ + DISABLED_WARNINGS_gcc := undef unused-result format-nonliteral, \ + DISABLED_WARNINGS_clang := undef unused-result format-nonliteral, \ + CFLAGS := $(JVM_CFLAGS) \ -I$(GTEST_FRAMEWORK_SRC)/googletest \ -I$(GTEST_FRAMEWORK_SRC)/googletest/include \ -I$(GTEST_FRAMEWORK_SRC)/googlemock \ @@ -81,10 +81,9 @@ else $(call create-mapfile) endif -# Disabling undef, switch, format-nonliteral and tautological-undefined-compare -# warnings for clang because of test source. +# Additional disabled warnings are due to code in the test source. -$(eval $(call SetupNativeCompilation, BUILD_GTEST_LIBJVM, \ +$(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \ NAME := jvm, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OUTPUT_DIR := $(JVM_OUTPUTDIR)/gtest, \ @@ -106,6 +105,7 @@ $(eval $(call SetupNativeCompilation, BUILD_GTEST_LIBJVM, \ DISABLED_WARNINGS_clang := $(DISABLED_WARNINGS_clang) \ undef switch format-nonliteral tautological-undefined-compare \ self-assign-overloaded, \ + DISABLED_WARNINGS_microsoft := $(DISABLED_WARNINGS_microsoft), \ LDFLAGS := $(JVM_LDFLAGS), \ LDFLAGS_unix := -L$(JVM_OUTPUTDIR)/libgtest, \ LIBS := $(JVM_LIBS), \ @@ -127,7 +127,7 @@ TARGETS += $(BUILD_GTEST_LIBJVM) ################################################################################ -$(eval $(call SetupNativeCompilation, BUILD_GTEST_LAUNCHER, \ +$(eval $(call SetupJdkExecutable, BUILD_GTEST_LAUNCHER, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ NAME := gtestLauncher, \ TYPE := EXECUTABLE, \ diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index 47177473795..6f851f6f38a 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk @@ -95,9 +95,7 @@ DISABLED_WARNINGS_clang := tautological-compare \ DISABLED_WARNINGS_xlc := tautological-compare shift-negative-value -DISABLED_WARNINGS_microsoft := - - +DISABLED_WARNINGS_microsoft := 4100 4127 4201 4244 4291 4351 4511 4512 4514 4996 ################################################################################ # Platform specific setup @@ -146,7 +144,7 @@ $(call FillFindCache, $(JVM_SRC_DIRS)) ################################################################################ # Now set up the actual compilation of the main hotspot native library -$(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \ +$(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \ NAME := jvm, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \ diff --git a/make/hotspot/lib/CompileLibraries.gmk b/make/hotspot/lib/CompileLibraries.gmk index 6b1e6529cd0..f6bac075193 100644 --- a/make/hotspot/lib/CompileLibraries.gmk +++ b/make/hotspot/lib/CompileLibraries.gmk @@ -27,7 +27,7 @@ default: all include $(SPEC) include MakeBase.gmk -include NativeCompilation.gmk +include JdkNativeCompilation.gmk include HotspotCommon.gmk diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index 71ef8bde6c1..b385f8d7924 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -1067,10 +1067,23 @@ private Annotation[][] createParameterAnnotations(List constantPool, Lis } private Annotation createAnnotation(List constantPool, AnnotationDescription desc) { + String annotationType = desc.annotationType; + + if (PREVIEW_FEATURE_ANNOTATION.equals(annotationType)) { + //the non-public PreviewFeature annotation will not be available in ct.sym, + //replace with purely synthetic javac-internal annotation: + annotationType = PREVIEW_FEATURE_ANNOTATION_INTERNAL; + } + return new Annotation(null, - addString(constantPool, desc.annotationType), + addString(constantPool, annotationType), createElementPairs(constantPool, desc.values)); } + //where: + private static final String PREVIEW_FEATURE_ANNOTATION = + "Ljdk/internal/PreviewFeature;"; + private static final String PREVIEW_FEATURE_ANNOTATION_INTERNAL = + "Ljdk/internal/PreviewFeature+Annotation;"; private element_value_pair[] createElementPairs(List constantPool, Map annotationAttributes) { element_value_pair[] pairs = new element_value_pair[annotationAttributes.size()]; diff --git a/make/src/native/fixpath.c b/make/src/native/fixpath.c index 35c5e22ee8f..73927d4fcca 100644 --- a/make/src/native/fixpath.c +++ b/make/src/native/fixpath.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ void report_error(char const * msg) { - LPVOID lpMsgBuf; + LPTSTR lpMsgBuf; DWORD dw = GetLastError(); FormatMessage( diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index 0fc26ff6131..4ab8c7103a5 100644 --- a/make/test/BuildMicrobenchmark.gmk +++ b/make/test/BuildMicrobenchmark.gmk @@ -90,11 +90,11 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \ SMALL_JAVA := false, \ CLASSPATH := $(MICROBENCHMARK_CLASSPATH), \ - DISABLED_WARNINGS := processing rawtypes unchecked cast serial deprecation, \ - JAVAC_FLAGS := -XDallowWithFieldOperator, \ + DISABLED_WARNINGS := processing rawtypes unchecked cast serial preview deprecation, \ SRC := $(MICROBENCHMARK_SRC), \ BIN := $(MICROBENCHMARK_CLASSES), \ JAVA_FLAGS := --add-modules jdk.unsupported --limit-modules java.management, \ + JAVAC_FLAGS := -XDallowWithFieldOperator --enable-preview, \ )) $(BUILD_JDK_MICROBENCHMARK): $(JMH_COMPILE_JARS) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 6f04f922c82..2ffa6b24626 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -2179,20 +2179,34 @@ int MacroAssembler::push_fp(unsigned int bitset, Register stack) { regs[count++] = reg; bitset >>= 1; } - regs[count++] = zr->encoding_nocheck(); - count &= ~1; // Only push an even number of regs - // Always pushing full 128 bit registers. - if (count) { - stpq(as_FloatRegister(regs[0]), as_FloatRegister(regs[1]), Address(pre(stack, -count * wordSize * 2))); - words_pushed += 2; + if (count == 0) { + return 0; } - for (int i = 2; i < count; i += 2) { + + if (count == 1) { + strq(as_FloatRegister(regs[0]), Address(pre(stack, -wordSize * 2))); + return 1; + } + + bool odd = (count & 1) == 1; + int push_slots = count + (odd ? 1 : 0); + + // Always pushing full 128 bit registers. + stpq(as_FloatRegister(regs[0]), as_FloatRegister(regs[1]), Address(pre(stack, -push_slots * wordSize * 2))); + words_pushed += 2; + + for (int i = 2; i + 1 < count; i += 2) { stpq(as_FloatRegister(regs[i]), as_FloatRegister(regs[i+1]), Address(stack, i * wordSize * 2)); words_pushed += 2; } - assert(words_pushed == count, "oops, pushed != count"); + if (odd) { + strq(as_FloatRegister(regs[count - 1]), Address(stack, (count - 1) * wordSize * 2)); + words_pushed++; + } + + assert(words_pushed == count, "oops, pushed(%d) != count(%d)", words_pushed, count); return count; } @@ -2207,19 +2221,33 @@ int MacroAssembler::pop_fp(unsigned int bitset, Register stack) { regs[count++] = reg; bitset >>= 1; } - regs[count++] = zr->encoding_nocheck(); - count &= ~1; - for (int i = 2; i < count; i += 2) { - ldpq(as_FloatRegister(regs[i]), as_FloatRegister(regs[i+1]), Address(stack, i * wordSize * 2)); - words_pushed += 2; + if (count == 0) { + return 0; } - if (count) { - ldpq(as_FloatRegister(regs[0]), as_FloatRegister(regs[1]), Address(post(stack, count * wordSize * 2))); + + if (count == 1) { + ldrq(as_FloatRegister(regs[0]), Address(post(stack, wordSize * 2))); + return 1; + } + + bool odd = (count & 1) == 1; + int push_slots = count + (odd ? 1 : 0); + + if (odd) { + ldrq(as_FloatRegister(regs[count - 1]), Address(stack, (count - 1) * wordSize * 2)); + words_pushed++; + } + + for (int i = 2; i + 1 < count; i += 2) { + ldpq(as_FloatRegister(regs[i]), as_FloatRegister(regs[i+1]), Address(stack, i * wordSize * 2)); words_pushed += 2; } - assert(words_pushed == count, "oops, pushed != count"); + ldpq(as_FloatRegister(regs[0]), as_FloatRegister(regs[1]), Address(post(stack, push_slots * wordSize * 2))); + words_pushed += 2; + + assert(words_pushed == count, "oops, pushed(%d) != count(%d)", words_pushed, count); return count; } diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp index fcdfb30af67..931632a512d 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2018 SAP SE. All rights reserved. + * Copyright (c) 2012, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include "gc/shared/barrierSetAssembler.hpp" #include "interp_masm_ppc.hpp" #include "interpreter/interpreterRuntime.hpp" +#include "oops/methodData.hpp" #include "prims/jvmtiThreadState.hpp" #include "runtime/frame.inline.hpp" #include "runtime/safepointMechanism.hpp" diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index 089034e4d38..2f4cc7be680 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, 2017 SAP SE. All rights reserved. + * Copyright (c) 2013, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ #include "interpreter/templateTable.hpp" #include "memory/universe.hpp" #include "oops/klass.inline.hpp" +#include "oops/methodData.hpp" #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/methodHandles.hpp" diff --git a/src/hotspot/cpu/s390/interp_masm_s390.cpp b/src/hotspot/cpu/s390/interp_masm_s390.cpp index 766273af583..d71398163ff 100644 --- a/src/hotspot/cpu/s390/interp_masm_s390.cpp +++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2019 SAP SE. All rights reserved. + * Copyright (c) 2016, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ #include "interpreter/interpreterRuntime.hpp" #include "oops/arrayOop.hpp" #include "oops/markWord.hpp" +#include "oops/methodData.hpp" #include "prims/jvmtiExport.hpp" #include "prims/jvmtiThreadState.hpp" #include "runtime/basicLock.hpp" diff --git a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp index 7385081f8e3..54c65f593b4 100644 --- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2019, SAP SE. All rights reserved. + * Copyright (c) 2016, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ #include "interpreter/templateInterpreterGenerator.hpp" #include "interpreter/templateTable.hpp" #include "oops/arrayOop.hpp" +#include "oops/methodData.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "prims/jvmtiThreadState.hpp" diff --git a/src/hotspot/cpu/s390/templateTable_s390.cpp b/src/hotspot/cpu/s390/templateTable_s390.cpp index 1b4a7494010..67a70c94b2b 100644 --- a/src/hotspot/cpu/s390/templateTable_s390.cpp +++ b/src/hotspot/cpu/s390/templateTable_s390.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2018 SAP SE. All rights reserved. + * Copyright (c) 2016, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include "interpreter/interp_masm.hpp" #include "interpreter/templateTable.hpp" #include "memory/universe.hpp" +#include "oops/methodData.hpp" #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/methodHandles.hpp" diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 17110dddaed..1b8fcc378ee 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -3950,14 +3950,11 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha #ifndef _WINDOWS -#define ASM_SUBTRACT - -#ifdef ASM_SUBTRACT // Subtract 0:b from carry:a. Return carry. -static unsigned long -sub(unsigned long a[], unsigned long b[], unsigned long carry, long len) { - long i = 0, cnt = len; - unsigned long tmp; +static julong +sub(julong a[], julong b[], julong carry, long len) { + long long i = 0, cnt = len; + julong tmp; asm volatile("clc; " "0: ; " "mov (%[b], %[i], 8), %[tmp]; " @@ -3970,24 +3967,6 @@ sub(unsigned long a[], unsigned long b[], unsigned long carry, long len) { : "memory"); return tmp; } -#else // ASM_SUBTRACT -typedef int __attribute__((mode(TI))) int128; - -// Subtract 0:b from carry:a. Return carry. -static unsigned long -sub(unsigned long a[], unsigned long b[], unsigned long carry, int len) { - int128 tmp = 0; - int i; - for (i = 0; i < len; i++) { - tmp += a[i]; - tmp -= b[i]; - a[i] = tmp; - tmp >>= 64; - assert(-1 <= tmp && tmp <= 0, "invariant"); - } - return tmp + carry; -} -#endif // ! ASM_SUBTRACT // Multiply (unsigned) Long A by Long B, accumulating the double- // length result into the accumulator formed of T0, T1, and T2. @@ -4010,17 +3989,59 @@ do { \ : "r"(A), "a"(B) : "cc"); \ } while(0) +#else //_WINDOWS + +static julong +sub(julong a[], julong b[], julong carry, long len) { + long i; + julong tmp; + unsigned char c = 1; + for (i = 0; i < len; i++) { + c = _addcarry_u64(c, a[i], ~b[i], &tmp); + a[i] = tmp; + } + c = _addcarry_u64(c, carry, ~0, &tmp); + return tmp; +} + +// Multiply (unsigned) Long A by Long B, accumulating the double- +// length result into the accumulator formed of T0, T1, and T2. +#define MACC(A, B, T0, T1, T2) \ +do { \ + julong hi, lo; \ + lo = _umul128(A, B, &hi); \ + unsigned char c = _addcarry_u64(0, lo, T0, &T0); \ + c = _addcarry_u64(c, hi, T1, &T1); \ + _addcarry_u64(c, T2, 0, &T2); \ + } while(0) + +// As above, but add twice the double-length result into the +// accumulator. +#define MACC2(A, B, T0, T1, T2) \ +do { \ + julong hi, lo; \ + lo = _umul128(A, B, &hi); \ + unsigned char c = _addcarry_u64(0, lo, T0, &T0); \ + c = _addcarry_u64(c, hi, T1, &T1); \ + _addcarry_u64(c, T2, 0, &T2); \ + c = _addcarry_u64(0, lo, T0, &T0); \ + c = _addcarry_u64(c, hi, T1, &T1); \ + _addcarry_u64(c, T2, 0, &T2); \ + } while(0) + +#endif //_WINDOWS + // Fast Montgomery multiplication. The derivation of the algorithm is // in A Cryptographic Library for the Motorola DSP56000, // Dusse and Kaliski, Proc. EUROCRYPT 90, pp. 230-237. -static void __attribute__((noinline)) -montgomery_multiply(unsigned long a[], unsigned long b[], unsigned long n[], - unsigned long m[], unsigned long inv, int len) { - unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator +static void NOINLINE +montgomery_multiply(julong a[], julong b[], julong n[], + julong m[], julong inv, int len) { + julong t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator int i; - assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply"); + assert(inv * n[0] == ULLONG_MAX, "broken inverse in Montgomery multiply"); for (i = 0; i < len; i++) { int j; @@ -4056,13 +4077,13 @@ montgomery_multiply(unsigned long a[], unsigned long b[], unsigned long n[], // multiplication. However, its loop control is more complex and it // may actually run slower on some machines. -static void __attribute__((noinline)) -montgomery_square(unsigned long a[], unsigned long n[], - unsigned long m[], unsigned long inv, int len) { - unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator +static void NOINLINE +montgomery_square(julong a[], julong n[], + julong m[], julong inv, int len) { + julong t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator int i; - assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply"); + assert(inv * n[0] == ULLONG_MAX, "broken inverse in Montgomery square"); for (i = 0; i < len; i++) { int j; @@ -4108,13 +4129,13 @@ montgomery_square(unsigned long a[], unsigned long n[], } // Swap words in a longword. -static unsigned long swap(unsigned long x) { +static julong swap(julong x) { return (x << 32) | (x >> 32); } // Copy len longwords from s to d, word-swapping as we go. The // destination array is reversed. -static void reverse_words(unsigned long *s, unsigned long *d, int len) { +static void reverse_words(julong *s, julong *d, int len) { d += len; while(len-- > 0) { d--; @@ -4136,24 +4157,24 @@ void SharedRuntime::montgomery_multiply(jint *a_ints, jint *b_ints, jint *n_ints // Make very sure we don't use so much space that the stack might // overflow. 512 jints corresponds to an 16384-bit integer and // will use here a total of 8k bytes of stack space. - int total_allocation = longwords * sizeof (unsigned long) * 4; + int total_allocation = longwords * sizeof (julong) * 4; guarantee(total_allocation <= 8192, "must be"); - unsigned long *scratch = (unsigned long *)alloca(total_allocation); + julong *scratch = (julong *)alloca(total_allocation); // Local scratch arrays - unsigned long + julong *a = scratch + 0 * longwords, *b = scratch + 1 * longwords, *n = scratch + 2 * longwords, *m = scratch + 3 * longwords; - reverse_words((unsigned long *)a_ints, a, longwords); - reverse_words((unsigned long *)b_ints, b, longwords); - reverse_words((unsigned long *)n_ints, n, longwords); + reverse_words((julong *)a_ints, a, longwords); + reverse_words((julong *)b_ints, b, longwords); + reverse_words((julong *)n_ints, n, longwords); - ::montgomery_multiply(a, b, n, m, (unsigned long)inv, longwords); + ::montgomery_multiply(a, b, n, m, (julong)inv, longwords); - reverse_words(m, (unsigned long *)m_ints, longwords); + reverse_words(m, (julong *)m_ints, longwords); } void SharedRuntime::montgomery_square(jint *a_ints, jint *n_ints, @@ -4165,30 +4186,28 @@ void SharedRuntime::montgomery_square(jint *a_ints, jint *n_ints, // Make very sure we don't use so much space that the stack might // overflow. 512 jints corresponds to an 16384-bit integer and // will use here a total of 6k bytes of stack space. - int total_allocation = longwords * sizeof (unsigned long) * 3; + int total_allocation = longwords * sizeof (julong) * 3; guarantee(total_allocation <= 8192, "must be"); - unsigned long *scratch = (unsigned long *)alloca(total_allocation); + julong *scratch = (julong *)alloca(total_allocation); // Local scratch arrays - unsigned long + julong *a = scratch + 0 * longwords, *n = scratch + 1 * longwords, *m = scratch + 2 * longwords; - reverse_words((unsigned long *)a_ints, a, longwords); - reverse_words((unsigned long *)n_ints, n, longwords); + reverse_words((julong *)a_ints, a, longwords); + reverse_words((julong *)n_ints, n, longwords); if (len >= MONTGOMERY_SQUARING_THRESHOLD) { - ::montgomery_square(a, n, m, (unsigned long)inv, longwords); + ::montgomery_square(a, n, m, (julong)inv, longwords); } else { - ::montgomery_multiply(a, a, n, m, (unsigned long)inv, longwords); + ::montgomery_multiply(a, a, n, m, (julong)inv, longwords); } - reverse_words(m, (unsigned long *)m_ints, longwords); + reverse_words(m, (julong *)m_ints, longwords); } -#endif // WINDOWS - #ifdef COMPILER2 // This is here instead of runtime_x86_64.cpp because it uses SimpleRuntimeFrame // diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 69b1ba84798..19ff2cc9e4e 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -6724,7 +6724,6 @@ address generate_avx_ghash_processBlocks() { StubRoutines::_bigIntegerRightShiftWorker = generate_bigIntegerRightShift(); StubRoutines::_bigIntegerLeftShiftWorker = generate_bigIntegerLeftShift(); } -#ifndef _WINDOWS if (UseMontgomeryMultiplyIntrinsic) { StubRoutines::_montgomeryMultiply = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_multiply); @@ -6733,7 +6732,6 @@ address generate_avx_ghash_processBlocks() { StubRoutines::_montgomerySquare = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_square); } -#endif // WINDOWS #endif // COMPILER2 if (UseVectorizedMismatchIntrinsic) { diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 14a9f1028e8..188c66bef01 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1507,6 +1507,12 @@ void VM_Version::get_processor_features() { // Modern processors allow misaligned memory operations for vectors. AlignVector = !UseUnalignedLoadStores; } + if (FLAG_IS_DEFAULT(OptimizeFill)) { + // 8247307: On x86, the auto-vectorized loop array fill code shows + // better performance than the array fill stubs. We should reenable + // this after the x86 stubs get improved. + OptimizeFill = false; + } #endif // COMPILER2 if (FLAG_IS_DEFAULT(AllocatePrefetchInstr)) { diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index ff13754d113..64face5268a 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -53,7 +53,6 @@ #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/globals.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -2704,7 +2703,7 @@ OSReturn os::get_native_priority(const Thread* const thread, int *priority_ptr) // The SR_lock is, however, used by JavaThread::java_suspend()/java_resume() APIs. // // Note that resume_clear_context() and suspend_save_context() are needed -// by SR_handler(), so that fetch_frame_from_ucontext() works, +// by SR_handler(), so that fetch_frame_from_context() works, // which in part is used by: // - Forte Analyzer: AsyncGetCallTrace() // - StackBanging: get_frame_at_stack_banging_point() diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 84e1e0ca465..57cfe91509a 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -44,7 +44,6 @@ #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/globals.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -2330,7 +2329,7 @@ OSReturn os::get_native_priority(const Thread* const thread, int *priority_ptr) // The SR_lock is, however, used by JavaThread::java_suspend()/java_resume() APIs. // // Note that resume_clear_context() and suspend_save_context() are needed -// by SR_handler(), so that fetch_frame_from_ucontext() works, +// by SR_handler(), so that fetch_frame_from_context() works, // which in part is used by: // - Forte Analyzer: AsyncGetCallTrace() // - StackBanging: get_frame_at_stack_banging_point() diff --git a/src/hotspot/os/bsd/os_bsd.hpp b/src/hotspot/os/bsd/os_bsd.hpp index c9afcdad10f..f894dd2fb9e 100644 --- a/src/hotspot/os/bsd/os_bsd.hpp +++ b/src/hotspot/os/bsd/os_bsd.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,14 +82,6 @@ class Bsd { static intptr_t* ucontext_get_sp(const ucontext_t* uc); static intptr_t* ucontext_get_fp(const ucontext_t* uc); - // For Analyzer Forte AsyncGetCallTrace profiling support: - // - // This interface should be declared in os_bsd_i486.hpp, but - // that file provides extensions to the os class and not the - // Bsd class. - static ExtendedPC fetch_frame_from_ucontext(Thread* thread, const ucontext_t* uc, - intptr_t** ret_sp, intptr_t** ret_fp); - static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr); // This boolean allows users to forward their own non-matching signals diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 6176d6faa18..b08caf4d5d3 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -45,7 +45,6 @@ #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/globals.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/init.hpp" @@ -4482,7 +4481,7 @@ OSReturn os::get_native_priority(const Thread* const thread, // The SR_lock is, however, used by JavaThread::java_suspend()/java_resume() APIs. // // Note that resume_clear_context() and suspend_save_context() are needed -// by SR_handler(), so that fetch_frame_from_ucontext() works, +// by SR_handler(), so that fetch_frame_from_context() works, // which in part is used by: // - Forte Analyzer: AsyncGetCallTrace() // - StackBanging: get_frame_at_stack_banging_point() diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index 0687d03012b..754773a7d61 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -145,14 +145,6 @@ class Linux { static intptr_t* ucontext_get_sp(const ucontext_t* uc); static intptr_t* ucontext_get_fp(const ucontext_t* uc); - // For Analyzer Forte AsyncGetCallTrace profiling support: - // - // This interface should be declared in os_linux_i486.hpp, but - // that file provides extensions to the os class and not the - // Linux class. - static ExtendedPC fetch_frame_from_ucontext(Thread* thread, const ucontext_t* uc, - intptr_t** ret_sp, intptr_t** ret_fp); - static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr); // This boolean allows users to forward their own non-matching signals diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index be2ea26ddcf..698407b7807 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -46,7 +46,6 @@ #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/globals.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp index 9e3438e8f74..e5e4bbc434e 100644 --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp @@ -40,7 +40,6 @@ #include "prims/jvm_misc.hpp" #include "porting_aix.hpp" #include "runtime/arguments.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -110,19 +109,18 @@ static address ucontext_get_lr(const ucontext_t * uc) { return (address)uc->uc_mcontext.jmp_context.lr; } -ExtendedPC os::fetch_frame_from_context(const void* ucVoid, - intptr_t** ret_sp, intptr_t** ret_fp) { +address os::fetch_frame_from_context(const void* ucVoid, + intptr_t** ret_sp, intptr_t** ret_fp) { - ExtendedPC epc; + address epc; const ucontext_t* uc = (const ucontext_t*)ucVoid; if (uc != NULL) { - epc = ExtendedPC(os::Aix::ucontext_get_pc(uc)); + epc = os::Aix::ucontext_get_pc(uc); if (ret_sp) *ret_sp = os::Aix::ucontext_get_sp(uc); if (ret_fp) *ret_fp = os::Aix::ucontext_get_fp(uc); } else { - // construct empty ExtendedPC for return value checking - epc = ExtendedPC(NULL); + epc = NULL; if (ret_sp) *ret_sp = (intptr_t *)NULL; if (ret_fp) *ret_fp = (intptr_t *)NULL; } @@ -133,10 +131,10 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, frame os::fetch_frame_from_context(const void* ucVoid) { intptr_t* sp; intptr_t* fp; - ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); + address epc = fetch_frame_from_context(ucVoid, &sp, &fp); // Avoid crash during crash if pc broken. - if (epc.pc()) { - frame fr(sp, epc.pc()); + if (epc) { + frame fr(sp, epc); return fr; } frame fr(sp); diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp index 69621b8e712..51e69ea9247 100644 --- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp @@ -38,7 +38,6 @@ #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -313,35 +312,18 @@ intptr_t* os::Bsd::ucontext_get_fp(const ucontext_t * uc) { return (intptr_t*)uc->context_fp; } -// For Forte Analyzer AsyncGetCallTrace profiling support - thread -// is currently interrupted by SIGPROF. -// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal -// frames. Currently we don't do that on Bsd, so it's the same as -// os::fetch_frame_from_context(). -// This method is also used for stack overflow signal handling. -ExtendedPC os::Bsd::fetch_frame_from_ucontext(Thread* thread, - const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { - - assert(thread != NULL, "just checking"); - assert(ret_sp != NULL, "just checking"); - assert(ret_fp != NULL, "just checking"); - - return os::fetch_frame_from_context(uc, ret_sp, ret_fp); -} - -ExtendedPC os::fetch_frame_from_context(const void* ucVoid, +address os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { - ExtendedPC epc; + address epc; const ucontext_t* uc = (const ucontext_t*)ucVoid; if (uc != NULL) { - epc = ExtendedPC(os::Bsd::ucontext_get_pc(uc)); + epc = os::Bsd::ucontext_get_pc(uc); if (ret_sp) *ret_sp = os::Bsd::ucontext_get_sp(uc); if (ret_fp) *ret_fp = os::Bsd::ucontext_get_fp(uc); } else { - // construct empty ExtendedPC for return value checking - epc = ExtendedPC(NULL); + epc = NULL; if (ret_sp) *ret_sp = (intptr_t *)NULL; if (ret_fp) *ret_fp = (intptr_t *)NULL; } @@ -352,15 +334,8 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, frame os::fetch_frame_from_context(const void* ucVoid) { intptr_t* sp; intptr_t* fp; - ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); - return frame(sp, fp, epc.pc()); -} - -frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) { - intptr_t* sp; - intptr_t* fp; - ExtendedPC epc = os::Bsd::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, &fp); - return frame(sp, fp, epc.pc()); + address epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, fp, epc); } bool os::Bsd::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { @@ -370,7 +345,7 @@ bool os::Bsd::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* u // been generated while the compilers perform it before. To maintain // semantic consistency between interpreted and compiled frames, the // method returns the Java sender of the current frame. - *fr = os::fetch_frame_from_ucontext(thread, uc); + *fr = os::fetch_frame_from_context(uc); if (!fr->is_first_java_frame()) { // get_frame_at_stack_banging_point() is only called when we // have well defined stacks so java_sender() calls do not need @@ -386,7 +361,7 @@ bool os::Bsd::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* u // stack overflow handling return false; } else { - *fr = os::fetch_frame_from_ucontext(thread, uc); + *fr = os::fetch_frame_from_context(uc); // in compiled code, the stack banging is performed just after the return pc // has been pushed on the stack *fr = frame(fr->sp() + 1, fr->fp(), (address)*(fr->sp())); diff --git a/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp index 2d64def4801..3522cad9e1f 100644 --- a/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,24 +64,23 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) intptr_t* ret_fp; intptr_t* ret_sp; - ExtendedPC addr = os::Bsd::fetch_frame_from_ucontext(this, uc, - &ret_sp, &ret_fp); - if (addr.pc() == NULL || ret_sp == NULL ) { + address addr = os::fetch_frame_from_context(uc, &ret_sp, &ret_fp); + if (addr == NULL || ret_sp == NULL ) { // ucontext wasn't useful return false; } - if (MetaspaceShared::is_in_trampoline_frame(addr.pc())) { + if (MetaspaceShared::is_in_trampoline_frame(addr)) { // In the middle of a trampoline call. Bail out for safety. // This happens rarely so shouldn't affect profiling. return false; } - frame ret_frame(ret_sp, ret_fp, addr.pc()); + frame ret_frame(ret_sp, ret_fp, addr); if (!ret_frame.safe_for_sender(jt)) { #if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps - frame ret_frame2(ret_sp, NULL, addr.pc()); + frame ret_frame2(ret_sp, NULL, addr); if (!ret_frame2.safe_for_sender(jt)) { // nothing else to try if the frame isn't good return false; diff --git a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp index 4c21793f99a..4db293eca15 100644 --- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp +++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp @@ -43,7 +43,6 @@ #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -103,11 +102,11 @@ void os::Bsd::ucontext_set_pc(ucontext_t * uc, address pc) { ShouldNotCallThis(); } -ExtendedPC os::fetch_frame_from_context(const void* ucVoid, - intptr_t** ret_sp, - intptr_t** ret_fp) { +address os::fetch_frame_from_context(const void* ucVoid, + intptr_t** ret_sp, + intptr_t** ret_fp) { ShouldNotCallThis(); - return ExtendedPC(); + return NULL; } frame os::fetch_frame_from_context(const void* ucVoid) { diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp index ecd05e70d13..0075e7e841c 100644 --- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp @@ -39,7 +39,6 @@ #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -108,34 +107,18 @@ intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) { return (intptr_t*)uc->uc_mcontext.regs[REG_FP]; } -// For Forte Analyzer AsyncGetCallTrace profiling support - thread -// is currently interrupted by SIGPROF. -// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal -// frames. Currently we don't do that on Linux, so it's the same as -// os::fetch_frame_from_context(). -ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread, - const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { - - assert(thread != NULL, "just checking"); - assert(ret_sp != NULL, "just checking"); - assert(ret_fp != NULL, "just checking"); - - return os::fetch_frame_from_context(uc, ret_sp, ret_fp); -} - -ExtendedPC os::fetch_frame_from_context(const void* ucVoid, +address os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { - ExtendedPC epc; + address epc; const ucontext_t* uc = (const ucontext_t*)ucVoid; if (uc != NULL) { - epc = ExtendedPC(os::Linux::ucontext_get_pc(uc)); + epc = os::Linux::ucontext_get_pc(uc); if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc); if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc); } else { - // construct empty ExtendedPC for return value checking - epc = ExtendedPC(NULL); + epc = NULL; if (ret_sp) *ret_sp = (intptr_t *)NULL; if (ret_fp) *ret_fp = (intptr_t *)NULL; } @@ -146,8 +129,8 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, frame os::fetch_frame_from_context(const void* ucVoid) { intptr_t* sp; intptr_t* fp; - ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); - return frame(sp, fp, epc.pc()); + address epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, fp, epc); } bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { diff --git a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp index 9084daeaa2e..c09244ed754 100644 --- a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -65,23 +65,22 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) intptr_t* ret_fp; intptr_t* ret_sp; - ExtendedPC addr = os::Linux::fetch_frame_from_ucontext(this, uc, - &ret_sp, &ret_fp); - if (addr.pc() == NULL || ret_sp == NULL ) { + address addr = os::fetch_frame_from_context(uc, &ret_sp, &ret_fp); + if (addr == NULL || ret_sp == NULL ) { // ucontext wasn't useful return false; } - if (MetaspaceShared::is_in_trampoline_frame(addr.pc())) { + if (MetaspaceShared::is_in_trampoline_frame(addr)) { // In the middle of a trampoline call. Bail out for safety. // This happens rarely so shouldn't affect profiling. return false; } - frame ret_frame(ret_sp, ret_fp, addr.pc()); + frame ret_frame(ret_sp, ret_fp, addr); if (!ret_frame.safe_for_sender(jt)) { #ifdef COMPILER2 - frame ret_frame2(ret_sp, NULL, addr.pc()); + frame ret_frame2(ret_sp, NULL, addr); if (!ret_frame2.safe_for_sender(jt)) { // nothing else to try if the frame isn't good return false; diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp index 4a5b5337e85..eb54fd091da 100644 --- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp @@ -37,7 +37,6 @@ #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -142,34 +141,19 @@ bool is_safe_for_fp(address pc) { #endif } -// For Forte Analyzer AsyncGetCallTrace profiling support - thread -// is currently interrupted by SIGPROF. -// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal -// frames. Currently we don't do that on Linux, so it's the same as -// os::fetch_frame_from_context(). -ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread, - const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { - - assert(thread != NULL, "just checking"); - assert(ret_sp != NULL, "just checking"); - assert(ret_fp != NULL, "just checking"); - - return os::fetch_frame_from_context(uc, ret_sp, ret_fp); -} - -ExtendedPC os::fetch_frame_from_context(const void* ucVoid, +address os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { - ExtendedPC epc; + address epc; const ucontext_t* uc = (const ucontext_t*)ucVoid; if (uc != NULL) { - epc = ExtendedPC(os::Linux::ucontext_get_pc(uc)); + epc = os::Linux::ucontext_get_pc(uc); if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc); if (ret_fp) { intptr_t* fp = os::Linux::ucontext_get_fp(uc); #ifndef __thumb__ - if (CodeCache::find_blob(epc.pc()) == NULL) { + if (CodeCache::find_blob(epc) == NULL) { // It's a C frame. We need to adjust the fp. fp += os::C_frame_offset; } @@ -178,15 +162,14 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, // the frame created will not be walked. // However, ensure FP is set correctly when reliable and // potentially necessary. - if (!is_safe_for_fp(epc.pc())) { + if (!is_safe_for_fp(epc)) { // FP unreliable fp = (intptr_t *)NULL; } *ret_fp = fp; } } else { - // construct empty ExtendedPC for return value checking - epc = ExtendedPC(NULL); + epc = NULL; if (ret_sp) *ret_sp = (intptr_t *)NULL; if (ret_fp) *ret_fp = (intptr_t *)NULL; } @@ -197,8 +180,8 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, frame os::fetch_frame_from_context(const void* ucVoid) { intptr_t* sp; intptr_t* fp; - ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); - return frame(sp, fp, epc.pc()); + address epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, fp, epc); } frame os::get_sender_for_C_frame(frame* fr) { diff --git a/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp index d7752d63717..8776e9198bc 100644 --- a/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,24 +99,23 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) intptr_t* ret_fp; intptr_t* ret_sp; - ExtendedPC addr = os::Linux::fetch_frame_from_ucontext(this, uc, - &ret_sp, &ret_fp); - if (addr.pc() == NULL || ret_sp == NULL ) { + address addr = os::fetch_frame_from_context(uc, &ret_sp, &ret_fp); + if (addr == NULL || ret_sp == NULL ) { // ucontext wasn't useful return false; } - if (MetaspaceShared::is_in_trampoline_frame(addr.pc())) { + if (MetaspaceShared::is_in_trampoline_frame(addr)) { // In the middle of a trampoline call. Bail out for safety. // This happens rarely so shouldn't affect profiling. return false; } - frame ret_frame(ret_sp, ret_fp, addr.pc()); + frame ret_frame(ret_sp, ret_fp, addr); if (!ret_frame.safe_for_sender(jt)) { #ifdef COMPILER2 // C2 uses ebp as a general register see if NULL fp helps - frame ret_frame2(ret_sp, NULL, addr.pc()); + frame ret_frame2(ret_sp, NULL, addr); if (!ret_frame2.safe_for_sender(jt)) { // nothing else to try if the frame isn't good return false; diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp index 50c77a96f65..0f5251df602 100644 --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp @@ -39,7 +39,6 @@ #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -136,19 +135,18 @@ static unsigned long ucontext_get_trap(const ucontext_t * uc) { return uc->uc_mcontext.regs->trap; } -ExtendedPC os::fetch_frame_from_context(const void* ucVoid, +address os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { - ExtendedPC epc; + address epc; const ucontext_t* uc = (const ucontext_t*)ucVoid; if (uc != NULL) { - epc = ExtendedPC(os::Linux::ucontext_get_pc(uc)); + epc = os::Linux::ucontext_get_pc(uc); if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc); if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc); } else { - // construct empty ExtendedPC for return value checking - epc = ExtendedPC(NULL); + epc = NULL; if (ret_sp) *ret_sp = (intptr_t *)NULL; if (ret_fp) *ret_fp = (intptr_t *)NULL; } @@ -159,8 +157,8 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, frame os::fetch_frame_from_context(const void* ucVoid) { intptr_t* sp; intptr_t* fp; - ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); - return frame(sp, epc.pc()); + address epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, epc); } bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp index 316b83a9f43..e803c6fdce8 100644 --- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp @@ -42,7 +42,6 @@ #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -119,19 +118,18 @@ intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) { return NULL; } -ExtendedPC os::fetch_frame_from_context(const void* ucVoid, +address os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { - ExtendedPC epc; + address epc; const ucontext_t* uc = (const ucontext_t*)ucVoid; if (uc != NULL) { - epc = ExtendedPC(os::Linux::ucontext_get_pc(uc)); + epc = os::Linux::ucontext_get_pc(uc); if (ret_sp) { *ret_sp = os::Linux::ucontext_get_sp(uc); } if (ret_fp) { *ret_fp = os::Linux::ucontext_get_fp(uc); } } else { - // Construct empty ExtendedPC for return value checking. - epc = ExtendedPC(NULL); + epc = NULL; if (ret_sp) { *ret_sp = (intptr_t *)NULL; } if (ret_fp) { *ret_fp = (intptr_t *)NULL; } } @@ -142,8 +140,8 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, frame os::fetch_frame_from_context(const void* ucVoid) { intptr_t* sp; intptr_t* fp; - ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); - return frame(sp, epc.pc()); + address epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, epc); } bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index fd441e61ed1..a902d938373 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -38,7 +38,6 @@ #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -122,35 +121,18 @@ intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) { return (intptr_t*)uc->uc_mcontext.gregs[REG_FP]; } -// For Forte Analyzer AsyncGetCallTrace profiling support - thread -// is currently interrupted by SIGPROF. -// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal -// frames. Currently we don't do that on Linux, so it's the same as -// os::fetch_frame_from_context(). -// This method is also used for stack overflow signal handling. -ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread, - const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { - - assert(thread != NULL, "just checking"); - assert(ret_sp != NULL, "just checking"); - assert(ret_fp != NULL, "just checking"); - - return os::fetch_frame_from_context(uc, ret_sp, ret_fp); -} - -ExtendedPC os::fetch_frame_from_context(const void* ucVoid, +address os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { - ExtendedPC epc; + address epc; const ucontext_t* uc = (const ucontext_t*)ucVoid; if (uc != NULL) { - epc = ExtendedPC(os::Linux::ucontext_get_pc(uc)); + epc = os::Linux::ucontext_get_pc(uc); if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc); if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc); } else { - // construct empty ExtendedPC for return value checking - epc = ExtendedPC(NULL); + epc = NULL; if (ret_sp) *ret_sp = (intptr_t *)NULL; if (ret_fp) *ret_fp = (intptr_t *)NULL; } @@ -161,15 +143,8 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, frame os::fetch_frame_from_context(const void* ucVoid) { intptr_t* sp; intptr_t* fp; - ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); - return frame(sp, fp, epc.pc()); -} - -frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) { - intptr_t* sp; - intptr_t* fp; - ExtendedPC epc = os::Linux::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, &fp); - return frame(sp, fp, epc.pc()); + address epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, fp, epc); } bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { @@ -179,7 +154,7 @@ bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* // been generated while the compilers perform it before. To maintain // semantic consistency between interpreted and compiled frames, the // method returns the Java sender of the current frame. - *fr = os::fetch_frame_from_ucontext(thread, uc); + *fr = os::fetch_frame_from_context(uc); if (!fr->is_first_java_frame()) { // get_frame_at_stack_banging_point() is only called when we // have well defined stacks so java_sender() calls do not need diff --git a/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp index 68e08761b8c..f2e5ef10310 100644 --- a/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,24 +65,23 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) intptr_t* ret_fp; intptr_t* ret_sp; - ExtendedPC addr = os::Linux::fetch_frame_from_ucontext(this, uc, - &ret_sp, &ret_fp); - if (addr.pc() == NULL || ret_sp == NULL ) { + address addr = os::fetch_frame_from_context(uc, &ret_sp, &ret_fp); + if (addr == NULL || ret_sp == NULL ) { // ucontext wasn't useful return false; } - if (MetaspaceShared::is_in_trampoline_frame(addr.pc())) { + if (MetaspaceShared::is_in_trampoline_frame(addr)) { // In the middle of a trampoline call. Bail out for safety. // This happens rarely so shouldn't affect profiling. return false; } - frame ret_frame(ret_sp, ret_fp, addr.pc()); + frame ret_frame(ret_sp, ret_fp, addr); if (!ret_frame.safe_for_sender(jt)) { #if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps - frame ret_frame2(ret_sp, NULL, addr.pc()); + frame ret_frame2(ret_sp, NULL, addr); if (!ret_frame2.safe_for_sender(jt)) { // nothing else to try if the frame isn't good return false; diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp index d431d96dda1..d9e2382bf2c 100644 --- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp +++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp @@ -38,7 +38,6 @@ #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -99,9 +98,9 @@ void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) { ShouldNotCallThis(); } -ExtendedPC os::fetch_frame_from_context(const void* ucVoid, - intptr_t** ret_sp, - intptr_t** ret_fp) { +address os::fetch_frame_from_context(const void* ucVoid, + intptr_t** ret_sp, + intptr_t** ret_fp) { ShouldNotCallThis(); return NULL; // silence compile warnings } diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp index 77309f0331a..2e7e7ed6d41 100644 --- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp +++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2010, 2018, Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -34,6 +34,19 @@ // Note: Currently only used in 64 bit Windows implementations static bool register_code_area(char *low, char *high) { return true; } + /* + * Work-around for broken NX emulation using CS limit, Red Hat patch "Exec-Shield" + * (IA32 only). + * + * Map and execute at a high VA to prevent CS lazy updates race with SMP MM + * invalidation.Further code generation by the JVM will no longer cause CS limit + * updates. + * + * Affects IA32: RHEL 5 & 6, Ubuntu 10.04 (LTS), 10.10, 11.04, 11.10, 12.04. + * @see JDK-8023956 + */ + static void workaround_expand_exec_shield_cs_limit(); + // Atomically copy 64 bits of data static void atomic_copy64(const volatile void *src, volatile void *dst) { #if defined(PPC32) && !defined(__SPE__) diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp index cbfec96405a..878ea3da9ef 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,6 @@ #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" -#include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" @@ -430,19 +429,18 @@ bool os::platform_print_native_stack(outputStream* st, const void* context, } #endif // AMD64 -ExtendedPC os::fetch_frame_from_context(const void* ucVoid, +address os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { - ExtendedPC epc; + address epc; CONTEXT* uc = (CONTEXT*)ucVoid; if (uc != NULL) { - epc = ExtendedPC((address)uc->REG_PC); + epc = (address)uc->REG_PC; if (ret_sp) *ret_sp = (intptr_t*)uc->REG_SP; if (ret_fp) *ret_fp = (intptr_t*)uc->REG_FP; } else { - // construct empty ExtendedPC for return value checking - epc = ExtendedPC(NULL); + epc = NULL; if (ret_sp) *ret_sp = (intptr_t *)NULL; if (ret_fp) *ret_fp = (intptr_t *)NULL; } @@ -453,8 +451,8 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, frame os::fetch_frame_from_context(const void* ucVoid) { intptr_t* sp; intptr_t* fp; - ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); - return frame(sp, fp, epc.pc()); + address epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, fp, epc); } // VC++ does not save frame pointer on stack in optimized build. It diff --git a/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp index 69fff0318e9..7d9048c57c6 100644 --- a/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,28 +68,28 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) #ifdef AMD64 intptr_t* ret_fp = (intptr_t*) uc->Rbp; intptr_t* ret_sp = (intptr_t*) uc->Rsp; - ExtendedPC addr = ExtendedPC((address)uc->Rip); + address addr = (address)uc->Rip; #else intptr_t* ret_fp = (intptr_t*) uc->Ebp; intptr_t* ret_sp = (intptr_t*) uc->Esp; - ExtendedPC addr = ExtendedPC((address)uc->Eip); + address addr = (address)uc->Eip; #endif // AMD64 - if (addr.pc() == NULL || ret_sp == NULL ) { + if (addr == NULL || ret_sp == NULL ) { // CONTEXT wasn't useful return false; } - if (MetaspaceShared::is_in_trampoline_frame(addr.pc())) { + if (MetaspaceShared::is_in_trampoline_frame(addr)) { // In the middle of a trampoline call. Bail out for safety. // This happens rarely so shouldn't affect profiling. return false; } - frame ret_frame(ret_sp, ret_fp, addr.pc()); + frame ret_frame(ret_sp, ret_fp, addr); if (!ret_frame.safe_for_sender(jt)) { #if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps - frame ret_frame2(ret_sp, NULL, addr.pc()); + frame ret_frame2(ret_sp, NULL, addr); if (!ret_frame2.safe_for_sender(jt)) { // nothing else to try if the frame isn't good return false; diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index 03bbe731237..9f9394606ac 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -441,12 +441,11 @@ class PerfClassTraceTime { public: enum { CLASS_LOAD = 0, - PARSE_CLASS = 1, - CLASS_LINK = 2, - CLASS_VERIFY = 3, - CLASS_CLINIT = 4, - DEFINE_CLASS = 5, - EVENT_TYPE_COUNT = 6 + CLASS_LINK = 1, + CLASS_VERIFY = 2, + CLASS_CLINIT = 3, + DEFINE_CLASS = 4, + EVENT_TYPE_COUNT = 5 }; protected: // _t tracks time from initialization to destruction of this timer instance @@ -484,9 +483,6 @@ class PerfClassTraceTime { initialize(); } - inline void suspend() { _t.stop(); _timers[_event_type].stop(); } - inline void resume() { _t.start(); _timers[_event_type].start(); } - ~PerfClassTraceTime(); void initialize(); }; diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp index a7f3a245464..004af96f302 100644 --- a/src/hotspot/share/classfile/symbolTable.cpp +++ b/src/hotspot/share/classfile/symbolTable.cpp @@ -513,6 +513,13 @@ Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, boo } assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); +#if INCLUDE_CDS + if (DumpSharedSpaces) { + if (sym != NULL) { + MetaspaceShared::add_symbol(sym); + } + } +#endif return sym; } diff --git a/src/hotspot/share/code/compiledIC.cpp b/src/hotspot/share/code/compiledIC.cpp index 898b35db129..287a76bcabe 100644 --- a/src/hotspot/share/code/compiledIC.cpp +++ b/src/hotspot/share/code/compiledIC.cpp @@ -771,7 +771,9 @@ void CompiledDirectStaticCall::verify_mt_safe(const methodHandle& callee, addres "a) MT-unsafe modification of inline cache"); address destination = jump->jump_destination(); - assert(destination == (address)-1 || destination == entry, + assert(destination == (address)-1 || destination == entry + || old_method == NULL || !old_method->method_holder()->is_loader_alive() // may have a race due to class unloading. + || old_method->is_old(), // may be race patching deoptimized nmethod due to redefinition. "b) MT-unsafe modification of inline cache"); } #endif // !PRODUCT diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 79e4683e8d0..c221edcf3ba 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -1655,7 +1655,7 @@ void CompileBroker::wait_for_completion(CompileTask* task) { bool free_task; #if INCLUDE_JVMCI AbstractCompiler* comp = compiler(task->comp_level()); - if (comp->is_jvmci() && !task->should_wait_for_compilation()) { + if (!UseJVMCINativeLibrary && comp->is_jvmci() && !task->should_wait_for_compilation()) { // It may return before compilation is completed. free_task = wait_for_jvmci_completion((JVMCICompiler*) comp, task, thread); } else diff --git a/src/hotspot/share/compiler/compileTask.hpp b/src/hotspot/share/compiler/compileTask.hpp index 78f76163f7f..aca640a8e71 100644 --- a/src/hotspot/share/compiler/compileTask.hpp +++ b/src/hotspot/share/compiler/compileTask.hpp @@ -53,7 +53,7 @@ class CompileTask : public CHeapObj { Reason_CTW, // Compile the world Reason_Replay, // ciReplay Reason_Whitebox, // Whitebox API - Reason_MustBeCompiled, // Java callHelper, LinkResolver + Reason_MustBeCompiled, // Used for -Xcomp or AlwaysCompileLoopMethods (see CompilationPolicy::must_be_compiled()) Reason_Bootstrap, // JVMCI bootstrap Reason_Count }; @@ -140,7 +140,6 @@ class CompileTask : public CHeapObj { case Reason_CTW: case Reason_Replay: case Reason_Whitebox: - case Reason_MustBeCompiled: case Reason_Bootstrap: return _is_blocking; default: diff --git a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp index 533c6eaafa6..259126dd955 100644 --- a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp +++ b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp @@ -785,9 +785,8 @@ void G1BarrierSetC2::verify_gc_barriers(Compile* compile, CompilePhase phase) co // Verify G1 pre-barriers const int marking_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()); - ResourceArea *area = Thread::current()->resource_area(); - Unique_Node_List visited(area); - Node_List worklist(area); + Unique_Node_List visited; + Node_List worklist; // We're going to walk control flow backwards starting from the Root worklist.push(compile->root()); while (worklist.size() > 0) { diff --git a/src/hotspot/share/gc/g1/g1Analytics.cpp b/src/hotspot/share/gc/g1/g1Analytics.cpp index 0f1de8e1a29..c817d27a899 100644 --- a/src/hotspot/share/gc/g1/g1Analytics.cpp +++ b/src/hotspot/share/gc/g1/g1Analytics.cpp @@ -149,18 +149,14 @@ void G1Analytics::report_alloc_rate_ms(double alloc_rate) { _alloc_rate_ms_seq->add(alloc_rate); } -void G1Analytics::compute_pause_time_ratio(double interval_ms, double pause_time_ms) { - _long_term_pause_time_ratio = _recent_gc_times_ms->sum() / interval_ms; - // Filter out nonsensical results due to bad input. +void G1Analytics::compute_pause_time_ratios(double end_time_sec, double pause_time_ms) { + double long_interval_ms = (end_time_sec - oldest_known_gc_end_time_sec()) * 1000.0; + _long_term_pause_time_ratio = _recent_gc_times_ms->sum() / long_interval_ms; _long_term_pause_time_ratio = clamp(_long_term_pause_time_ratio, 0.0, 1.0); - // Compute the ratio of just this last pause time to the entire time range stored - // in the vectors. Comparing this pause to the entire range, rather than only the - // most recent interval, has the effect of smoothing over a possible transient 'burst' - // of more frequent pauses that don't really reflect a change in heap occupancy. - // This reduces the likelihood of a needless heap expansion being triggered. - _short_term_pause_time_ratio = - (pause_time_ms * _recent_prev_end_times_for_all_gcs_sec->num()) / interval_ms; + double short_interval_ms = (end_time_sec - most_recent_gc_end_time_sec()) * 1000.0; + _short_term_pause_time_ratio = pause_time_ms / short_interval_ms; + _short_term_pause_time_ratio = clamp(_short_term_pause_time_ratio, 0.0, 1.0); } void G1Analytics::report_concurrent_refine_rate_ms(double cards_per_ms) { @@ -228,7 +224,11 @@ void G1Analytics::report_rs_length(double rs_length) { } double G1Analytics::predict_alloc_rate_ms() const { - return predict_zero_bounded(_alloc_rate_ms_seq); + if (enough_samples_available(_alloc_rate_ms_seq)) { + return predict_zero_bounded(_alloc_rate_ms_seq); + } else { + return 0.0; + } } double G1Analytics::predict_concurrent_refine_rate_ms() const { @@ -311,10 +311,14 @@ size_t G1Analytics::predict_pending_cards() const { return predict_size(_pending_cards_seq); } -double G1Analytics::last_known_gc_end_time_sec() const { +double G1Analytics::oldest_known_gc_end_time_sec() const { return _recent_prev_end_times_for_all_gcs_sec->oldest(); } +double G1Analytics::most_recent_gc_end_time_sec() const { + return _recent_prev_end_times_for_all_gcs_sec->last(); +} + void G1Analytics::update_recent_gc_times(double end_time_sec, double pause_time_ms) { _recent_gc_times_ms->add(pause_time_ms); diff --git a/src/hotspot/share/gc/g1/g1Analytics.hpp b/src/hotspot/share/gc/g1/g1Analytics.hpp index d2fe2ec1599..8057f375db3 100644 --- a/src/hotspot/share/gc/g1/g1Analytics.hpp +++ b/src/hotspot/share/gc/g1/g1Analytics.hpp @@ -88,6 +88,9 @@ class G1Analytics: public CHeapObj { size_t predict_size(TruncatedSeq const* seq) const; double predict_zero_bounded(TruncatedSeq const* seq) const; + double oldest_known_gc_end_time_sec() const; + double most_recent_gc_end_time_sec() const; + public: G1Analytics(const G1Predictions* predictor); @@ -160,9 +163,7 @@ class G1Analytics: public CHeapObj { // Add a new GC of the given duration and end time to the record. void update_recent_gc_times(double end_time_sec, double elapsed_ms); - void compute_pause_time_ratio(double interval_ms, double pause_time_ms); - - double last_known_gc_end_time_sec() const; + void compute_pause_time_ratios(double end_time_sec, double pause_time_ms); }; #endif // SHARE_GC_G1_G1ANALYTICS_HPP diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index 45c6932efa8..c6db8780388 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -53,54 +53,61 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) : { assert(max_gc_threads > 0, "Must have some GC threads"); - _gc_par_phases[GCWorkerStart] = new WorkerDataArray("GC Worker Start (ms):", max_gc_threads); - _gc_par_phases[ExtRootScan] = new WorkerDataArray("Ext Root Scanning (ms):", max_gc_threads); + _gc_par_phases[GCWorkerStart] = new WorkerDataArray("GCWorkerStart", "GC Worker Start (ms):", max_gc_threads); + _gc_par_phases[ExtRootScan] = new WorkerDataArray("ExtRootScan", "Ext Root Scanning (ms):", max_gc_threads); // Root scanning phases - _gc_par_phases[ThreadRoots] = new WorkerDataArray("Thread Roots (ms):", max_gc_threads); - _gc_par_phases[UniverseRoots] = new WorkerDataArray("Universe Roots (ms):", max_gc_threads); - _gc_par_phases[JNIRoots] = new WorkerDataArray("JNI Handles Roots (ms):", max_gc_threads); - _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray("ObjectSynchronizer Roots (ms):", max_gc_threads); - _gc_par_phases[ManagementRoots] = new WorkerDataArray("Management Roots (ms):", max_gc_threads); - _gc_par_phases[VMGlobalRoots] = new WorkerDataArray("VM Global Roots (ms):", max_gc_threads); - _gc_par_phases[CLDGRoots] = new WorkerDataArray("CLDG Roots (ms):", max_gc_threads); - _gc_par_phases[JVMTIRoots] = new WorkerDataArray("JVMTI Roots (ms):", max_gc_threads); - AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray("AOT Root Scan (ms):", max_gc_threads);) - _gc_par_phases[CMRefRoots] = new WorkerDataArray("CM RefProcessor Roots (ms):", max_gc_threads); - - _gc_par_phases[MergeER] = new WorkerDataArray("Eager Reclaim (ms):", max_gc_threads); - - _gc_par_phases[MergeRS] = new WorkerDataArray("Remembered Sets (ms):", max_gc_threads); + _gc_par_phases[ThreadRoots] = new WorkerDataArray("ThreadRoots", "Thread Roots (ms):", max_gc_threads); + _gc_par_phases[UniverseRoots] = new WorkerDataArray("UniverseRoots", "Universe Roots (ms):", max_gc_threads); + _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray("ObjectSynchronizerRoots", "ObjectSynchronizer Roots (ms):", max_gc_threads); + _gc_par_phases[ManagementRoots] = new WorkerDataArray("ManagementRoots", "Management Roots (ms):", max_gc_threads); + _gc_par_phases[CLDGRoots] = new WorkerDataArray("CLDGRoots", "CLDG Roots (ms):", max_gc_threads); + _gc_par_phases[JVMTIRoots] = new WorkerDataArray("JVMTIRoots", "JVMTI Roots (ms):", max_gc_threads); + AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray("AOTCodeRoots", "AOT Root Scan (ms):", max_gc_threads);) + _gc_par_phases[CMRefRoots] = new WorkerDataArray("CMRefRoots", "CM RefProcessor Roots (ms):", max_gc_threads); + + int index = G1GCPhaseTimes::StrongOopStorageSetRoots; + for (OopStorageSet::Iterator it = OopStorageSet::strong_iterator(); !it.is_end(); ++it, ++index) { + const char* phase_name_postfix = " Roots (ms):"; + char* oop_storage_phase_name = NEW_C_HEAP_ARRAY(char, strlen(phase_name_postfix) + strlen(it->name()) + 1, mtGC); + strcpy(oop_storage_phase_name, it->name()); + strcat(oop_storage_phase_name, phase_name_postfix); + _gc_par_phases[index] = new WorkerDataArray(it->name(), oop_storage_phase_name, max_gc_threads); + } + + _gc_par_phases[MergeER] = new WorkerDataArray("MergeER", "Eager Reclaim (ms):", max_gc_threads); + + _gc_par_phases[MergeRS] = new WorkerDataArray("MergeRS", "Remembered Sets (ms):", max_gc_threads); _gc_par_phases[MergeRS]->create_thread_work_items("Merged Sparse:", MergeRSMergedSparse); _gc_par_phases[MergeRS]->create_thread_work_items("Merged Fine:", MergeRSMergedFine); _gc_par_phases[MergeRS]->create_thread_work_items("Merged Coarse:", MergeRSMergedCoarse); _gc_par_phases[MergeRS]->create_thread_work_items("Dirty Cards:", MergeRSDirtyCards); - _gc_par_phases[OptMergeRS] = new WorkerDataArray("Optional Remembered Sets (ms):", max_gc_threads); + _gc_par_phases[OptMergeRS] = new WorkerDataArray("OptMergeRS", "Optional Remembered Sets (ms):", max_gc_threads); _gc_par_phases[OptMergeRS]->create_thread_work_items("Merged Sparse:", MergeRSMergedSparse); _gc_par_phases[OptMergeRS]->create_thread_work_items("Merged Fine:", MergeRSMergedFine); _gc_par_phases[OptMergeRS]->create_thread_work_items("Merged Coarse:", MergeRSMergedCoarse); _gc_par_phases[OptMergeRS]->create_thread_work_items("Dirty Cards:", MergeRSDirtyCards); - _gc_par_phases[MergeLB] = new WorkerDataArray("Log Buffers (ms):", max_gc_threads); + _gc_par_phases[MergeLB] = new WorkerDataArray("MergeLB", "Log Buffers (ms):", max_gc_threads); if (G1HotCardCache::default_use_cache()) { - _gc_par_phases[MergeHCC] = new WorkerDataArray("Hot Card Cache (ms):", max_gc_threads); + _gc_par_phases[MergeHCC] = new WorkerDataArray("MergeHCC", "Hot Card Cache (ms):", max_gc_threads); _gc_par_phases[MergeHCC]->create_thread_work_items("Dirty Cards:", MergeHCCDirtyCards); _gc_par_phases[MergeHCC]->create_thread_work_items("Skipped Cards:", MergeHCCSkippedCards); } else { _gc_par_phases[MergeHCC] = NULL; } - _gc_par_phases[ScanHR] = new WorkerDataArray("Scan Heap Roots (ms):", max_gc_threads); - _gc_par_phases[OptScanHR] = new WorkerDataArray("Optional Scan Heap Roots (ms):", max_gc_threads); - _gc_par_phases[CodeRoots] = new WorkerDataArray("Code Root Scan (ms):", max_gc_threads); - _gc_par_phases[OptCodeRoots] = new WorkerDataArray("Optional Code Root Scan (ms):", max_gc_threads); - _gc_par_phases[ObjCopy] = new WorkerDataArray("Object Copy (ms):", max_gc_threads); - _gc_par_phases[OptObjCopy] = new WorkerDataArray("Optional Object Copy (ms):", max_gc_threads); - _gc_par_phases[Termination] = new WorkerDataArray("Termination (ms):", max_gc_threads); - _gc_par_phases[OptTermination] = new WorkerDataArray("Optional Termination (ms):", max_gc_threads); - _gc_par_phases[GCWorkerTotal] = new WorkerDataArray("GC Worker Total (ms):", max_gc_threads); - _gc_par_phases[GCWorkerEnd] = new WorkerDataArray("GC Worker End (ms):", max_gc_threads); - _gc_par_phases[Other] = new WorkerDataArray("GC Worker Other (ms):", max_gc_threads); + _gc_par_phases[ScanHR] = new WorkerDataArray("ScanHR", "Scan Heap Roots (ms):", max_gc_threads); + _gc_par_phases[OptScanHR] = new WorkerDataArray("OptScanHR", "Optional Scan Heap Roots (ms):", max_gc_threads); + _gc_par_phases[CodeRoots] = new WorkerDataArray("CodeRoots", "Code Root Scan (ms):", max_gc_threads); + _gc_par_phases[OptCodeRoots] = new WorkerDataArray("OptCodeRoots", "Optional Code Root Scan (ms):", max_gc_threads); + _gc_par_phases[ObjCopy] = new WorkerDataArray("ObjCopy", "Object Copy (ms):", max_gc_threads); + _gc_par_phases[OptObjCopy] = new WorkerDataArray("OptObjCopy", "Optional Object Copy (ms):", max_gc_threads); + _gc_par_phases[Termination] = new WorkerDataArray("Termination", "Termination (ms):", max_gc_threads); + _gc_par_phases[OptTermination] = new WorkerDataArray("OptTermination", "Optional Termination (ms):", max_gc_threads); + _gc_par_phases[GCWorkerTotal] = new WorkerDataArray("GCWorkerTotal", "GC Worker Total (ms):", max_gc_threads); + _gc_par_phases[GCWorkerEnd] = new WorkerDataArray("GCWorkerEnd", "GC Worker End (ms):", max_gc_threads); + _gc_par_phases[Other] = new WorkerDataArray("Other", "GC Worker Other (ms):", max_gc_threads); _gc_par_phases[ScanHR]->create_thread_work_items("Scanned Cards:", ScanHRScannedCards); _gc_par_phases[ScanHR]->create_thread_work_items("Scanned Blocks:", ScanHRScannedBlocks); @@ -115,7 +122,7 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) : _gc_par_phases[MergeLB]->create_thread_work_items("Dirty Cards:", MergeLBDirtyCards); _gc_par_phases[MergeLB]->create_thread_work_items("Skipped Cards:", MergeLBSkippedCards); - _gc_par_phases[MergePSS] = new WorkerDataArray("Merge Per-Thread State", 1 /* length */, true /* is_serial */); + _gc_par_phases[MergePSS] = new WorkerDataArray("MergePSS", "Merge Per-Thread State", 1 /* length */, true /* is_serial */); _gc_par_phases[MergePSS]->create_thread_work_items("Copied Bytes", MergePSSCopiedBytes, max_gc_threads); _gc_par_phases[MergePSS]->create_thread_work_items("LAB Waste", MergePSSLABWasteBytes, max_gc_threads); @@ -126,20 +133,20 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) : _gc_par_phases[OptTermination]->create_thread_work_items("Optional Termination Attempts:"); if (UseStringDeduplication) { - _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray("Queue Fixup (ms):", max_gc_threads); - _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray("Table Fixup (ms):", max_gc_threads); + _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray("StringDedupQueueFixup", "Queue Fixup (ms):", max_gc_threads); + _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray("StringDedupTableFixup", "Table Fixup (ms):", max_gc_threads); } else { _gc_par_phases[StringDedupQueueFixup] = NULL; _gc_par_phases[StringDedupTableFixup] = NULL; } - _gc_par_phases[RedirtyCards] = new WorkerDataArray("Parallel Redirty (ms):", max_gc_threads); + _gc_par_phases[RedirtyCards] = new WorkerDataArray("RedirtyCards", "Parallel Redirty (ms):", max_gc_threads); _gc_par_phases[RedirtyCards]->create_thread_work_items("Redirtied Cards:"); - _gc_par_phases[ParFreeCSet] = new WorkerDataArray("Parallel Free Collection Set (ms):", max_gc_threads); - _gc_par_phases[YoungFreeCSet] = new WorkerDataArray("Young Free Collection Set (ms):", max_gc_threads); - _gc_par_phases[NonYoungFreeCSet] = new WorkerDataArray("Non-Young Free Collection Set (ms):", max_gc_threads); - _gc_par_phases[RebuildFreeList] = new WorkerDataArray("Parallel Rebuild Free List (ms):", max_gc_threads); + _gc_par_phases[ParFreeCSet] = new WorkerDataArray("ParFreeCSet", "Parallel Free Collection Set (ms):", max_gc_threads); + _gc_par_phases[YoungFreeCSet] = new WorkerDataArray("YoungFreeCSet", "Young Free Collection Set (ms):", max_gc_threads); + _gc_par_phases[NonYoungFreeCSet] = new WorkerDataArray("NonYoungFreeCSet", "Non-Young Free Collection Set (ms):", max_gc_threads); + _gc_par_phases[RebuildFreeList] = new WorkerDataArray("RebuildFreeList", "Parallel Rebuild Free List (ms):", max_gc_threads); reset(); } @@ -553,49 +560,8 @@ void G1GCPhaseTimes::print() { } const char* G1GCPhaseTimes::phase_name(GCParPhases phase) { - static const char* names[] = { - "GCWorkerStart", - "ExtRootScan", - "ThreadRoots", - "UniverseRoots", - "JNIRoots", - "ObjectSynchronizerRoots", - "ManagementRoots", - "VMGlobalRoots", - "CLDGRoots", - "JVMTIRoots", - AOT_ONLY("AOTCodeRoots" COMMA) - "CMRefRoots", - "MergeER", - "MergeRS", - "OptMergeRS", - "MergeLB", - "MergeHCC", - "ScanHR", - "OptScanHR", - "CodeRoots", - "OptCodeRoots", - "ObjCopy", - "OptObjCopy", - "Termination", - "OptTermination", - "Other", - "GCWorkerTotal", - "GCWorkerEnd", - "StringDedupQueueFixup", - "StringDedupTableFixup", - "RedirtyCards", - "ParFreeCSet", - "YoungFreeCSet", - "NonYoungFreeCSet", - "RebuildFreeList", - "MergePSS" - //GCParPhasesSentinel only used to tell end of enum - }; - - STATIC_ASSERT(ARRAY_SIZE(names) == G1GCPhaseTimes::GCParPhasesSentinel); // GCParPhases enum and corresponding string array should have the same "length", this tries to assert it - - return names[phase]; + G1GCPhaseTimes* phase_times = G1CollectedHeap::heap()->phase_times(); + return phase_times->_gc_par_phases[phase]->short_name(); } G1EvacPhaseWithTrimTimeTracker::G1EvacPhaseWithTrimTimeTracker(G1ParScanThreadState* pss, Tickspan& total_time, Tickspan& trim_time) : diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index a3b83c68582..549c849e203 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_GC_G1_G1GCPHASETIMES_HPP #define SHARE_GC_G1_G1GCPHASETIMES_HPP +#include "gc/shared/oopStorageSet.hpp" #include "gc/shared/referenceProcessorPhaseTimes.hpp" #include "gc/shared/weakProcessorPhaseTimes.hpp" #include "logging/logLevel.hpp" @@ -48,15 +49,16 @@ class G1GCPhaseTimes : public CHeapObj { ExtRootScan, ThreadRoots, UniverseRoots, - JNIRoots, ObjectSynchronizerRoots, ManagementRoots, - VMGlobalRoots, CLDGRoots, JVMTIRoots, AOT_ONLY(AOTCodeRoots COMMA) CMRefRoots, - MergeER, + // For every OopStorage there will be one element in the enum, starting with + // StrongOopStorageSetRoots. + StrongOopStorageSetRoots, + MergeER = StrongOopStorageSetRoots + OopStorageSet::strong_count, MergeRS, OptMergeRS, MergeLB, @@ -84,7 +86,7 @@ class G1GCPhaseTimes : public CHeapObj { }; static const GCParPhases ExtRootScanSubPhasesFirst = ThreadRoots; - static const GCParPhases ExtRootScanSubPhasesLast = CMRefRoots; + static const GCParPhases ExtRootScanSubPhasesLast = GCParPhases(MergeER - 1); enum GCMergeRSWorkTimes { MergeRSMergedSparse, diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 7808c0c90eb..e447be4e7b3 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -46,6 +46,7 @@ #include "gc/shared/gcPolicyCounters.hpp" #include "logging/log.hpp" #include "runtime/arguments.hpp" +#include "runtime/globals.hpp" #include "runtime/java.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/debug.hpp" @@ -61,8 +62,8 @@ G1Policy::G1Policy(STWGCTimer* gc_timer) : _policy_counters(new GCPolicyCounters("GarbageFirst", 1, 2)), _full_collection_start_sec(0.0), _collection_pause_end_millis(os::javaTimeNanos() / NANOSECS_PER_MILLISEC), + _young_list_desired_length(0), _young_list_target_length(0), - _young_list_fixed_length(0), _young_list_max_length(0), _eden_surv_rate_group(new G1SurvRateGroup()), _survivor_surv_rate_group(new G1SurvRateGroup()), @@ -107,14 +108,11 @@ void G1Policy::init(G1CollectedHeap* g1h, G1CollectionSet* collection_set) { assert(Heap_lock->owned_by_self(), "Locking discipline."); - if (!use_adaptive_young_list_length()) { - _young_list_fixed_length = _young_gen_sizer->min_desired_young_length(); - } _young_gen_sizer->adjust_max_new_size(_g1h->max_expandable_regions()); _free_regions_at_end_of_collection = _g1h->num_free_regions(); - update_young_list_max_and_target_length(); + update_young_length_bounds(); // We may immediately start allocating regions and placing them on the // collection set list. Initialize the per-collection set info _collection_set->start_incremental_building(); @@ -189,158 +187,254 @@ void G1Policy::record_new_heap_size(uint new_number_of_regions) { _ihop_control->update_target_occupancy(new_number_of_regions * HeapRegion::GrainBytes); } -uint G1Policy::calculate_young_list_desired_min_length(uint base_min_length) const { +uint G1Policy::calculate_desired_eden_length_by_mmu() const { + // One could argue that any useful eden length to keep any MMU would be 1, but + // in theory this is possible. Other constraints enforce a minimum eden of 1 + // anyway. uint desired_min_length = 0; if (use_adaptive_young_list_length()) { - if (_analytics->num_alloc_rate_ms() > 3) { - double now_sec = os::elapsedTime(); - double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; - double alloc_rate_ms = _analytics->predict_alloc_rate_ms(); - desired_min_length = (uint) ceil(alloc_rate_ms * when_ms); - } else { - // otherwise we don't have enough info to make the prediction - } + double now_sec = os::elapsedTime(); + double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; + double alloc_rate_ms = _analytics->predict_alloc_rate_ms(); + desired_min_length = (uint) ceil(alloc_rate_ms * when_ms); } - desired_min_length += base_min_length; - // make sure we don't go below any user-defined minimum bound - return MAX2(_young_gen_sizer->min_desired_young_length(), desired_min_length); -} - -uint G1Policy::calculate_young_list_desired_max_length() const { - // Here, we might want to also take into account any additional - // constraints (i.e., user-defined minimum bound). Currently, we - // effectively don't set this bound. - return _young_gen_sizer->max_desired_young_length(); -} - -uint G1Policy::update_young_list_max_and_target_length() { - return update_young_list_max_and_target_length(_analytics->predict_rs_length()); -} - -uint G1Policy::update_young_list_max_and_target_length(size_t rs_length) { - uint unbounded_target_length = update_young_list_target_length(rs_length); - update_max_gc_locker_expansion(); - return unbounded_target_length; -} - -uint G1Policy::update_young_list_target_length(size_t rs_length) { - YoungTargetLengths young_lengths = young_list_target_lengths(rs_length); - _young_list_target_length = young_lengths.first; - - return young_lengths.second; -} - -G1Policy::YoungTargetLengths G1Policy::young_list_target_lengths(size_t rs_length) const { - YoungTargetLengths result; + return desired_min_length; +} + +void G1Policy::update_young_length_bounds() { + update_young_length_bounds(_analytics->predict_rs_length()); +} + +void G1Policy::update_young_length_bounds(size_t rs_length) { + _young_list_desired_length = calculate_young_desired_length(rs_length); + _young_list_target_length = calculate_young_target_length(_young_list_desired_length); + _young_list_max_length = calculate_young_max_length(_young_list_target_length); + + log_debug(gc,ergo,heap)("Young list lengths: desired: %u, target: %u, max: %u", + _young_list_desired_length, + _young_list_target_length, + _young_list_max_length); +} + +// Calculates desired young gen length. It is calculated from: +// +// - sizer min/max bounds on young gen +// - pause time goal for whole young gen evacuation +// - MMU goal influencing eden to make GCs spaced apart. +// - a minimum one eden region length. +// +// We may enter with already allocated eden and survivor regions, that may be +// higher than the maximum, or the above goals may result in a desired value +// smaller than are already allocated. +// The main reason is revising young length, with our without the GCLocker being +// active. +// +uint G1Policy::calculate_young_desired_length(size_t rs_length) const { + uint min_young_length_by_sizer = _young_gen_sizer->min_desired_young_length(); + uint max_young_length_by_sizer = _young_gen_sizer->max_desired_young_length(); + + assert(min_young_length_by_sizer >= 1, "invariant"); + assert(max_young_length_by_sizer >= min_young_length_by_sizer, "invariant"); + + // Absolute minimum eden length. + // Enforcing a minimum eden length helps at startup when the predictors are not + // yet trained on the application to avoid unnecessary (but very short) full gcs + // on very small (initial) heaps. + uint const MinDesiredEdenLength = 1; // Calculate the absolute and desired min bounds first. - // This is how many young regions we already have (currently: the survivors). - const uint base_min_length = _g1h->survivor_regions_count(); - uint desired_min_length = calculate_young_list_desired_min_length(base_min_length); - // This is the absolute minimum young length. Ensure that we - // will at least have one eden region available for allocation. - uint absolute_min_length = base_min_length + MAX2(_g1h->eden_regions_count(), (uint)1); - // If we shrank the young list target it should not shrink below the current size. - desired_min_length = MAX2(desired_min_length, absolute_min_length); - // Calculate the absolute and desired max bounds. + // This is how many survivor regions we already have. + const uint survivor_length = _g1h->survivor_regions_count(); + // Size of the already allocated young gen. + const uint allocated_young_length = _g1h->young_regions_count(); + // This is the absolute minimum young length that we can return. Ensure that we + // don't go below any user-defined minimum bound; but we might have already + // allocated more than that for reasons. In this case, use that. + uint absolute_min_young_length = MAX2(allocated_young_length, min_young_length_by_sizer); + // Calculate the absolute max bounds. After evac failure or when revising the + // young length we might have exceeded absolute min length or absolute_max_length, + // so adjust the result accordingly. + uint absolute_max_young_length = MAX2(max_young_length_by_sizer, absolute_min_young_length); + + uint desired_eden_length_by_mmu = 0; + uint desired_eden_length_by_pause = 0; + uint desired_eden_length_before_mixed = 0; + + uint desired_young_length = 0; + if (use_adaptive_young_list_length()) { + desired_eden_length_by_mmu = calculate_desired_eden_length_by_mmu(); - uint desired_max_length = calculate_young_list_desired_max_length(); + const size_t pending_cards = _analytics->predict_pending_cards(); + double survivor_base_time_ms = predict_base_elapsed_time_ms(pending_cards, rs_length); - uint young_list_target_length = 0; - if (use_adaptive_young_list_length()) { - if (collector_state()->in_young_only_phase()) { - young_list_target_length = - calculate_young_list_target_length(rs_length, - base_min_length, - desired_min_length, - desired_max_length); + if (!next_gc_should_be_mixed(NULL, NULL)) { + desired_eden_length_by_pause = + calculate_desired_eden_length_by_pause(survivor_base_time_ms, + absolute_min_young_length - survivor_length, + absolute_max_young_length - survivor_length); } else { - // Don't calculate anything and let the code below bound it to - // the desired_min_length, i.e., do the next GC as soon as - // possible to maximize how many old regions we can add to it. + desired_eden_length_before_mixed = + calculate_desired_eden_length_before_mixed(survivor_base_time_ms, + absolute_min_young_length - survivor_length, + absolute_max_young_length - survivor_length); } + // Above either sets desired_eden_length_by_pause or desired_eden_length_before_mixed, + // the other is zero. Use the one that has been set below. + uint desired_eden_length = MAX2(desired_eden_length_by_pause, + desired_eden_length_before_mixed); + + // Finally incorporate MMU concerns; assume that it overrides the pause time + // goal, as the default value has been chosen to effectively disable it. + // Also request at least one eden region, see above for reasons. + desired_eden_length = MAX3(desired_eden_length, + desired_eden_length_by_mmu, + MinDesiredEdenLength); + + desired_young_length = desired_eden_length + survivor_length; } else { // The user asked for a fixed young gen so we'll fix the young gen // whether the next GC is young or mixed. - young_list_target_length = _young_list_fixed_length; + desired_young_length = min_young_length_by_sizer; } - - result.second = young_list_target_length; - - // We will try our best not to "eat" into the reserve. - uint absolute_max_length = 0; - if (_free_regions_at_end_of_collection > _reserve_regions) { - absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions; - } - if (desired_max_length > absolute_max_length) { - desired_max_length = absolute_max_length; + // Clamp to absolute min/max after we determined desired lengths. + desired_young_length = clamp(desired_young_length, absolute_min_young_length, absolute_max_young_length); + + log_trace(gc, ergo, heap)("Young desired length %u " + "survivor length %u " + "allocated young length %u " + "absolute min young length %u " + "absolute max young length %u " + "desired eden length by mmu %u " + "desired eden length by pause %u " + "desired eden length before mixed %u" + "desired eden length by default %u", + desired_young_length, survivor_length, + allocated_young_length, absolute_min_young_length, + absolute_max_young_length, desired_eden_length_by_mmu, + desired_eden_length_by_pause, + desired_eden_length_before_mixed, + MinDesiredEdenLength); + + assert(desired_young_length >= allocated_young_length, "must be"); + return desired_young_length; +} + +// Limit the desired (wished) young length by current free regions. If the request +// can be satisfied without using up reserve regions, do so, otherwise eat into +// the reserve, giving away at most what the heap sizer allows. +uint G1Policy::calculate_young_target_length(uint desired_young_length) const { + uint allocated_young_length = _g1h->young_regions_count(); + + uint receiving_additional_eden; + if (allocated_young_length >= desired_young_length) { + // Already used up all we actually want (may happen as G1 revises the + // young list length concurrently, or caused by gclocker). Do not allow more, + // potentially resulting in GC. + receiving_additional_eden = 0; + log_trace(gc, ergo, heap)("Young target length: Already used up desired young %u allocated %u", + desired_young_length, + allocated_young_length); + } else { + // Now look at how many free regions are there currently, and the heap reserve. + // We will try our best not to "eat" into the reserve as long as we can. If we + // do, we at most eat the sizer's minimum regions into the reserve or half the + // reserve rounded up (if possible; this is an arbitrary value). + + uint max_to_eat_into_reserve = MIN2(_young_gen_sizer->min_desired_young_length(), + (_reserve_regions + 1) / 2); + + log_trace(gc, ergo, heap)("Young target length: Common " + "free regions at end of collection %u " + "desired young length %u " + "reserve region %u " + "max to eat into reserve %u", + _free_regions_at_end_of_collection, + desired_young_length, + _reserve_regions, + max_to_eat_into_reserve); + + if (_free_regions_at_end_of_collection <= _reserve_regions) { + // Fully eat (or already eating) into the reserve, hand back at most absolute_min_length regions. + uint receiving_young = MIN3(_free_regions_at_end_of_collection, + desired_young_length, + max_to_eat_into_reserve); + // We could already have allocated more regions than what we could get + // above. + receiving_additional_eden = allocated_young_length < receiving_young ? + receiving_young - allocated_young_length : 0; + + log_trace(gc, ergo, heap)("Young target length: Fully eat into reserve " + "receiving young %u receiving additional eden %u", + receiving_young, + receiving_additional_eden); + } else if (_free_regions_at_end_of_collection < (desired_young_length + _reserve_regions)) { + // Partially eat into the reserve, at most max_to_eat_into_reserve regions. + uint free_outside_reserve = _free_regions_at_end_of_collection - _reserve_regions; + assert(free_outside_reserve < desired_young_length, + "must be %u %u", + free_outside_reserve, desired_young_length); + + uint receiving_within_reserve = MIN2(desired_young_length - free_outside_reserve, + max_to_eat_into_reserve); + uint receiving_young = free_outside_reserve + receiving_within_reserve; + // Again, we could have already allocated more than we could get. + receiving_additional_eden = allocated_young_length < receiving_young ? + receiving_young - allocated_young_length : 0; + + log_trace(gc, ergo, heap)("Young target length: Partially eat into reserve " + "free outside reserve %u " + "receiving within reserve %u " + "receiving young %u " + "receiving additional eden %u", + free_outside_reserve, receiving_within_reserve, + receiving_young, receiving_additional_eden); + } else { + // No need to use the reserve. + receiving_additional_eden = desired_young_length - allocated_young_length; + log_trace(gc, ergo, heap)("Young target length: No need to use reserve " + "receiving additional eden %u", + receiving_additional_eden); + } } - // Make sure we don't go over the desired max length, nor under the - // desired min length. In case they clash, desired_min_length wins - // which is why that test is second. - if (young_list_target_length > desired_max_length) { - young_list_target_length = desired_max_length; - } - if (young_list_target_length < desired_min_length) { - young_list_target_length = desired_min_length; - } + uint target_young_length = allocated_young_length + receiving_additional_eden; - assert(young_list_target_length > base_min_length, - "we should be able to allocate at least one eden region"); - assert(young_list_target_length >= absolute_min_length, "post-condition"); + assert(target_young_length >= allocated_young_length, "must be"); - result.first = young_list_target_length; - return result; + log_trace(gc, ergo, heap)("Young target length: " + "young target length %u " + "allocated young length %u " + "received additional eden %u", + target_young_length, allocated_young_length, + receiving_additional_eden); + return target_young_length; } -uint G1Policy::calculate_young_list_target_length(size_t rs_length, - uint base_min_length, - uint desired_min_length, - uint desired_max_length) const { +uint G1Policy::calculate_desired_eden_length_by_pause(double base_time_ms, + uint min_eden_length, + uint max_eden_length) const { assert(use_adaptive_young_list_length(), "pre-condition"); - assert(collector_state()->in_young_only_phase(), "only call this for young GCs"); - - // In case some edge-condition makes the desired max length too small... - if (desired_max_length <= desired_min_length) { - return desired_min_length; - } - // We'll adjust min_young_length and max_young_length not to include - // the already allocated young regions (i.e., so they reflect the - // min and max eden regions we'll allocate). The base_min_length - // will be reflected in the predictions by the - // survivor_regions_evac_time prediction. - assert(desired_min_length > base_min_length, "invariant"); - uint min_young_length = desired_min_length - base_min_length; - assert(desired_max_length > base_min_length, "invariant"); - uint max_young_length = desired_max_length - base_min_length; - - const double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; - const size_t pending_cards = _analytics->predict_pending_cards(); - const double base_time_ms = predict_base_elapsed_time_ms(pending_cards, rs_length); - const uint available_free_regions = _free_regions_at_end_of_collection; - const uint base_free_regions = - available_free_regions > _reserve_regions ? available_free_regions - _reserve_regions : 0; + assert(min_eden_length <= max_eden_length, "must be %u %u", min_eden_length, max_eden_length); // Here, we will make sure that the shortest young length that // makes sense fits within the target pause time. G1YoungLengthPredictor p(base_time_ms, - base_free_regions, - target_pause_time_ms, + _free_regions_at_end_of_collection, + _mmu_tracker->max_gc_time() * 1000.0, this); - if (p.will_fit(min_young_length)) { + if (p.will_fit(min_eden_length)) { // The shortest young length will fit into the target pause time; // we'll now check whether the absolute maximum number of young // regions will fit in the target pause time. If not, we'll do // a binary search between min_young_length and max_young_length. - if (p.will_fit(max_young_length)) { + if (p.will_fit(max_eden_length)) { // The maximum young length will fit into the target pause time. // We are done so set min young length to the maximum length (as // the result is assumed to be returned in min_young_length). - min_young_length = max_young_length; + min_eden_length = max_eden_length; } else { // The maximum possible number of young regions will not fit within // the target pause time so we'll search for the optimal @@ -357,37 +451,56 @@ uint G1Policy::calculate_young_list_target_length(size_t rs_length, // does, it becomes the new min. If it doesn't, it becomes // the new max. This way we maintain the loop invariants. - assert(min_young_length < max_young_length, "invariant"); - uint diff = (max_young_length - min_young_length) / 2; + assert(min_eden_length < max_eden_length, "invariant"); + uint diff = (max_eden_length - min_eden_length) / 2; while (diff > 0) { - uint young_length = min_young_length + diff; - if (p.will_fit(young_length)) { - min_young_length = young_length; + uint eden_length = min_eden_length + diff; + if (p.will_fit(eden_length)) { + min_eden_length = eden_length; } else { - max_young_length = young_length; + max_eden_length = eden_length; } - assert(min_young_length < max_young_length, "invariant"); - diff = (max_young_length - min_young_length) / 2; + assert(min_eden_length < max_eden_length, "invariant"); + diff = (max_eden_length - min_eden_length) / 2; } // The results is min_young_length which, according to the // loop invariants, should fit within the target pause time. // These are the post-conditions of the binary search above: - assert(min_young_length < max_young_length, - "otherwise we should have discovered that max_young_length " + assert(min_eden_length < max_eden_length, + "otherwise we should have discovered that max_eden_length " "fits into the pause target and not done the binary search"); - assert(p.will_fit(min_young_length), - "min_young_length, the result of the binary search, should " + assert(p.will_fit(min_eden_length), + "min_eden_length, the result of the binary search, should " "fit into the pause target"); - assert(!p.will_fit(min_young_length + 1), - "min_young_length, the result of the binary search, should be " + assert(!p.will_fit(min_eden_length + 1), + "min_eden_length, the result of the binary search, should be " "optimal, so no larger length should fit into the pause target"); } } else { // Even the minimum length doesn't fit into the pause time // target, return it as the result nevertheless. } - return base_min_length + min_young_length; + return min_eden_length; +} + +uint G1Policy::calculate_desired_eden_length_before_mixed(double survivor_base_time_ms, + uint min_eden_length, + uint max_eden_length) const { + G1CollectionSetCandidates* candidates = _collection_set->candidates(); + + uint min_old_regions_end = MIN2(candidates->cur_idx() + calc_min_old_cset_length(), candidates->num_regions()); + double predicted_region_evac_time_ms = survivor_base_time_ms; + for (uint i = candidates->cur_idx(); i < min_old_regions_end; i++) { + HeapRegion* r = candidates->at(i); + predicted_region_evac_time_ms += predict_region_total_time_ms(r, false); + } + uint desired_eden_length_by_min_cset_length = + calculate_desired_eden_length_by_pause(predicted_region_evac_time_ms, + min_eden_length, + max_eden_length); + + return desired_eden_length_by_min_cset_length; } double G1Policy::predict_survivor_regions_evac_time() const { @@ -408,8 +521,7 @@ void G1Policy::revise_young_list_target_length_if_necessary(size_t rs_length) { // add 10% to avoid having to recalculate often size_t rs_length_prediction = rs_length * 1100 / 1000; update_rs_length_prediction(rs_length_prediction); - - update_young_list_max_and_target_length(rs_length_prediction); + update_young_length_bounds(rs_length_prediction); } } @@ -457,7 +569,7 @@ void G1Policy::record_full_collection_end() { _free_regions_at_end_of_collection = _g1h->num_free_regions(); _survivor_surv_rate_group->reset(); - update_young_list_max_and_target_length(); + update_young_length_bounds(); update_rs_length_prediction(); _old_gen_alloc_tracker.reset_after_full_gc(); @@ -669,10 +781,8 @@ void G1Policy::record_collection_pause_end(double pause_time_ms) { double alloc_rate_ms = (double) regions_allocated / app_time_ms; _analytics->report_alloc_rate_ms(alloc_rate_ms); - double interval_ms = - (end_time_sec - _analytics->last_known_gc_end_time_sec()) * 1000.0; + _analytics->compute_pause_time_ratios(end_time_sec, pause_time_ms); _analytics->update_recent_gc_times(end_time_sec, pause_time_ms); - _analytics->compute_pause_time_ratio(interval_ms, pause_time_ms); } if (collector_state()->in_young_gc_before_mixed()) { @@ -789,16 +899,11 @@ void G1Policy::record_collection_pause_end(double pause_time_ms) { // Do not update dynamic IHOP due to G1 periodic collection as it is highly likely // that in this case we are not running in a "normal" operating mode. if (_g1h->gc_cause() != GCCause::_g1_periodic_collection) { - // IHOP control wants to know the expected young gen length if it were not - // restrained by the heap reserve. Using the actual length would make the - // prediction too small and the limit the young gen every time we get to the - // predicted target occupancy. - size_t last_unrestrained_young_length = update_young_list_max_and_target_length(); + update_young_length_bounds(); _old_gen_alloc_tracker.reset_after_young_gc(app_time_ms / 1000.0); update_ihop_prediction(_old_gen_alloc_tracker.last_cycle_duration(), _old_gen_alloc_tracker.last_cycle_old_bytes(), - last_unrestrained_young_length * HeapRegion::GrainBytes, this_pause_was_young_only); _ihop_control->send_trace_event(_g1h->gc_tracer_stw()); @@ -848,7 +953,6 @@ G1IHOPControl* G1Policy::create_ihop_control(const G1Predictions* predictor){ void G1Policy::update_ihop_prediction(double mutator_time_s, size_t mutator_alloc_bytes, - size_t young_gen_size, bool this_gc_was_young_only) { // Always try to update IHOP prediction. Even evacuation failures give information // about e.g. whether to start IHOP earlier next time. @@ -876,6 +980,11 @@ void G1Policy::update_ihop_prediction(double mutator_time_s, // marking, which makes any prediction useless. This increases the accuracy of the // prediction. if (this_gc_was_young_only && mutator_time_s > min_valid_time) { + // IHOP control wants to know the expected young gen length if it were not + // restrained by the heap reserve. Using the actual length would make the + // prediction too small and the limit the young gen every time we get to the + // predicted target occupancy. + size_t young_gen_size = young_list_desired_length() * HeapRegion::GrainBytes; _ihop_control->update_allocation_info(mutator_time_s, mutator_alloc_bytes, young_gen_size); report = true; } @@ -982,7 +1091,7 @@ void G1Policy::print_age_table() { _survivors_age_table.print_age_table(_tenuring_threshold); } -void G1Policy::update_max_gc_locker_expansion() { +uint G1Policy::calculate_young_max_length(uint target_young_length) const { uint expansion_region_num = 0; if (GCLockerEdenExpansionPercent > 0) { double perc = (double) GCLockerEdenExpansionPercent / 100.0; @@ -993,8 +1102,9 @@ void G1Policy::update_max_gc_locker_expansion() { } else { assert(expansion_region_num == 0, "sanity"); } - _young_list_max_length = _young_list_target_length + expansion_region_num; - assert(_young_list_target_length <= _young_list_max_length, "post-condition"); + uint max_length = target_young_length + expansion_region_num; + assert(target_young_length <= max_length, "post-condition"); + return max_length; } // Calculates survivor space parameters. @@ -1203,8 +1313,10 @@ bool G1Policy::next_gc_should_be_mixed(const char* true_action_str, const char* false_action_str) const { G1CollectionSetCandidates* candidates = _collection_set->candidates(); - if (candidates->is_empty()) { - log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str); + if (candidates == NULL || candidates->is_empty()) { + if (false_action_str != NULL) { + log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str); + } return false; } @@ -1213,12 +1325,16 @@ bool G1Policy::next_gc_should_be_mixed(const char* true_action_str, double reclaimable_percent = reclaimable_bytes_percent(reclaimable_bytes); double threshold = (double) G1HeapWastePercent; if (reclaimable_percent <= threshold) { - log_debug(gc, ergo)("%s (reclaimable percentage not over threshold). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, - false_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); + if (false_action_str != NULL) { + log_debug(gc, ergo)("%s (reclaimable percentage not over threshold). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, + false_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); + } return false; } - log_debug(gc, ergo)("%s (candidate old regions available). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, - true_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); + if (true_action_str != NULL) { + log_debug(gc, ergo)("%s (candidate old regions available). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, + true_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); + } return true; } diff --git a/src/hotspot/share/gc/g1/g1Policy.hpp b/src/hotspot/share/gc/g1/g1Policy.hpp index 473ebbac392..9784fd4e10e 100644 --- a/src/hotspot/share/gc/g1/g1Policy.hpp +++ b/src/hotspot/share/gc/g1/g1Policy.hpp @@ -60,7 +60,6 @@ class G1Policy: public CHeapObj { // Update the IHOP control with necessary statistics. void update_ihop_prediction(double mutator_time_s, size_t mutator_alloc_bytes, - size_t young_gen_size, bool this_gc_was_young_only); void report_ihop_statistics(); @@ -76,8 +75,8 @@ class G1Policy: public CHeapObj { jlong _collection_pause_end_millis; + uint _young_list_desired_length; uint _young_list_target_length; - uint _young_list_fixed_length; // The max number of regions we can extend the eden by while the GC // locker is active. This should be >= _young_list_target_length; @@ -170,6 +169,10 @@ class G1Policy: public CHeapObj { private: G1CollectionSet* _collection_set; + + bool next_gc_should_be_mixed(const char* true_action_str, + const char* false_action_str) const; + double average_time_ms(G1GCPhaseTimes::GCParPhases phase) const; double other_time_ms(double pause_time_ms) const; @@ -189,44 +192,38 @@ class G1Policy: public CHeapObj { double _mark_remark_start_sec; double _mark_cleanup_start_sec; - // Updates the internal young list maximum and target lengths. Returns the - // unbounded young list target length. If no rs_length parameter is passed, - // predict the RS length using the prediction model, otherwise use the - // given rs_length as the prediction. - uint update_young_list_max_and_target_length(); - uint update_young_list_max_and_target_length(size_t rs_length); - - // Update the young list target length either by setting it to the - // desired fixed value or by calculating it using G1's pause - // prediction model. - // Returns the unbounded young list target length. - uint update_young_list_target_length(size_t rs_length); - - // Calculate and return the minimum desired young list target - // length. This is the minimum desired young list length according - // to the user's inputs. - uint calculate_young_list_desired_min_length(uint base_min_length) const; - - // Calculate and return the maximum desired young list target - // length. This is the maximum desired young list length according - // to the user's inputs. - uint calculate_young_list_desired_max_length() const; - - // Calculate and return the maximum young list target length that - // can fit into the pause time goal. The parameters are: rs_length - // represent the prediction of how large the young RSet lengths will - // be, base_min_length is the already existing number of regions in - // the young list, min_length and max_length are the desired min and - // max young list length according to the user's inputs. - uint calculate_young_list_target_length(size_t rs_length, - uint base_min_length, - uint desired_min_length, - uint desired_max_length) const; - - // Result of the bounded_young_list_target_length() method, containing both the - // bounded as well as the unbounded young list target lengths in this order. - typedef Pair YoungTargetLengths; - YoungTargetLengths young_list_target_lengths(size_t rs_length) const; + // Updates the internal young gen maximum and target and desired lengths. + // If no rs_length parameter is passed, predict the RS length using the + // prediction model, otherwise use the given rs_length as the prediction. + void update_young_length_bounds(); + void update_young_length_bounds(size_t rs_length); + + // Calculate and return the minimum desired eden length based on the MMU target. + uint calculate_desired_eden_length_by_mmu() const; + + // Calculate and return the desired eden length that can fit into the pause time goal. + // The parameters are: rs_length represents the prediction of how large the + // young RSet lengths will be, min_eden_length and max_eden_length are the bounds + // (inclusive) within eden can grow. + uint calculate_desired_eden_length_by_pause(double base_time_ms, + uint min_eden_length, + uint max_eden_length) const; + + // Calculates the desired eden length before mixed gc so that after adding the + // minimum amount of old gen regions from the collection set, the eden fits into + // the pause time goal. + uint calculate_desired_eden_length_before_mixed(double survivor_base_time_ms, + uint min_eden_length, + uint max_eden_length) const; + + // Calculate desired young length based on current situation without taking actually + // available free regions into account. + uint calculate_young_desired_length(size_t rs_length) const; + // Limit the given desired young length to available free regions. + uint calculate_young_target_length(uint desired_young_length) const; + // The GCLocker might cause us to need more regions than the target. Calculate + // the maximum number of regions to use in that case. + uint calculate_young_max_length(uint target_young_length) const; void update_rs_length_prediction(); void update_rs_length_prediction(size_t prediction); @@ -335,9 +332,6 @@ class G1Policy: public CHeapObj { void print_phases(); - bool next_gc_should_be_mixed(const char* true_action_str, - const char* false_action_str) const; - // Calculate and return the number of initial and optional old gen regions from // the given collection set candidates and the remaining time. void calculate_old_collection_set_regions(G1CollectionSetCandidates* candidates, @@ -374,6 +368,7 @@ class G1Policy: public CHeapObj { // the initial-mark work and start a marking cycle. void decide_on_conc_mark_initiation(); + uint young_list_desired_length() const { return _young_list_desired_length; } size_t young_list_target_length() const { return _young_list_target_length; } bool should_allocate_mutator_region() const; @@ -434,8 +429,6 @@ class G1Policy: public CHeapObj { void print_age_table(); - void update_max_gc_locker_expansion(); - void update_survivors_policy(); virtual bool force_upgrade_to_full() { diff --git a/src/hotspot/share/gc/g1/g1RootProcessor.cpp b/src/hotspot/share/gc/g1/g1RootProcessor.cpp index 139def1662a..244a04243c3 100644 --- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp +++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp @@ -40,6 +40,7 @@ #include "gc/g1/heapRegion.inline.hpp" #include "gc/shared/oopStorage.inline.hpp" #include "gc/shared/oopStorageSet.hpp" +#include "gc/shared/oopStorageSetParState.inline.hpp" #include "gc/shared/referenceProcessor.hpp" #include "memory/allocation.inline.hpp" #include "memory/universe.hpp" @@ -188,13 +189,6 @@ void G1RootProcessor::process_vm_roots(G1RootClosures* closures, } } - { - G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JNIRoots, worker_id); - if (_process_strong_tasks.try_claim_task(G1RP_PS_JNIHandles_oops_do)) { - JNIHandles::oops_do(strong_roots); - } - } - { G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ObjectSynchronizerRoots, worker_id); if (_process_strong_tasks.try_claim_task(G1RP_PS_ObjectSynchronizer_oops_do)) { @@ -225,11 +219,10 @@ void G1RootProcessor::process_vm_roots(G1RootClosures* closures, } #endif - { - G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::VMGlobalRoots, worker_id); - if (_process_strong_tasks.try_claim_task(G1RP_PS_VMGlobal_oops_do)) { - OopStorageSet::vm_global()->oops_do(strong_roots); - } + for (int i = 0; i < _oop_storage_set_strong_par_state.par_state_count(); ++i) { + G1GCPhaseTimes::GCParPhases phase = G1GCPhaseTimes::GCParPhases(G1GCPhaseTimes::StrongOopStorageSetRoots + i); + G1GCParPhaseTimesTracker x(phase_times, phase, worker_id); + _oop_storage_set_strong_par_state.par_state(i)->oops_do(closures->strong_oops()); } } diff --git a/src/hotspot/share/gc/g1/g1RootProcessor.hpp b/src/hotspot/share/gc/g1/g1RootProcessor.hpp index a75d53f7009..26f35e937ad 100644 --- a/src/hotspot/share/gc/g1/g1RootProcessor.hpp +++ b/src/hotspot/share/gc/g1/g1RootProcessor.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_GC_G1_G1ROOTPROCESSOR_HPP #define SHARE_GC_G1_G1ROOTPROCESSOR_HPP +#include "gc/shared/oopStorageSetParState.hpp" #include "gc/shared/strongRootsScope.hpp" #include "memory/allocation.hpp" #include "runtime/mutex.hpp" @@ -49,13 +50,12 @@ class G1RootProcessor : public StackObj { G1CollectedHeap* _g1h; SubTasksDone _process_strong_tasks; StrongRootsScope _srs; + OopStorageSetStrongParState _oop_storage_set_strong_par_state; enum G1H_process_roots_tasks { G1RP_PS_Universe_oops_do, - G1RP_PS_JNIHandles_oops_do, G1RP_PS_ObjectSynchronizer_oops_do, G1RP_PS_Management_oops_do, - G1RP_PS_VMGlobal_oops_do, G1RP_PS_ClassLoaderDataGraph_oops_do, G1RP_PS_jvmti_oops_do, G1RP_PS_CodeCache_oops_do, diff --git a/src/hotspot/share/gc/shared/oopStorage.cpp b/src/hotspot/share/gc/shared/oopStorage.cpp index 416afce7034..04cce946330 100644 --- a/src/hotspot/share/gc/shared/oopStorage.cpp +++ b/src/hotspot/share/gc/shared/oopStorage.cpp @@ -731,15 +731,21 @@ void OopStorage::release(const oop* const* ptrs, size_t size) { const size_t initial_active_array_size = 8; -OopStorage::OopStorage(const char* name, - Mutex* allocation_mutex, - Mutex* active_mutex) : +static Mutex* make_oopstorage_mutex(const char* storage_name, + const char* kind, + int rank) { + char name[256]; + os::snprintf(name, sizeof(name), "%s %s lock", storage_name, kind); + return new PaddedMutex(rank, name, true, Mutex::_safepoint_check_never); +} + +OopStorage::OopStorage(const char* name) : _name(os::strdup(name)), _active_array(ActiveArray::create(initial_active_array_size)), _allocation_list(), _deferred_updates(NULL), - _allocation_mutex(allocation_mutex), - _active_mutex(active_mutex), + _allocation_mutex(make_oopstorage_mutex(name, "alloc", Mutex::oopstorage)), + _active_mutex(make_oopstorage_mutex(name, "active", Mutex::oopstorage - 1)), _allocation_count(0), _concurrent_iteration_count(0), _needs_cleanup(false) diff --git a/src/hotspot/share/gc/shared/oopStorage.hpp b/src/hotspot/share/gc/shared/oopStorage.hpp index 36862f954a0..718aeacd5de 100644 --- a/src/hotspot/share/gc/shared/oopStorage.hpp +++ b/src/hotspot/share/gc/shared/oopStorage.hpp @@ -74,7 +74,7 @@ class outputStream; class OopStorage : public CHeapObj { public: - OopStorage(const char* name, Mutex* allocation_mutex, Mutex* active_mutex); + explicit OopStorage(const char* name); ~OopStorage(); // These count and usage accessors are racy unless at a safepoint. diff --git a/src/hotspot/share/gc/shared/oopStorageSet.cpp b/src/hotspot/share/gc/shared/oopStorageSet.cpp index ef477bcd592..0b42d508e17 100644 --- a/src/hotspot/share/gc/shared/oopStorageSet.cpp +++ b/src/hotspot/share/gc/shared/oopStorageSet.cpp @@ -25,8 +25,6 @@ #include "precompiled.hpp" #include "gc/shared/oopStorage.hpp" #include "gc/shared/oopStorageSet.hpp" -#include "runtime/mutex.hpp" -#include "runtime/os.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" @@ -34,28 +32,14 @@ // +1 for NULL singular entry. OopStorage* OopStorageSet::storages[all_count + 1] = {}; -static Mutex* make_oopstorage_mutex(const char* storage_name, - const char* kind, - int rank) { - char name[256]; - os::snprintf(name, sizeof(name), "%s %s lock", storage_name, kind); - return new PaddedMutex(rank, name, true, Mutex::_safepoint_check_never); -} - -static OopStorage* make_oopstorage(const char* name) { - Mutex* alloc = make_oopstorage_mutex(name, "alloc", Mutex::oopstorage); - Mutex* active = make_oopstorage_mutex(name, "active", Mutex::oopstorage - 1); - return new OopStorage(name, alloc, active); -} - void OopStorageSet::initialize() { - storages[jni_global_index] = make_oopstorage("JNI global"); - storages[vm_global_index] = make_oopstorage("VM global"); - storages[jni_weak_index] = make_oopstorage("JNI weak"); - storages[vm_weak_index] = make_oopstorage("VM weak"); - storages[string_table_weak_index] = make_oopstorage("StringTable weak"); + storages[jni_global_index] = new OopStorage("JNI Global"); + storages[vm_global_index] = new OopStorage("VM Global"); + storages[jni_weak_index] = new OopStorage("JNI Weak"); + storages[vm_weak_index] = new OopStorage("VM Weak"); + storages[string_table_weak_index] = new OopStorage("StringTable Weak"); storages[resolved_method_table_weak_index] = - make_oopstorage("ResolvedMethodTable weak"); + new OopStorage("ResolvedMethodTable Weak"); // Ensure we have all of them. STATIC_ASSERT(all_count == 6); diff --git a/src/hotspot/share/gc/shared/oopStorageSetParState.hpp b/src/hotspot/share/gc/shared/oopStorageSetParState.hpp index 2e37435e7c4..5701bcd41fa 100644 --- a/src/hotspot/share/gc/shared/oopStorageSetParState.hpp +++ b/src/hotspot/share/gc/shared/oopStorageSetParState.hpp @@ -41,6 +41,9 @@ class OopStorageSetStrongParState { template void oops_do(Closure* cl); + + ParStateType* par_state(int i) const { return _par_states.at(i); } + int par_state_count() const { return _par_states.count(); } }; #endif // SHARE_GC_SHARED_OOPSTORAGESETPARSTATE_HPP diff --git a/src/hotspot/share/gc/shared/oopStorageSetParState.inline.hpp b/src/hotspot/share/gc/shared/oopStorageSetParState.inline.hpp index 8152aa76d63..8284023585b 100644 --- a/src/hotspot/share/gc/shared/oopStorageSetParState.inline.hpp +++ b/src/hotspot/share/gc/shared/oopStorageSetParState.inline.hpp @@ -42,5 +42,4 @@ void OopStorageSetStrongParState::oops_do(Closure* cl) { } } - #endif // SHARE_GC_SHARED_OOPSTORAGESETPARSTATE_INLINE_HPP diff --git a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp index 4b76ccf6609..76335788d0a 100644 --- a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp @@ -177,9 +177,9 @@ ReferenceProcessorPhaseTimes::ReferenceProcessorPhaseTimes(GCTimer* gc_timer, ui _processing_is_mt(false), _gc_timer(gc_timer) { for (uint i = 0; i < ReferenceProcessor::RefSubPhaseMax; i++) { - _sub_phases_worker_time_sec[i] = new WorkerDataArray(SubPhasesParWorkTitle[i], max_gc_threads); + _sub_phases_worker_time_sec[i] = new WorkerDataArray(NULL, SubPhasesParWorkTitle[i], max_gc_threads); } - _phase2_worker_time_sec = new WorkerDataArray(Phase2ParWorkTitle, max_gc_threads); + _phase2_worker_time_sec = new WorkerDataArray(NULL, Phase2ParWorkTitle, max_gc_threads); reset(); } diff --git a/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp b/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp index 73afbf3dc57..b8178b9fa04 100644 --- a/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp +++ b/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp @@ -91,7 +91,7 @@ WeakProcessorPhaseTimes::WeakProcessorPhaseTimes(uint max_threads) : for ( ; !it.is_end(); ++it) { assert(size_t(wpt - _worker_data) < ARRAY_SIZE(_worker_data), "invariant"); const char* description = it->name(); - *wpt = new WorkerDataArray(description, _max_threads); + *wpt = new WorkerDataArray(NULL, description, _max_threads); (*wpt)->create_thread_work_items("Dead", DeadItems); (*wpt)->create_thread_work_items("Total", TotalItems); wpt++; diff --git a/src/hotspot/share/gc/shared/workerDataArray.hpp b/src/hotspot/share/gc/shared/workerDataArray.hpp index 4f7635a6c6e..6d9c44de8ef 100644 --- a/src/hotspot/share/gc/shared/workerDataArray.hpp +++ b/src/hotspot/share/gc/shared/workerDataArray.hpp @@ -38,14 +38,15 @@ class WorkerDataArray : public CHeapObj { private: T* _data; uint _length; - const char* _title; + const char* _short_name; // Short name for JFR + const char* _title; // Title for logging. bool _is_serial; WorkerDataArray* _thread_work_items[MaxThreadWorkItems]; public: - WorkerDataArray(const char* title, uint length, bool is_serial = false); + WorkerDataArray(const char* short_name, const char* title, uint length, bool is_serial = false); ~WorkerDataArray(); // Create an integer sub-item at the given index to this WorkerDataArray. If length_override @@ -78,6 +79,10 @@ class WorkerDataArray : public CHeapObj { return _title; } + const char* short_name() const { + return _short_name; + } + void reset(); void set_all(T value); diff --git a/src/hotspot/share/gc/shared/workerDataArray.inline.hpp b/src/hotspot/share/gc/shared/workerDataArray.inline.hpp index f698c2f21a2..6f247df8d94 100644 --- a/src/hotspot/share/gc/shared/workerDataArray.inline.hpp +++ b/src/hotspot/share/gc/shared/workerDataArray.inline.hpp @@ -30,9 +30,10 @@ #include "utilities/ostream.hpp" template -WorkerDataArray::WorkerDataArray(const char* title, uint length, bool is_serial) : +WorkerDataArray::WorkerDataArray(const char* short_name, const char* title, uint length, bool is_serial) : _data(NULL), _length(length), + _short_name(short_name), _title(title), _is_serial(is_serial) { assert(length > 0, "Must have some workers to store data for"); @@ -70,7 +71,7 @@ void WorkerDataArray::create_thread_work_items(const char* title, uint index, assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)", index, MaxThreadWorkItems); assert(_thread_work_items[index] == NULL, "Tried to overwrite existing thread work item"); uint length = length_override != 0 ? length_override : _length; - _thread_work_items[index] = new WorkerDataArray(title, length); + _thread_work_items[index] = new WorkerDataArray(NULL, title, length); } template diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index dac046d99db..46f7ce1c9c1 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -986,9 +986,8 @@ void ShenandoahBarrierSetC2::verify_gc_barriers(Compile* compile, CompilePhase p // Verify G1 pre-barriers const int marking_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_active_offset()); - ResourceArea *area = Thread::current()->resource_area(); - Unique_Node_List visited(area); - Node_List worklist(area); + Unique_Node_List visited; + Node_List worklist; // We're going to walk control flow backwards starting from the Root worklist.push(compile->root()); while (worklist.size() > 0) { diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index afec788e19a..8d715332241 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -279,7 +279,7 @@ void ShenandoahBarrierC2Support::verify(RootNode* root) { GrowableArray barriers; Unique_Node_List barriers_used; Node_Stack phis(0); - VectorSet visited(Thread::current()->resource_area()); + VectorSet visited; const bool trace = false; const bool verify_no_useless_barrier = false; @@ -766,7 +766,7 @@ Node* ShenandoahBarrierC2Support::no_branches(Node* c, Node* dom, bool allow_one Node* ShenandoahBarrierC2Support::dom_mem(Node* mem, Node* ctrl, int alias, Node*& mem_ctrl, PhaseIdealLoop* phase) { ResourceMark rm; - VectorSet wq(Thread::current()->resource_area()); + VectorSet wq; wq.set(mem->_idx); mem_ctrl = phase->ctrl_or_self(mem); while (!phase->is_dominator(mem_ctrl, ctrl) || mem_ctrl == ctrl) { @@ -1082,11 +1082,12 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { Node* barrier = state->enqueue_barrier(i); Node* ctrl = phase->get_ctrl(barrier); IdealLoopTree* loop = phase->get_loop(ctrl); - if (loop->_head->is_OuterStripMinedLoop()) { + Node* head = loop->head(); + if (head->is_OuterStripMinedLoop()) { // Expanding a barrier here will break loop strip mining // verification. Transform the loop so the loop nest doesn't // appear as strip mined. - OuterStripMinedLoopNode* outer = loop->_head->as_OuterStripMinedLoop(); + OuterStripMinedLoopNode* outer = head->as_OuterStripMinedLoop(); hide_strip_mined_loop(outer, outer->unique_ctrl_out()->as_CountedLoop(), phase); } } @@ -1181,7 +1182,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { } CallProjections* projs = call->extract_projections(false, false); #ifdef ASSERT - VectorSet cloned(Thread::current()->resource_area()); + VectorSet cloned; #endif Node* lrb_clone = lrb->clone(); phase->register_new_node(lrb_clone, projs->catchall_catchproj); @@ -1286,11 +1287,12 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i); Node* ctrl = phase->get_ctrl(lrb); IdealLoopTree* loop = phase->get_loop(ctrl); - if (loop->_head->is_OuterStripMinedLoop()) { + Node* head = loop->head(); + if (head->is_OuterStripMinedLoop()) { // Expanding a barrier here will break loop strip mining // verification. Transform the loop so the loop nest doesn't // appear as strip mined. - OuterStripMinedLoopNode* outer = loop->_head->as_OuterStripMinedLoop(); + OuterStripMinedLoopNode* outer = head->as_OuterStripMinedLoop(); hide_strip_mined_loop(outer, outer->unique_ctrl_out()->as_CountedLoop(), phase); } } @@ -1351,7 +1353,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { Node* addr; if (ShenandoahSelfFixing) { - VectorSet visited(Thread::current()->resource_area()); + VectorSet visited; addr = get_load_addr(phase, visited, lrb); } else { addr = phase->igvn().zerocon(T_OBJECT); @@ -1815,7 +1817,7 @@ void ShenandoahBarrierC2Support::optimize_after_expansion(VectorSet &visited, No } if (!phase->C->major_progress()) { - VectorSet seen(Thread::current()->resource_area()); + VectorSet seen; for (uint i = 0; i < heap_stable_tests.size(); i++) { Node* n = heap_stable_tests.at(i); IdealLoopTree* loop = phase->get_loop(n); @@ -2087,7 +2089,7 @@ static bool has_never_branch(Node* root) { void MemoryGraphFixer::collect_memory_nodes() { Node_Stack stack(0); - VectorSet visited(Thread::current()->resource_area()); + VectorSet visited; Node_List regions; // Walk the raw memory graph and create a mapping from CFG node to diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 5bca1cafe0c..1c47e3b7470 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -83,8 +83,6 @@ #include "services/mallocTracker.hpp" #include "utilities/powerOfTwo.hpp" -ShenandoahHeap* ShenandoahHeap::_heap = NULL; - #ifdef ASSERT template void ShenandoahAssertToSpaceClosure::do_oop_work(T* p) { @@ -497,8 +495,6 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) : _liveness_cache(NULL), _collection_set(NULL) { - _heap = this; - BarrierSet::set_barrier_set(new ShenandoahBarrierSet(this)); _max_workers = MAX2(_max_workers, 1U); @@ -1044,28 +1040,79 @@ void ShenandoahHeap::trash_humongous_region_at(ShenandoahHeapRegion* start) { } } +class ShenandoahCheckCleanGCLABClosure : public ThreadClosure { +public: + ShenandoahCheckCleanGCLABClosure() {} + void do_thread(Thread* thread) { + PLAB* gclab = ShenandoahThreadLocalData::gclab(thread); + assert(gclab != NULL, "GCLAB should be initialized for %s", thread->name()); + assert(gclab->words_remaining() == 0, "GCLAB should not need retirement"); + } +}; + class ShenandoahRetireGCLABClosure : public ThreadClosure { +private: + bool const _resize; public: + ShenandoahRetireGCLABClosure(bool resize) : _resize(resize) {} void do_thread(Thread* thread) { PLAB* gclab = ShenandoahThreadLocalData::gclab(thread); assert(gclab != NULL, "GCLAB should be initialized for %s", thread->name()); gclab->retire(); + if (_resize && ShenandoahThreadLocalData::gclab_size(thread) > 0) { + ShenandoahThreadLocalData::set_gclab_size(thread, 0); + } } }; -void ShenandoahHeap::make_parsable(bool retire_tlabs) { - if (UseTLAB) { - CollectedHeap::ensure_parsability(retire_tlabs); +void ShenandoahHeap::labs_make_parsable() { + assert(UseTLAB, "Only call with UseTLAB"); + + ShenandoahRetireGCLABClosure cl(false); + + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { + ThreadLocalAllocBuffer& tlab = t->tlab(); + tlab.make_parsable(); + cl.do_thread(t); } - ShenandoahRetireGCLABClosure cl; + + workers()->threads_do(&cl); +} + +void ShenandoahHeap::tlabs_retire(bool resize) { + assert(UseTLAB, "Only call with UseTLAB"); + assert(!resize || ResizeTLAB, "Only call for resize when ResizeTLAB is enabled"); + + ThreadLocalAllocStats stats; + + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { + ThreadLocalAllocBuffer& tlab = t->tlab(); + tlab.retire(&stats); + if (resize) { + tlab.resize(); + } + } + + stats.publish(); + +#ifdef ASSERT + ShenandoahCheckCleanGCLABClosure cl; for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { cl.do_thread(t); } workers()->threads_do(&cl); +#endif } -void ShenandoahHeap::resize_tlabs() { - CollectedHeap::resize_all_tlabs(); +void ShenandoahHeap::gclabs_retire(bool resize) { + assert(UseTLAB, "Only call with UseTLAB"); + assert(!resize || ResizeTLAB, "Only call for resize when ResizeTLAB is enabled"); + + ShenandoahRetireGCLABClosure cl(resize); + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { + cl.do_thread(t); + } + workers()->threads_do(&cl); } class ShenandoahEvacuateUpdateRootsTask : public AbstractGangTask { @@ -1122,25 +1169,6 @@ size_t ShenandoahHeap::max_tlab_size() const { return ShenandoahHeapRegion::max_tlab_size_words(); } -class ShenandoahRetireAndResetGCLABClosure : public ThreadClosure { -public: - void do_thread(Thread* thread) { - PLAB* gclab = ShenandoahThreadLocalData::gclab(thread); - gclab->retire(); - if (ShenandoahThreadLocalData::gclab_size(thread) > 0) { - ShenandoahThreadLocalData::set_gclab_size(thread, 0); - } - } -}; - -void ShenandoahHeap::retire_and_reset_gclabs() { - ShenandoahRetireAndResetGCLABClosure cl; - for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { - cl.do_thread(t); - } - workers()->threads_do(&cl); -} - void ShenandoahHeap::collect(GCCause::Cause cause) { control_thread()->request_gc(cause); } @@ -1173,8 +1201,8 @@ jlong ShenandoahHeap::millis_since_last_gc() { } void ShenandoahHeap::prepare_for_verify() { - if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) { - make_parsable(false); + if (SafepointSynchronize::is_at_safepoint() && UseTLAB) { + labs_make_parsable(); } } @@ -1264,7 +1292,7 @@ class ObjectIterateScanRootClosure : public BasicOopIterateClosure { * This is public API, used in preparation of object_iterate(). * Since we don't do linear scan of heap in object_iterate() (see comment below), we don't * need to make the heap parsable. For Shenandoah-internal linear heap scans that we can - * control, we call SH::make_tlabs_parsable(). + * control, we call SH::tlabs_retire, SH::gclabs_retire. */ void ShenandoahHeap::ensure_parsability(bool retire_tlabs) { // No-op. @@ -1420,10 +1448,13 @@ void ShenandoahHeap::op_init_mark() { } set_concurrent_mark_in_progress(true); - // We need to reset all TLABs because we'd lose marks on all objects allocated in them. - { - ShenandoahGCPhase phase(ShenandoahPhaseTimings::make_parsable); - make_parsable(true); + + // We need to reset all TLABs because they might be below the TAMS, and we need to mark + // the objects in them. Do not let mutators allocate any new objects in their current TLABs. + // It is also a good place to resize the TLAB sizes for future allocations. + if (UseTLAB) { + ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_manage_tlabs); + tlabs_retire(ResizeTLAB); } { @@ -1437,11 +1468,6 @@ void ShenandoahHeap::op_init_mark() { concurrent_mark()->mark_roots(ShenandoahPhaseTimings::scan_roots); - if (UseTLAB) { - ShenandoahGCPhase phase(ShenandoahPhaseTimings::resize_tlabs); - resize_tlabs(); - } - if (ShenandoahPacing) { pacer()->setup_for_mark(); } @@ -1539,9 +1565,9 @@ void ShenandoahHeap::op_final_mark() { // which would be outside the collection set, so no cset writes would happen there. // Weaker one: new allocations would happen past update watermark, and so less work would // be needed for reference updates (would update the large filler instead). - { - ShenandoahGCPhase phase(ShenandoahPhaseTimings::retire_tlabs); - make_parsable(true); + if (UseTLAB) { + ShenandoahGCPhase phase(ShenandoahPhaseTimings::final_manage_labs); + tlabs_retire(false); } { @@ -1917,10 +1943,6 @@ void ShenandoahHeap::op_full(GCCause::Cause cause) { metrics.snap_before(); full_gc()->do_it(cause); - if (UseTLAB) { - ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_resize_tlabs); - resize_all_tlabs(); - } metrics.snap_after(); @@ -2511,9 +2533,12 @@ void ShenandoahHeap::op_init_updaterefs() { set_evacuation_in_progress(false); - { - ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_refs_retire_gclabs); - retire_and_reset_gclabs(); + // Evacuation is over, no GCLABs are needed anymore. GCLABs are under URWM, so we need to + // make them parsable for update code to work correctly. Plus, we can compute new sizes + // for future GCLABs here. + if (UseTLAB) { + ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_refs_manage_gclabs); + gclabs_retire(true); } if (ShenandoahVerify) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 0657e73be9a..5085fdb4c53 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -141,9 +141,6 @@ class ShenandoahHeap : public CollectedHeap { // ---------- Initialization, termination, identification, printing routines // -private: - static ShenandoahHeap* _heap; - public: static ShenandoahHeap* heap(); @@ -595,7 +592,6 @@ class ShenandoahHeap : public CollectedHeap { inline HeapWord* allocate_from_gclab(Thread* thread, size_t size); HeapWord* allocate_from_gclab_slow(Thread* thread, size_t size); HeapWord* allocate_new_gclab(size_t min_size, size_t word_size, size_t* actual_size); - void retire_and_reset_gclabs(); public: HeapWord* allocate_memory(ShenandoahAllocRequest& request); @@ -615,10 +611,11 @@ class ShenandoahHeap : public CollectedHeap { size_t max_tlab_size() const; size_t tlab_used(Thread* ignored) const; - void resize_tlabs(); + void ensure_parsability(bool retire_labs); - void ensure_parsability(bool retire_tlabs); - void make_parsable(bool retire_tlabs); + void labs_make_parsable(); + void tlabs_retire(bool resize); + void gclabs_retire(bool resize); // ---------- Marking support // diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp index 475bcd7490e..144c9f00aba 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -49,8 +49,7 @@ #include "utilities/globalDefinitions.hpp" inline ShenandoahHeap* ShenandoahHeap::heap() { - assert(_heap != NULL, "Heap is not initialized yet"); - return _heap; + return named_heap(CollectedHeap::Shenandoah); } inline ShenandoahHeapRegion* ShenandoahRegionIterator::next() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp index 753638af6de..9509ae75206 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp @@ -145,7 +145,10 @@ void ShenandoahMarkCompact::do_it(GCCause::Cause gc_cause) { _preserved_marks->init(heap->workers()->active_workers()); } - heap->make_parsable(true); + if (UseTLAB) { + heap->gclabs_retire(true); + heap->tlabs_retire(true); + } OrderAccess::fence(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp index e0f8cf58634..a3ff2623c78 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp @@ -69,7 +69,7 @@ ShenandoahPhaseTimings::ShenandoahPhaseTimings(uint max_workers) : if (is_worker_phase(Phase(i))) { int c = 0; #define SHENANDOAH_WORKER_DATA_INIT(type, title) \ - if (c++ != 0) _worker_data[i + c] = new ShenandoahWorkerData(title, _max_workers); + if (c++ != 0) _worker_data[i + c] = new ShenandoahWorkerData(NULL, title, _max_workers); SHENANDOAH_PAR_PHASE_DO(,, SHENANDOAH_WORKER_DATA_INIT) #undef SHENANDOAH_WORKER_DATA_INIT } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp index 40d51f1f0f0..e7d9e8c7a06 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp @@ -60,11 +60,10 @@ class outputStream; \ f(init_mark_gross, "Pause Init Mark (G)") \ f(init_mark, "Pause Init Mark (N)") \ - f(make_parsable, " Make Parsable") \ + f(init_manage_tlabs, " Manage TLABs") \ f(init_update_region_states, " Update Region States") \ f(scan_roots, " Scan Roots") \ SHENANDOAH_PAR_PHASE_DO(scan_, " S: ", f) \ - f(resize_tlabs, " Resize TLABs") \ \ f(conc_mark, "Concurrent Marking") \ f(conc_mark_roots, " Roots ") \ @@ -86,7 +85,7 @@ class outputStream; SHENANDOAH_PAR_PHASE_DO(purge_weak_par_, " WR: ", f) \ f(purge_cldg, " CLDG") \ f(final_update_region_states, " Update Region States") \ - f(retire_tlabs, " Retire TLABs") \ + f(final_manage_labs, " Manage GC/TLABs") \ f(choose_cset, " Choose Collection Set") \ f(final_rebuild_freeset, " Rebuild Free Set") \ f(init_evac, " Initial Evacuation") \ @@ -113,7 +112,7 @@ class outputStream; \ f(init_update_refs_gross, "Pause Init Update Refs (G)") \ f(init_update_refs, "Pause Init Update Refs (N)") \ - f(init_update_refs_retire_gclabs, " Retire GCLABs") \ + f(init_update_refs_manage_gclabs, " Manage GCLABs") \ \ f(conc_update_refs, "Concurrent Update Refs") \ \ @@ -166,7 +165,6 @@ class outputStream; f(full_gc_copy_objects_humong, " Humongous Objects") \ f(full_gc_copy_objects_reset_complete, " Reset Complete Bitmap") \ f(full_gc_copy_objects_rebuild, " Rebuild Region Sets") \ - f(full_gc_resize_tlabs, " Resize TLABs") \ f(full_gc_heapdump_post, " Post Heap Dump") \ \ f(conc_uncommit, "Concurrent Uncommit") \ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index 3fb45f813d0..ecb96eb3825 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -690,7 +690,10 @@ void ShenandoahVerifier::verify_at_safepoint(const char *label, } OrderAccess::fence(); - _heap->make_parsable(false); + + if (UseTLAB) { + _heap->labs_make_parsable(); + } // Allocate temporary bitmap for storing marking wavefront: _verification_bit_map->clear(); diff --git a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp index 6c4d6c8aa0e..d0ea716bf15 100644 --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp @@ -371,7 +371,7 @@ void ZBarrierSetC2::analyze_dominating_barriers() const { // Dominating block? Look around for safepoints ResourceMark rm; Block_List stack; - VectorSet visited(Thread::current()->resource_area()); + VectorSet visited; stack.push(load_block); bool safepoint_found = block_has_safepoint(load_block); while (!safepoint_found && stack.size() > 0) { diff --git a/src/hotspot/share/interpreter/bytecodes.cpp b/src/hotspot/share/interpreter/bytecodes.cpp index 2665528f974..2db87abf41e 100644 --- a/src/hotspot/share/interpreter/bytecodes.cpp +++ b/src/hotspot/share/interpreter/bytecodes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -536,8 +536,8 @@ void Bytecodes::initialize() { def(_nofast_getfield , "nofast_getfield" , "bJJ" , NULL , T_ILLEGAL, 0, true, _getfield ); def(_nofast_putfield , "nofast_putfield" , "bJJ" , NULL , T_ILLEGAL, -2, true , _putfield ); - def(_nofast_aload_0 , "nofast_aload_0" , "b" , NULL , T_ILLEGAL, 1, true , _aload_0 ); - def(_nofast_iload , "nofast_iload" , "bi" , NULL , T_ILLEGAL, 1, false, _iload ); + def(_nofast_aload_0 , "nofast_aload_0" , "b" , NULL , T_OBJECT, 1, true , _aload_0 ); + def(_nofast_iload , "nofast_iload" , "bi" , NULL , T_INT, 1, false, _iload ); def(_shouldnotreachhere , "_shouldnotreachhere" , "b" , NULL , T_VOID , 0, false); diff --git a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp index 84dd64aa30a..918d41fbbe8 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp @@ -27,7 +27,7 @@ #include "classfile/classLoaderDataGraph.hpp" #include "classfile/stringTable.hpp" #include "gc/shared/oopStorage.inline.hpp" -#include "gc/shared/oopStorageSet.hpp" +#include "gc/shared/oopStorageSet.inline.hpp" #include "gc/shared/strongRootsScope.hpp" #include "jfr/leakprofiler/chains/bfsClosure.hpp" #include "jfr/leakprofiler/chains/dfsClosure.hpp" @@ -38,7 +38,6 @@ #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" -#include "runtime/jniHandles.inline.hpp" #include "runtime/synchronizer.hpp" #include "runtime/thread.hpp" #include "services/management.hpp" @@ -76,9 +75,8 @@ void RootSetClosure::process() { Threads::oops_do(this, NULL); ObjectSynchronizer::oops_do(this); Universe::oops_do(this); - JNIHandles::oops_do(this); JvmtiExport::oops_do(this); - OopStorageSet::vm_global()->oops_do(this); + OopStorageSet::strong_oops_do(this); Management::oops_do(this); AOTLoader::oops_do(this); } diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp index 61a24949918..7c437a0630f 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp @@ -98,9 +98,8 @@ class ReferenceToRootClosure : public StackObj { bool do_cldg_roots(); bool do_object_synchronizer_roots(); bool do_universe_roots(); - bool do_jni_handle_roots(); + bool do_oop_storage_roots(); bool do_jvmti_roots(); - bool do_vm_global_roots(); bool do_management_roots(); bool do_string_table_roots(); bool do_aot_loader_roots(); @@ -148,11 +147,22 @@ bool ReferenceToRootClosure::do_universe_roots() { return rlc.complete(); } -bool ReferenceToRootClosure::do_jni_handle_roots() { - assert(!complete(), "invariant"); - ReferenceLocateClosure rlc(_callback, OldObjectRoot::_global_jni_handles, OldObjectRoot::_global_jni_handle, NULL); - JNIHandles::oops_do(&rlc); - return rlc.complete(); +bool ReferenceToRootClosure::do_oop_storage_roots() { + int i = 0; + for (OopStorageSet::Iterator it = OopStorageSet::strong_iterator(); !it.is_end(); ++it, ++i) { + assert(!complete(), "invariant"); + OopStorage* oop_storage = *it; + OldObjectRoot::Type type = oop_storage == OopStorageSet::jni_global() ? + OldObjectRoot::_global_jni_handle : + OldObjectRoot::_global_oop_handle; + OldObjectRoot::System system = OldObjectRoot::System(OldObjectRoot::_strong_oop_storage_set_first + i); + ReferenceLocateClosure rlc(_callback, system, type, NULL); + oop_storage->oops_do(&rlc); + if (rlc.complete()) { + return true; + } + } + return false; } bool ReferenceToRootClosure::do_jvmti_roots() { @@ -162,13 +172,6 @@ bool ReferenceToRootClosure::do_jvmti_roots() { return rlc.complete(); } -bool ReferenceToRootClosure::do_vm_global_roots() { - assert(!complete(), "invariant"); - ReferenceLocateClosure rlc(_callback, OldObjectRoot::_vm_global, OldObjectRoot::_type_undetermined, NULL); - OopStorageSet::vm_global()->oops_do(&rlc); - return rlc.complete(); -} - bool ReferenceToRootClosure::do_management_roots() { assert(!complete(), "invariant"); ReferenceLocateClosure rlc(_callback, OldObjectRoot::_management, OldObjectRoot::_type_undetermined, NULL); @@ -203,7 +206,7 @@ bool ReferenceToRootClosure::do_roots() { return true; } - if (do_jni_handle_roots()) { + if (do_oop_storage_roots()) { _complete = true; return true; } @@ -213,11 +216,6 @@ bool ReferenceToRootClosure::do_roots() { return true; } - if (do_vm_global_roots()) { - _complete = true; - return true; - } - if (do_management_roots()) { _complete = true; return true; diff --git a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.cpp b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.cpp new file mode 100644 index 00000000000..a3ac2a7aec8 --- /dev/null +++ b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/shared/oopStorage.hpp" +#include "gc/shared/oopStorageSet.hpp" +#include "jfr/leakprofiler/utilities/rootType.hpp" +#include "utilities/debug.hpp" + +OopStorage* OldObjectRoot::system_oop_storage(System system) { + int val = int(system); + if (val >= _strong_oop_storage_set_first && val <= _strong_oop_storage_set_last) { + int index = val - _strong_oop_storage_set_first; + int i = 0; + for (OopStorageSet::Iterator it = OopStorageSet::strong_iterator(); !it.is_end(); ++it, ++i) { + if (i == index) { + return *it; + } + } + } + return NULL; +} + +const char* OldObjectRoot::system_description(System system) { + OopStorage* oop_storage = system_oop_storage(system); + if (oop_storage != NULL) { + return oop_storage->name(); + } + switch (system) { + case _system_undetermined: + return ""; + case _universe: + return "Universe"; + case _threads: + return "Threads"; + case _object_synchronizer: + return "Object Monitor"; + case _class_loader_data: + return "Class Loader Data"; + case _management: + return "Management"; + case _jvmti: + return "JVMTI"; + case _code_cache: + return "Code Cache"; + case _aot: + return "AOT"; +#if INCLUDE_JVMCI + case _jvmci: + return "JVMCI"; +#endif + default: + ShouldNotReachHere(); + } + return NULL; +} + +const char* OldObjectRoot::type_description(Type type) { + switch (type) { + case _type_undetermined: + return ""; + case _stack_variable: + return "Stack Variable"; + case _local_jni_handle: + return "Local JNI Handle"; + case _global_jni_handle: + return "Global JNI Handle"; + case _global_oop_handle: + return "Global Object Handle"; + case _handle_area: + return "Handle Area"; + default: + ShouldNotReachHere(); + } + return NULL; +} diff --git a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp index c8129a4ec41..64173a855db 100644 --- a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp +++ b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp @@ -25,18 +25,18 @@ #ifndef SHARE_JFR_LEAKPROFILER_UTILITIES_ROOTTYPE_HPP #define SHARE_JFR_LEAKPROFILER_UTILITIES_ROOTTYPE_HPP +#include "gc/shared/oopStorageSet.hpp" #include "memory/allocation.hpp" -#include "utilities/debug.hpp" class OldObjectRoot : public AllStatic { public: enum System { _system_undetermined, _universe, - _global_jni_handles, _threads, + _strong_oop_storage_set_first, + _strong_oop_storage_set_last = _strong_oop_storage_set_first + OopStorageSet::strong_count - 1, _object_synchronizer, - _vm_global, _class_loader_data, _management, _jvmti, @@ -51,61 +51,14 @@ class OldObjectRoot : public AllStatic { _stack_variable, _local_jni_handle, _global_jni_handle, + _global_oop_handle, _handle_area, _number_of_types }; - static const char* system_description(System system) { - switch (system) { - case _system_undetermined: - return ""; - case _universe: - return "Universe"; - case _global_jni_handles: - return "Global JNI Handles"; - case _threads: - return "Threads"; - case _object_synchronizer: - return "Object Monitor"; - case _vm_global: - return "VM Global"; - case _class_loader_data: - return "Class Loader Data"; - case _management: - return "Management"; - case _jvmti: - return "JVMTI"; - case _code_cache: - return "Code Cache"; - case _aot: - return "AOT"; -#if INCLUDE_JVMCI - case _jvmci: - return "JVMCI"; -#endif - default: - ShouldNotReachHere(); - } - return NULL; - } - - static const char* type_description(Type type) { - switch (type) { - case _type_undetermined: - return ""; - case _stack_variable: - return "Stack Variable"; - case _local_jni_handle: - return "Local JNI Handle"; - case _global_jni_handle: - return "Global JNI Handle"; - case _handle_area: - return "Handle Area"; - default: - ShouldNotReachHere(); - } - return NULL; - } + static OopStorage* system_oop_storage(System system); + static const char* system_description(System system); + static const char* type_description(Type type); }; #endif // SHARE_JFR_LEAKPROFILER_UTILITIES_ROOTTYPE_HPP diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp index d36d9d73b2c..3ba27e40386 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp @@ -35,6 +35,7 @@ #include "jfr/recorder/jfrRecorder.hpp" #include "jfr/recorder/repository/jfrChunkWriter.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" +#include "jfr/recorder/storage/jfrEpochStorage.inline.hpp" #include "jfr/recorder/storage/jfrMemorySpace.inline.hpp" #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp" #include "jfr/support/jfrKlassUnloading.hpp" @@ -91,50 +92,44 @@ void JfrCheckpointManager::destroy() { } JfrCheckpointManager::JfrCheckpointManager(JfrChunkWriter& cw) : - _mspace(NULL), + _global_mspace(NULL), + _thread_local_mspace(NULL), _chunkwriter(cw) {} JfrCheckpointManager::~JfrCheckpointManager() { JfrTraceIdLoadBarrier::destroy(); JfrTypeManager::destroy(); - delete _mspace; + delete _global_mspace; + delete _thread_local_mspace; } -static const size_t buffer_count = 2; -static const size_t buffer_size = 512 * K; +static const size_t global_buffer_prealloc_count = 2; +static const size_t global_buffer_size = 512 * K; -static JfrCheckpointMspace* allocate_mspace(size_t min_elem_size, - size_t free_list_cache_count_limit, - size_t cache_prealloc_count, - bool prealloc_to_free_list, - JfrCheckpointManager* mgr) { - return create_mspace(min_elem_size, - free_list_cache_count_limit, - cache_prealloc_count, - prealloc_to_free_list, - mgr); -} +static const size_t thread_local_buffer_prealloc_count = 16; +static const size_t thread_local_buffer_size = 128; bool JfrCheckpointManager::initialize() { - assert(_mspace == NULL, "invariant"); - _mspace = allocate_mspace(buffer_size, 0, 0, false, this); // post-pone preallocation - if (_mspace == NULL) { + assert(_global_mspace == NULL, "invariant"); + _global_mspace = create_mspace(global_buffer_size, 0, 0, false, this); // post-pone preallocation + if (_global_mspace == NULL) { return false; } // preallocate buffer count to each of the epoch live lists - for (size_t i = 0; i < buffer_count * 2; ++i) { - Buffer* const buffer = mspace_allocate(buffer_size, _mspace); - _mspace->add_to_live_list(buffer, i % 2 == 0); + for (size_t i = 0; i < global_buffer_prealloc_count * 2; ++i) { + Buffer* const buffer = mspace_allocate(global_buffer_size, _global_mspace); + _global_mspace->add_to_live_list(buffer, i % 2 == 0); } - assert(_mspace->free_list_is_empty(), "invariant"); - return JfrTypeManager::initialize() && JfrTraceIdLoadBarrier::initialize(); -} + assert(_global_mspace->free_list_is_empty(), "invariant"); -void JfrCheckpointManager::register_full(BufferPtr buffer, Thread* thread) { - // nothing here at the moment - assert(buffer != NULL, "invariant"); - assert(buffer->acquired_by(thread), "invariant"); - assert(buffer->retired(), "invariant"); + assert(_thread_local_mspace == NULL, "invariant"); + _thread_local_mspace = new JfrThreadLocalCheckpointMspace(); + if (_thread_local_mspace == NULL || !_thread_local_mspace->initialize(thread_local_buffer_size, + JFR_MSPACE_UNLIMITED_CACHE_SIZE, + thread_local_buffer_prealloc_count)) { + return false; + } + return JfrTypeManager::initialize() && JfrTraceIdLoadBarrier::initialize(); } #ifdef ASSERT @@ -149,15 +144,28 @@ static void assert_release(const BufferPtr buffer) { assert(buffer->lease(), "invariant"); assert(buffer->acquired_by_self(), "invariant"); } + +static void assert_retired(const BufferPtr buffer, Thread* thread) { + assert(buffer != NULL, "invariant"); + assert(buffer->acquired_by(thread), "invariant"); + assert(buffer->retired(), "invariant"); +} #endif // ASSERT -static BufferPtr lease(size_t size, JfrCheckpointMspace* mspace, size_t retry_count, Thread* thread, bool previous_epoch) { +void JfrCheckpointManager::register_full(BufferPtr buffer, Thread* thread) { + DEBUG_ONLY(assert_retired(buffer, thread);) + // nothing here at the moment +} + +BufferPtr JfrCheckpointManager::lease(Thread* thread, bool previous_epoch /* false */, size_t size /* 0 */) { + JfrCheckpointMspace* const mspace = instance()._global_mspace; assert(mspace != NULL, "invariant"); static const size_t max_elem_size = mspace->min_element_size(); // min is max BufferPtr buffer; if (size <= max_elem_size) { - buffer = mspace_acquire_lease_with_retry(size, mspace, retry_count, thread, previous_epoch); + buffer = mspace_acquire_live(size, mspace, thread, previous_epoch); if (buffer != NULL) { + buffer->set_lease(); DEBUG_ONLY(assert_lease(buffer);) return buffer; } @@ -167,54 +175,70 @@ static BufferPtr lease(size_t size, JfrCheckpointMspace* mspace, size_t retry_co return buffer; } -static const size_t lease_retry = 100; +const u1 thread_local_context = 1; -BufferPtr JfrCheckpointManager::lease(Thread* thread, bool previous_epoch /* false */, size_t size /* 0 */) { - return ::lease(size, instance()._mspace, lease_retry, thread, previous_epoch); -} - -bool JfrCheckpointManager::lookup(BufferPtr old) const { - assert(old != NULL, "invariant"); - return !_mspace->in_current_epoch_list(old); +static bool is_thread_local(JfrBuffer* buffer) { + assert(buffer != NULL, "invariant"); + return buffer->context() == thread_local_context; } -BufferPtr JfrCheckpointManager::lease(BufferPtr old, Thread* thread, size_t size /* 0 */) { - assert(old != NULL, "invariant"); - return ::lease(size, instance()._mspace, lease_retry, thread, instance().lookup(old)); +static void retire(JfrBuffer* buffer) { + DEBUG_ONLY(assert_release(buffer);) + buffer->clear_lease(); + buffer->set_retired(); } /* - * If the buffer was a lease, release back. - * * The buffer is effectively invalidated for the thread post-return, * and the caller should take means to ensure that it is not referenced. */ -static void release(BufferPtr buffer, Thread* thread) { +static void release(JfrBuffer* buffer) { DEBUG_ONLY(assert_release(buffer);) - buffer->clear_lease(); - if (buffer->transient()) { - buffer->set_retired(); + if (is_thread_local(buffer)) { + retire(buffer); } else { + buffer->clear_lease(); buffer->release(); } } +BufferPtr JfrCheckpointManager::acquire_thread_local(size_t size, Thread* thread) { + assert(thread != NULL, "invariant"); + JfrBuffer* const buffer = instance()._thread_local_mspace->acquire(size, thread); + assert(buffer != NULL, "invariant"); + assert(buffer->free_size() >= size, "invariant"); + buffer->set_context(thread_local_context); + assert(is_thread_local(buffer), "invariant"); + buffer->set_lease(); + return buffer; +} + +BufferPtr JfrCheckpointManager::lease_thread_local(Thread* thread, size_t size /* 0 */) { + JfrBuffer* const buffer = acquire_thread_local(size, thread); + DEBUG_ONLY(assert_lease(buffer);) + return buffer; +} + +BufferPtr JfrCheckpointManager::lease(BufferPtr old, Thread* thread, size_t size) { + assert(old != NULL, "invariant"); + return is_thread_local(old) ? acquire_thread_local(size, thread) : + lease(thread, instance()._global_mspace->in_previous_epoch_list(old), size); +} BufferPtr JfrCheckpointManager::flush(BufferPtr old, size_t used, size_t requested, Thread* thread) { assert(old != NULL, "invariant"); assert(old->lease(), "invariant"); if (0 == requested) { // indicates a lease is being returned - release(old, thread); + release(old); + // signal completion of a new checkpoint set_constant_pending(); return NULL; } - // migration of in-flight information - BufferPtr const new_buffer = lease(old, thread, used + requested); - if (new_buffer != NULL) { - migrate_outstanding_writes(old, new_buffer, used, requested); - } - release(old, thread); - return new_buffer; // might be NULL + BufferPtr new_buffer = lease(old, thread, used + requested); + assert(new_buffer != NULL, "invariant"); + migrate_outstanding_writes(old, new_buffer, used, requested); + retire(old); + return new_buffer; } // offsets into the JfrCheckpointEntry @@ -311,7 +335,7 @@ class CheckpointWriteOp { typedef CheckpointWriteOp WriteOperation; typedef MutexedWriteOp MutexedWriteOperation; -typedef ReleaseOpWithExcision ReleaseOperation; +typedef ReleaseWithExcisionOp ReleaseOperation; typedef CompositeOperation WriteReleaseOperation; void JfrCheckpointManager::begin_epoch_shift() { @@ -328,12 +352,13 @@ void JfrCheckpointManager::end_epoch_shift() { size_t JfrCheckpointManager::write() { DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(Thread::current())); - assert(_mspace->free_list_is_empty(), "invariant"); WriteOperation wo(_chunkwriter); MutexedWriteOperation mwo(wo); - ReleaseOperation ro(_mspace, _mspace->live_list(true)); + _thread_local_mspace->iterate(mwo, true); // previous epoch list + assert(_global_mspace->free_list_is_empty(), "invariant"); + ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true)); WriteReleaseOperation wro(&mwo, &ro); - process_live_list(wro, _mspace, true); + process_live_list(wro, _global_mspace, true); // previous epoch list return wo.processed(); } @@ -344,10 +369,11 @@ size_t JfrCheckpointManager::clear() { JfrTraceIdLoadBarrier::clear(); clear_type_set(); DiscardOperation discard_operation(mutexed); // mutexed discard mode - ReleaseOperation ro(_mspace, _mspace->live_list(true)); + _thread_local_mspace->iterate(discard_operation, true); // previous epoch list + ReleaseOperation ro(_global_mspace, _global_mspace->live_list(true)); DiscardReleaseOperation discard_op(&discard_operation, &ro); - assert(_mspace->free_list_is_empty(), "invariant"); - process_live_list(discard_op, _mspace, true); // previous epoch list + assert(_global_mspace->free_list_is_empty(), "invariant"); + process_live_list(discard_op, _global_mspace, true); // previous epoch list return discard_operation.elements(); } @@ -427,40 +453,33 @@ void JfrCheckpointManager::on_unloading_classes() { } } -class JavaThreadToVM : public StackObj { - private: - JavaThread* _jt; - public: - JavaThreadToVM(Thread* thread) : _jt(thread->is_Java_thread() ? (JavaThread*)thread : NULL) { - if (_jt != NULL) { - assert(_jt->thread_state() == _thread_in_native, "invariant"); - _jt->set_thread_state(_thread_in_vm); - } - } - ~JavaThreadToVM() { - if (_jt != NULL) { - _jt->set_thread_state(_thread_in_native); - } - } -}; +static size_t flush_type_set(Thread* thread) { + assert(thread != NULL, "invariant"); + JfrCheckpointWriter writer(thread); + MutexLocker cld_lock(thread, ClassLoaderDataGraph_lock); + MutexLocker module_lock(thread, Module_lock); + return JfrTypeSet::serialize(&writer, NULL, false, true); +} size_t JfrCheckpointManager::flush_type_set() { size_t elements = 0; if (JfrTraceIdEpoch::has_changed_tag_state()) { - Thread* const t = Thread::current(); - // can safepoint here (if JavaThread) - JavaThreadToVM transition(t); - ResetNoHandleMark rnhm; - MutexLocker cld_lock(t, ClassLoaderDataGraph_lock); - MutexLocker module_lock(t, Module_lock); - JfrCheckpointWriter writer(t); - elements = JfrTypeSet::serialize(&writer, NULL, false, true); + Thread* const thread = Thread::current(); + if (thread->is_Java_thread()) { + // can safepoint here + ThreadInVMfromNative transition((JavaThread*)thread); + ResetNoHandleMark rnhm; + elements = ::flush_type_set(thread); + } else { + elements = ::flush_type_set(thread); + } } if (is_constant_pending()) { WriteOperation wo(_chunkwriter); MutexedWriteOperation mwo(wo); - assert(_mspace->live_list_is_nonempty(), "invariant"); - process_live_list(mwo, _mspace); + _thread_local_mspace->iterate(mwo); // current epoch list + assert(_global_mspace->live_list_is_nonempty(), "invariant"); + process_live_list(mwo, _global_mspace); // current epoch list } return elements; } diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp index d9c2ad8391a..428b6e6fe2a 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp @@ -26,14 +26,13 @@ #define SHARE_JFR_RECORDER_CHECKPOINT_JFRCHECKPOINTMANAGER_HPP #include "jfr/recorder/storage/jfrBuffer.hpp" +#include "jfr/recorder/storage/jfrEpochStorage.hpp" #include "jfr/recorder/storage/jfrMemorySpace.hpp" #include "jfr/recorder/storage/jfrMemorySpaceRetrieval.hpp" #include "jfr/utilities/jfrLinkedList.hpp" class JfrCheckpointManager; class JfrChunkWriter; -class JfrSerializer; -class JfrTypeManager; class Thread; struct JfrCheckpointEntry { @@ -45,6 +44,7 @@ struct JfrCheckpointEntry { }; typedef JfrMemorySpace, JfrLinkedList, true > JfrCheckpointMspace; +typedef JfrEpochStorageHost JfrThreadLocalCheckpointMspace; // // Responsible for maintaining checkpoints and by implication types. @@ -56,7 +56,8 @@ class JfrCheckpointManager : public JfrCHeapObj { typedef JfrCheckpointMspace::Node Buffer; typedef JfrCheckpointMspace::NodePtr BufferPtr; private: - JfrCheckpointMspace* _mspace; + JfrCheckpointMspace* _global_mspace; + JfrThreadLocalCheckpointMspace* _thread_local_mspace; JfrChunkWriter& _chunkwriter; JfrCheckpointManager(JfrChunkWriter& cw); @@ -66,14 +67,16 @@ class JfrCheckpointManager : public JfrCHeapObj { bool initialize(); static void destroy(); - bool lookup(Buffer* old) const; static BufferPtr lease(Thread* thread, bool previous_epoch = false, size_t size = 0); - static BufferPtr lease(BufferPtr old, Thread* thread, size_t size = 0); + static BufferPtr lease(BufferPtr old, Thread* thread, size_t size); + + static BufferPtr acquire_thread_local(size_t size, Thread* thread); + static BufferPtr lease_thread_local(Thread* thread, size_t size = 0); + static BufferPtr flush(BufferPtr old, size_t used, size_t requested, Thread* thread); size_t clear(); size_t write(); - size_t flush(); void notify_threads(); size_t write_static_type_set(Thread* thread); @@ -102,7 +105,6 @@ class JfrCheckpointManager : public JfrCHeapObj { friend class JfrCheckpointFlush; friend class JfrCheckpointWriter; friend class JfrSerializer; - friend class JfrStackTraceRepository; template class, typename, typename, bool> friend class JfrMemorySpace; }; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp index 604dce389ba..12497802cf7 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.cpp @@ -45,8 +45,8 @@ JfrCheckpointWriter::JfrCheckpointWriter(JfrCheckpointType type /* GENERIC */) : } } -JfrCheckpointWriter::JfrCheckpointWriter(Thread* thread, bool header /* true */, JfrCheckpointType type /* GENERIC */) : - JfrCheckpointWriterBase(JfrCheckpointManager::lease(thread), thread), +JfrCheckpointWriter::JfrCheckpointWriter(Thread* thread, bool header /* true */, JfrCheckpointType type /* GENERIC */, bool global_lease /* true */) : + JfrCheckpointWriterBase(global_lease ? JfrCheckpointManager::lease(thread) : JfrCheckpointManager::lease_thread_local(thread), thread), _time(JfrTicks::now()), _offset(0), _count(0), diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp index 2a2e0f14797..3666d7f747b 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp @@ -72,7 +72,7 @@ class JfrCheckpointWriter : public JfrCheckpointWriterBase { JfrCheckpointWriter(bool previous_epoch, Thread* thread, JfrCheckpointType type = GENERIC); public: JfrCheckpointWriter(JfrCheckpointType type = GENERIC); - JfrCheckpointWriter(Thread* thread, bool header = true, JfrCheckpointType mode = GENERIC); + JfrCheckpointWriter(Thread* thread, bool header = true, JfrCheckpointType mode = GENERIC, bool global_lease = true); ~JfrCheckpointWriter(); void write_type(JfrTypeId type_id); void write_count(u4 nof_entries); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp index 5c30e1699b2..40525969efe 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp @@ -28,6 +28,7 @@ #include "jfr/recorder/checkpoint/types/jfrType.hpp" #include "jfr/recorder/checkpoint/types/jfrTypeManager.hpp" #include "jfr/recorder/jfrRecorder.hpp" +#include "jfr/support/jfrThreadLocal.hpp" #include "jfr/utilities/jfrIterator.hpp" #include "jfr/utilities/jfrLinkedList.inline.hpp" #include "memory/resourceArea.hpp" @@ -105,7 +106,7 @@ void JfrTypeManager::create_thread_blob(Thread* t) { ResourceMark rm(t); HandleMark hm(t); JfrThreadConstant type_thread(t); - JfrCheckpointWriter writer(t, true, THREADS); + JfrCheckpointWriter writer(t, true, THREADS, false); writer.write_type(TYPE_THREAD); type_thread.serialize(writer); // create and install a checkpoint blob @@ -115,12 +116,11 @@ void JfrTypeManager::create_thread_blob(Thread* t) { void JfrTypeManager::write_thread_checkpoint(Thread* t) { assert(t != NULL, "invariant"); - ResourceMark rm(t); - HandleMark hm(t); - JfrThreadConstant type_thread(t); - JfrCheckpointWriter writer(t, true, THREADS); - writer.write_type(TYPE_THREAD); - type_thread.serialize(writer); + if (!t->jfr_thread_local()->has_thread_blob()) { + create_thread_blob(t); + } + JfrCheckpointWriter writer(t, false, THREADS, false); + t->jfr_thread_local()->thread_blob()->write(writer); } class SerializerRegistrationGuard : public StackObj { diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index db3c8f5ce3f..1792602489c 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -761,6 +761,7 @@ int write__method(JfrCheckpointWriter* writer, const void* m) { int write__method__leakp(JfrCheckpointWriter* writer, const void* m) { assert(m != NULL, "invariant"); MethodPtr method = (MethodPtr)m; + CLEAR_LEAKP_METHOD(method); return write_method(writer, method, true); } diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp index 9ea39ae0ff7..138a85ed005 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp @@ -170,6 +170,13 @@ void JfrTraceId::remove(const Klass* k) { k->set_trace_id(EVENT_KLASS_MASK(k)); } +// used by CDS / APPCDS as part of "remove_unshareable_info" +void JfrTraceId::remove(const Method* method) { + assert(method != NULL, "invariant"); + // Clear all bits. + method->set_trace_flags(0); +} + // used by CDS / APPCDS as part of "restore_unshareable_info" void JfrTraceId::restore(const Klass* k) { assert(k != NULL, "invariant"); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp index 9110f7d5554..2a67e57de8a 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp @@ -106,6 +106,7 @@ class JfrTraceId : public AllStatic { static traceid load_raw(const ClassLoaderData* cld); static void remove(const Klass* klass); + static void remove(const Method* method); static void restore(const Klass* klass); // set of event classes made visible to java diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp index b25500afc70..14b008b1d51 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp @@ -145,6 +145,7 @@ #define CLEAR_SERIALIZED_METHOD(method) (METHOD_META_MASK_CLEAR(method, META_MASK)) #define SET_PREVIOUS_EPOCH_METHOD_CLEARED_BIT(ptr) (METHOD_META_TAG(ptr, PREVIOUS_EPOCH_BIT)) #define CLEAR_LEAKP(ptr) (TRACE_ID_META_MASK_CLEAR(ptr, (~(LEAKP_META_BIT)))) +#define CLEAR_LEAKP_METHOD(method) (METHOD_META_MASK_CLEAR(method, (~(LEAKP_META_BIT)))) #define CLEAR_THIS_EPOCH_CLEARED_BIT(ptr) (TRACE_ID_META_MASK_CLEAR(ptr,(~(THIS_EPOCH_BIT)))) #define CLEAR_THIS_EPOCH_METHOD_CLEARED_BIT(ptr) (METHOD_META_MASK_CLEAR(ptr,(~(THIS_EPOCH_BIT)))) #define IS_THIS_EPOCH_METHOD_CLEARED(ptr) (METHOD_FLAG_PREDICATE(method, THIS_EPOCH_BIT)) diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp index 22b0955e15c..05907a6a757 100644 --- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp +++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp @@ -172,8 +172,8 @@ static void log_jdk_jfr_module_resolution_error(TRAPS) { } static bool is_cds_dump_requested() { - // we will not be able to launch recordings if a cds dump is being requested - if (Arguments::is_dumping_archive() && (JfrOptionSet::start_flight_recording_options() != NULL)) { + // we will not be able to launch recordings on startup if a cds dump is being requested + if (Arguments::is_dumping_archive() && JfrOptionSet::start_flight_recording_options() != NULL) { warning("JFR will be disabled during CDS dumping"); teardown_startup_support(); return true; @@ -213,7 +213,7 @@ bool JfrRecorder::on_create_vm_2() { bool JfrRecorder::on_create_vm_3() { assert(JvmtiEnvBase::get_phase() == JVMTI_PHASE_LIVE, "invalid init sequence"); - return launch_command_line_recordings(Thread::current()); + return Arguments::is_dumping_archive() || launch_command_line_recordings(Thread::current()); } static bool _created = false; diff --git a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp index e908bfef699..838d126c00a 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp @@ -32,9 +32,10 @@ JfrBuffer::JfrBuffer() : _next(NULL), _identity(NULL), _pos(NULL), _top(NULL), - _flags(0), + _size(0), _header_size(0), - _size(0) {} + _flags(0), + _context(0) {} bool JfrBuffer::initialize(size_t header_size, size_t size) { assert(_next == NULL, "invariant"); @@ -52,7 +53,6 @@ bool JfrBuffer::initialize(size_t header_size, size_t size) { void JfrBuffer::reinitialize(bool exclusion /* false */) { acquire_critical_section_top(); - assert(!lease(), "invariant"); if (exclusion != excluded()) { // update if (exclusion) { @@ -185,25 +185,25 @@ enum FLAG { EXCLUDED = 8 }; -inline u2 load(const volatile u2* flags) { - assert(flags != NULL, "invariant"); - return Atomic::load_acquire(flags); +inline u1 load(const volatile u1* dest) { + assert(dest != NULL, "invariant"); + return Atomic::load_acquire(dest); } -inline void set(u2* flags, FLAG flag) { - assert(flags != NULL, "invariant"); +inline void set(u1* dest, u1 data) { + assert(dest != NULL, "invariant"); OrderAccess::storestore(); - *flags |= (u1)flag; + *dest |= data; } -inline void clear(u2* flags, FLAG flag) { - assert(flags != NULL, "invariant"); +inline void clear(u1* dest, u1 data) { + assert(dest != NULL, "invariant"); OrderAccess::storestore(); - *flags ^= (u1)flag; + *dest ^= data; } -inline bool test(const u2* flags, FLAG flag) { - return (u1)flag == (load(flags) & (u1)flag); +inline bool test(const u1* dest, u1 data) { + return data == (load(dest) & data); } bool JfrBuffer::transient() const { @@ -273,3 +273,15 @@ void JfrBuffer::clear_retired() { clear(&_flags, RETIRED); } } + +u1 JfrBuffer::context() const { + return load(&_context); +} + +void JfrBuffer::set_context(u1 context) { + set(&_context, context); +} + +void JfrBuffer::clear_context() { + set(&_context, 0); +} diff --git a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp index f26eef06945..120c7311321 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp @@ -44,6 +44,10 @@ // e.g. the delta must always be fully parsable. // _top can move concurrently by other threads but is always <= _pos. // +// The _flags field holds generic tags applicable to all subsystems. +// +// The _context field can be used to set subsystem specific tags onto a buffer. +// // Memory ordering: // // Method Owner thread Other threads @@ -66,9 +70,10 @@ class JfrBuffer { const void* _identity; u1* _pos; mutable const u1* _top; - u2 _flags; - u2 _header_size; u4 _size; + u2 _header_size; + u1 _flags; + u1 _context; const u1* stable_top() const; @@ -168,6 +173,10 @@ class JfrBuffer { bool excluded() const; void set_excluded(); void clear_excluded(); + + u1 context() const; + void set_context(u1 context); + void clear_context(); }; #endif // SHARE_JFR_RECORDER_STORAGE_JFRBUFFER_HPP diff --git a/src/hotspot/share/jfr/recorder/storage/jfrEpochStorage.hpp b/src/hotspot/share/jfr/recorder/storage/jfrEpochStorage.hpp index 7592cbd6917..02f6a0ca774 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrEpochStorage.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrEpochStorage.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,9 +33,19 @@ /* * Provides storage as a function of an epoch, with iteration capabilities for the current and previous epoch. - * Iteration over the current epoch is incremental while iteration over the previous epoch is complete, - * including storage reclamation. The design caters to use cases having multiple incremental iterations - * over the current epoch, and a single, complete, iteration over the previous epoch. + * + * When iterating the previous epoch, where exclusive access to buffers is assumed, + * all buffers will be reinitialized post-callback, with retired buffers reclaimed + * and moved onto the free list and non-retired buffers left in-place. + * + * When iterating the current epoch, where concurrent access to buffers is assumed, + * there exist two modes, controlled by the EagerReclaim parameter. + * By default, EagerReclaim is false, meaning no retired buffers are reclaimed during the current epoch. + * Setting EagerReclaim to true, retired buffers will be reclaimed post-callback, by reinitialization + * and by moving them onto the free list, just like is done when iterating the previous epoch. + * + * The design caters to use cases having multiple incremental iterations over the current epoch, + * and a single iteration over the previous epoch. * * The JfrEpochStorage can be specialized by the following policies: * @@ -43,10 +53,12 @@ * * RetrievalPolicy see jfrMemorySpace.hpp for a description. * + * EagerReclaim should retired buffers be reclaimed also during the current epoch (i.e. eagerly) + * */ -template class RetrievalPolicy> +template class RetrievalPolicy, bool EagerReclaim = false> class JfrEpochStorageHost : public JfrCHeapObj { - typedef JfrMemorySpace, + typedef JfrMemorySpace, RetrievalPolicy, JfrConcurrentQueue, JfrLinkedList, diff --git a/src/hotspot/share/jfr/recorder/storage/jfrEpochStorage.inline.hpp b/src/hotspot/share/jfr/recorder/storage/jfrEpochStorage.inline.hpp index 725a08a92c4..464d393adc1 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrEpochStorage.inline.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrEpochStorage.inline.hpp @@ -32,23 +32,23 @@ #include "jfr/utilities/jfrLinkedList.inline.hpp" #include "logging/log.hpp" -template class RetrievalPolicy> -JfrEpochStorageHost::JfrEpochStorageHost() : _mspace(NULL) {} +template class RetrievalPolicy, bool EagerReclaim> +JfrEpochStorageHost::JfrEpochStorageHost() : _mspace(NULL) {} -template class RetrievalPolicy> -JfrEpochStorageHost::~JfrEpochStorageHost() { +template class RetrievalPolicy, bool EagerReclaim> +JfrEpochStorageHost::~JfrEpochStorageHost() { delete _mspace; } -template class RetrievalPolicy> -bool JfrEpochStorageHost::initialize(size_t min_elem_size, size_t free_list_cache_count_limit, size_t cache_prealloc_count) { +template class RetrievalPolicy, bool EagerReclaim> +bool JfrEpochStorageHost::initialize(size_t min_elem_size, size_t free_list_cache_count_limit, size_t cache_prealloc_count) { assert(_mspace == NULL, "invariant"); _mspace = new EpochMspace(min_elem_size, free_list_cache_count_limit, this); return _mspace != NULL && _mspace->initialize(cache_prealloc_count); } -template class RetrievalPolicy> -inline NodeType* JfrEpochStorageHost::acquire(size_t size, Thread* thread) { +template class RetrievalPolicy, bool EagerReclaim> +inline NodeType* JfrEpochStorageHost::acquire(size_t size, Thread* thread) { BufferPtr buffer = mspace_acquire_to_live_list(size, _mspace, thread); if (buffer == NULL) { log_warning(jfr)("Unable to allocate " SIZE_FORMAT " bytes of %s.", _mspace->min_element_size(), "epoch storage"); @@ -58,29 +58,37 @@ inline NodeType* JfrEpochStorageHost::acquire(size_t return buffer; } -template class RetrievalPolicy> -void JfrEpochStorageHost::release(NodeType* buffer) { +template class RetrievalPolicy, bool EagerReclaim> +void JfrEpochStorageHost::release(NodeType* buffer) { assert(buffer != NULL, "invariant"); buffer->set_retired(); } -template class RetrievalPolicy> -void JfrEpochStorageHost::register_full(NodeType* buffer, Thread* thread) { +template class RetrievalPolicy, bool EagerReclaim> +void JfrEpochStorageHost::register_full(NodeType* buffer, Thread* thread) { // nothing here at the moment } -template class RetrievalPolicy> +template class RetrievalPolicy, bool EagerReclaim> template -void JfrEpochStorageHost::iterate(Functor& functor, bool previous_epoch) { - typedef ReleaseRetiredToFreeListOp ReleaseStorage; - typedef CompositeOperation PreviousEpochOperation; +void JfrEpochStorageHost::iterate(Functor& functor, bool previous_epoch) { + typedef ReinitializeAllReleaseRetiredOp PreviousEpochReleaseOperation; + typedef CompositeOperation PreviousEpochOperation; + typedef ReleaseRetiredOp CurrentEpochReleaseOperation; + typedef CompositeOperation CurrentEpochOperation; if (previous_epoch) { - ReleaseStorage rs(_mspace, _mspace->live_list(true)); - PreviousEpochOperation peo(&functor, &rs); - process_live_list(peo, _mspace, true); + PreviousEpochReleaseOperation pero(_mspace, _mspace->live_list(true)); + PreviousEpochOperation peo(&functor, &pero); + process_live_list(peo, _mspace, true); // previous epoch list return; } - process_live_list(functor, _mspace, false); + if (EagerReclaim) { + CurrentEpochReleaseOperation cero(_mspace, _mspace->live_list()); + CurrentEpochOperation ceo(&functor, &cero); + process_live_list(ceo, _mspace, false); // current epoch list + return; + } + process_live_list(functor, _mspace, false); // current epoch list } #ifdef ASSERT @@ -100,8 +108,8 @@ class EmptyVerifier { } }; -template class RetrievalPolicy> -void JfrEpochStorageHost::verify_previous_empty() const { +template class RetrievalPolicy, bool EagerReclaim> +void JfrEpochStorageHost::verify_previous_empty() const { typedef EmptyVerifier VerifyEmptyMspace; VerifyEmptyMspace vem(_mspace); process_live_list(vem, _mspace, true); diff --git a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp index 40d585f42b0..47ae658b7b2 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp @@ -493,14 +493,14 @@ inline bool ReleaseOp::process(typename Mspace::NodePtr node) { } template -class ReleaseOpWithExcision : public ReleaseOp { +class ReleaseWithExcisionOp : public ReleaseOp { private: List& _list; typename List::NodePtr _prev; size_t _count; size_t _amount; public: - ReleaseOpWithExcision(Mspace* mspace, List& list) : + ReleaseWithExcisionOp(Mspace* mspace, List& list) : ReleaseOp(mspace), _list(list), _prev(NULL), _count(0), _amount(0) {} bool process(typename List::NodePtr node); size_t processed() const { return _count; } @@ -508,7 +508,7 @@ class ReleaseOpWithExcision : public ReleaseOp { }; template -inline bool ReleaseOpWithExcision::process(typename List::NodePtr node) { +inline bool ReleaseWithExcisionOp::process(typename List::NodePtr node) { assert(node != NULL, "invariant"); if (node->transient()) { _prev = _list.excise(_prev, node); @@ -569,20 +569,49 @@ inline bool ScavengingReleaseOp::excise_with_release(typename List } template -class ReleaseRetiredToFreeListOp : public StackObj { +class ReleaseRetiredOp : public StackObj { +private: + Mspace* _mspace; + FromList& _list; + typename Mspace::NodePtr _prev; +public: + typedef typename Mspace::Node Node; + ReleaseRetiredOp(Mspace* mspace, FromList& list) : + _mspace(mspace), _list(list), _prev(NULL) {} + bool process(Node* node); +}; + +template +inline bool ReleaseRetiredOp::process(typename Mspace::Node* node) { + assert(node != NULL, "invariant"); + if (node->retired()) { + _prev = _list.excise(_prev, node); + node->reinitialize(); + assert(node->empty(), "invariant"); + assert(!node->retired(), "invariant"); + node->release(); + mspace_release(node, _mspace); + } else { + _prev = node; + } + return true; +} + +template +class ReinitializeAllReleaseRetiredOp : public StackObj { private: Mspace* _mspace; FromList& _list; typename Mspace::NodePtr _prev; public: typedef typename Mspace::Node Node; - ReleaseRetiredToFreeListOp(Mspace* mspace, FromList& list) : + ReinitializeAllReleaseRetiredOp(Mspace* mspace, FromList& list) : _mspace(mspace), _list(list), _prev(NULL) {} bool process(Node* node); }; template -inline bool ReleaseRetiredToFreeListOp::process(typename Mspace::Node* node) { +inline bool ReinitializeAllReleaseRetiredOp::process(typename Mspace::Node* node) { assert(node != NULL, "invariant"); // assumes some means of exclusive access to node const bool retired = node->retired(); diff --git a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp index 230baf33a23..de836b00064 100644 --- a/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp +++ b/src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp @@ -208,7 +208,7 @@ typedef StringPoolOp WriteOperation; typedef StringPoolOp DiscardOperation; typedef ExclusiveOp ExclusiveWriteOperation; typedef ExclusiveOp ExclusiveDiscardOperation; -typedef ReleaseOpWithExcision ReleaseOperation; +typedef ReleaseWithExcisionOp ReleaseOperation; typedef CompositeOperation WriteReleaseOperation; typedef CompositeOperation DiscardReleaseOperation; diff --git a/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp b/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp index 98cac9e35c0..f21e9fdd37d 100644 --- a/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp +++ b/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ #define INIT_ID(data) JfrTraceId::assign(data) #define REMOVE_ID(k) JfrTraceId::remove(k); +#define REMOVE_METHOD_ID(method) JfrTraceId::remove(method); #define RESTORE_ID(k) JfrTraceId::restore(k); class JfrTraceFlag { diff --git a/src/hotspot/share/jfr/utilities/jfrConcurrentLinkedListHost.inline.hpp b/src/hotspot/share/jfr/utilities/jfrConcurrentLinkedListHost.inline.hpp index 48b54fda18a..0f3e8fb55b9 100644 --- a/src/hotspot/share/jfr/utilities/jfrConcurrentLinkedListHost.inline.hpp +++ b/src/hotspot/share/jfr/utilities/jfrConcurrentLinkedListHost.inline.hpp @@ -34,7 +34,7 @@ /* * The removal marker (i.e. the excision bit) is represented by '( )' as part of state description comments: - * node --> next becomes (node) --> next, when node is logically deleted. + * "node --> next" becomes "(node) --> next", when node is logically deleted. */ template inline Node* mark_for_removal(Node* node) { @@ -47,7 +47,7 @@ inline Node* mark_for_removal(Node* node) { /* * The insertion marker (i.e. the insertion bit) is represented by '[ ]' as part of state description comments: - * "node --> next" becomes "[node} --> next", in an attempt to convey node as being exlusively reserved. + * "node --> next" becomes "[node] --> next", in an attempt to convey node as being exlusively reserved. */ template inline bool mark_for_insertion(Node* node, const Node* tail) { diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 4d1809d1d87..3189df4d9ba 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -1025,7 +1025,7 @@ C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod); nmethodLocker locker; nmethod* nm = JVMCIENV->get_nmethod(nmethod_mirror, locker); - if (nm == NULL) { + if (nm == NULL || !nm->is_in_use()) { JVMCI_THROW_NULL(InvalidInstalledCodeException); } methodHandle mh(THREAD, nm->method()); @@ -1034,7 +1034,7 @@ C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static()); JavaValue result(jap.return_type()); - jca.set_alternative_target(nm); + jca.set_alternative_target(Handle(THREAD, JNIHandles::resolve(nmethod_mirror.as_jobject()))); JavaCalls::call(&result, mh, &jca, CHECK_NULL); if (jap.return_type() == T_VOID) { @@ -1768,6 +1768,18 @@ C2V_VMENTRY(void, ensureInitialized, (JNIEnv* env, jobject, jobject jvmci_type)) } C2V_END +C2V_VMENTRY(void, ensureLinked, (JNIEnv* env, jobject, jobject jvmci_type)) + if (jvmci_type == NULL) { + JVMCI_THROW(NullPointerException); + } + + Klass* klass = JVMCIENV->asKlass(jvmci_type); + if (klass != NULL && klass->is_instance_klass()) { + InstanceKlass* k = InstanceKlass::cast(klass); + k->link_class(CHECK); + } +C2V_END + C2V_VMENTRY_0(jint, interpreterFrameSize, (JNIEnv* env, jobject, jobject bytecode_frame_handle)) if (bytecode_frame_handle == NULL) { JVMCI_THROW_0(NullPointerException); @@ -2775,6 +2787,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getInterfaces", CC "(" HS_RESOLVED_KLASS ")[" HS_RESOLVED_KLASS, FN_PTR(getInterfaces)}, {CC "getComponentType", CC "(" HS_RESOLVED_KLASS ")" HS_RESOLVED_TYPE, FN_PTR(getComponentType)}, {CC "ensureInitialized", CC "(" HS_RESOLVED_KLASS ")V", FN_PTR(ensureInitialized)}, + {CC "ensureLinked", CC "(" HS_RESOLVED_KLASS ")V", FN_PTR(ensureLinked)}, {CC "getIdentityHashCode", CC "(" OBJECTCONSTANT ")I", FN_PTR(getIdentityHashCode)}, {CC "isInternedString", CC "(" OBJECTCONSTANT ")Z", FN_PTR(isInternedString)}, {CC "unboxPrimitive", CC "(" OBJECTCONSTANT ")" OBJECT, FN_PTR(unboxPrimitive)}, diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 27d191f304b..5f514b76f75 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -555,7 +555,14 @@ declare_constant(InstanceKlass::linked) \ declare_constant(InstanceKlass::being_initialized) \ declare_constant(InstanceKlass::fully_initialized) \ + \ + /*********************************/ \ + /* InstanceKlass _misc_flags */ \ + /*********************************/ \ + \ declare_constant(InstanceKlass::_misc_is_unsafe_anonymous) \ + declare_constant(InstanceKlass::_misc_has_nonstatic_concrete_methods) \ + declare_constant(InstanceKlass::_misc_declares_nonstatic_concrete_methods) \ \ declare_constant(JumpData::taken_off_set) \ declare_constant(JumpData::displacement_off_set) \ diff --git a/src/hotspot/share/libadt/vectset.cpp b/src/hotspot/share/libadt/vectset.cpp index ca085f2898c..9c711a7021b 100644 --- a/src/hotspot/share/libadt/vectset.cpp +++ b/src/hotspot/share/libadt/vectset.cpp @@ -24,15 +24,24 @@ #include "precompiled.hpp" #include "libadt/vectset.hpp" -#include "memory/allocation.inline.hpp" #include "memory/arena.hpp" +#include "memory/resourceArea.hpp" #include "utilities/count_leading_zeros.hpp" #include "utilities/powerOfTwo.hpp" -VectorSet::VectorSet(Arena *arena) : _size(2), - _data(NEW_ARENA_ARRAY(arena, uint32_t, 2)), - _data_size(2), - _set_arena(arena) { +VectorSet::VectorSet() { + init(Thread::current()->resource_area()); +} + +VectorSet::VectorSet(Arena* arena) { + init(arena); +} + +void VectorSet::init(Arena* arena) { + _size = 2; + _data = NEW_ARENA_ARRAY(arena, uint32_t, 2); + _data_size = 2; + _set_arena = arena; _data[0] = 0; _data[1] = 0; } diff --git a/src/hotspot/share/libadt/vectset.hpp b/src/hotspot/share/libadt/vectset.hpp index b980d3d1d23..0b0da1296c7 100644 --- a/src/hotspot/share/libadt/vectset.hpp +++ b/src/hotspot/share/libadt/vectset.hpp @@ -47,10 +47,12 @@ class VectorSet : public ResourceObj { uint _data_size; Arena* _set_arena; + void init(Arena* arena); // Grow vector to required word capacity void grow(uint new_word_capacity); public: - VectorSet(Arena *arena); + VectorSet(); + VectorSet(Arena* arena); ~VectorSet() {} void insert(uint elem); diff --git a/src/hotspot/share/memory/filemap.cpp b/src/hotspot/share/memory/filemap.cpp index c53613cc781..a0ac1871c64 100644 --- a/src/hotspot/share/memory/filemap.cpp +++ b/src/hotspot/share/memory/filemap.cpp @@ -749,6 +749,11 @@ bool FileMapInfo::validate_boot_class_paths() { num = rp_len; } mismatch = check_paths(1, num, rp_array); + } else { + // create_path_array() ignores non-existing paths. Although the dump time and runtime boot classpath lengths + // are the same initially, after the call to create_path_array(), the runtime boot classpath length could become + // shorter. We consider boot classpath mismatch in this case. + mismatch = true; } } @@ -775,6 +780,12 @@ bool FileMapInfo::validate_app_class_paths(int shared_app_paths_len) { // None of the jar file specified in the runtime -cp exists. return classpath_failure("None of the jar file specified in the runtime -cp exists: -Djava.class.path=", appcp); } + if (rp_array->length() < shared_app_paths_len) { + // create_path_array() ignores non-existing paths. Although the dump time and runtime app classpath lengths + // are the same initially, after the call to create_path_array(), the runtime app classpath length could become + // shorter. We consider app classpath mismatch in this case. + return classpath_failure("[APP classpath mismatch, actual: -Djava.class.path=", appcp); + } // Handling of non-existent entries in the classpath: we eliminate all the non-existent // entries from both the dump time classpath (ClassLoader::update_class_path_entry_list) diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index 00c24c83085..c3e4355112d 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -665,6 +665,33 @@ class CollectClassesClosure : public KlassClosure { } }; +// Global object for holding symbols that created during class loading. See SymbolTable::new_symbol +static GrowableArray* _global_symbol_objects = NULL; + +static int compare_symbols_by_address(Symbol** a, Symbol** b) { + if (a[0] < b[0]) { + return -1; + } else if (a[0] == b[0]) { + ResourceMark rm; + log_warning(cds)("Duplicated symbol %s unexpected", (*a)->as_C_string()); + return 0; + } else { + return 1; + } +} + +void MetaspaceShared::add_symbol(Symbol* sym) { + MutexLocker ml(CDSAddSymbol_lock, Mutex::_no_safepoint_check_flag); + if (_global_symbol_objects == NULL) { + _global_symbol_objects = new (ResourceObj::C_HEAP, mtSymbol) GrowableArray(2048, mtSymbol); + } + _global_symbol_objects->append(sym); +} + +GrowableArray* MetaspaceShared::collected_symbols() { + return _global_symbol_objects; +} + static void remove_unshareable_in_classes() { for (int i = 0; i < _global_klass_objects->length(); i++) { Klass* k = _global_klass_objects->at(i); @@ -1244,34 +1271,6 @@ class VM_PopulateDumpSharedSpace: public VM_Operation { bool allow_nested_vm_operations() const { return true; } }; // class VM_PopulateDumpSharedSpace -class SortedSymbolClosure: public SymbolClosure { - GrowableArray _symbols; - virtual void do_symbol(Symbol** sym) { - assert((*sym)->is_permanent(), "archived symbols must be permanent"); - _symbols.append(*sym); - } - static int compare_symbols_by_address(Symbol** a, Symbol** b) { - if (a[0] < b[0]) { - return -1; - } else if (a[0] == b[0]) { - ResourceMark rm; - log_warning(cds)("Duplicated symbol %s unexpected", (*a)->as_C_string()); - return 0; - } else { - return 1; - } - } - -public: - SortedSymbolClosure() { - SymbolTable::symbols_do(this); - _symbols.sort(compare_symbols_by_address); - } - GrowableArray* get_sorted_symbols() { - return &_symbols; - } -}; - // ArchiveCompactor -- // // This class is the central piece of shared archive compaction -- all metaspace data are @@ -1283,7 +1282,6 @@ class ArchiveCompactor : AllStatic { static const int MAX_TABLE_SIZE = 1000000; static DumpAllocStats* _alloc_stats; - static SortedSymbolClosure* _ssc; typedef KVHashtable RelocationTable; static RelocationTable* _new_loc_table; @@ -1441,8 +1439,6 @@ class ArchiveCompactor : AllStatic { public: static void copy_and_compact() { ResourceMark rm; - SortedSymbolClosure the_ssc; // StackObj - _ssc = &the_ssc; log_info(cds)("Scanning all metaspace objects ... "); { @@ -1478,9 +1474,11 @@ class ArchiveCompactor : AllStatic { { log_info(cds)("Fixing symbol identity hash ... "); os::init_random(0x12345678); - GrowableArray* symbols = _ssc->get_sorted_symbols(); - for (int i=0; ilength(); i++) { - symbols->at(i)->update_identity_hash(); + GrowableArray* all_symbols = MetaspaceShared::collected_symbols(); + all_symbols->sort(compare_symbols_by_address); + for (int i = 0; i < all_symbols->length(); i++) { + assert(all_symbols->at(i)->is_permanent(), "archived symbols must be permanent"); + all_symbols->at(i)->update_identity_hash(); } } #ifdef ASSERT @@ -1491,10 +1489,6 @@ class ArchiveCompactor : AllStatic { iterate_roots(&checker); } #endif - - - // cleanup - _ssc = NULL; } // We must relocate the System::_well_known_klasses only after we have copied the @@ -1530,8 +1524,8 @@ class ArchiveCompactor : AllStatic { // (see Symbol::operator new(size_t, int)). So if we iterate the Symbols by // ascending address order, we ensure that all Symbols are copied into deterministic // locations in the archive. - GrowableArray* symbols = _ssc->get_sorted_symbols(); - for (int i=0; ilength(); i++) { + GrowableArray* symbols = _global_symbol_objects; + for (int i = 0; i < symbols->length(); i++) { it->push(symbols->adr_at(i)); } if (_global_klass_objects != NULL) { @@ -1561,7 +1555,6 @@ class ArchiveCompactor : AllStatic { }; DumpAllocStats* ArchiveCompactor::_alloc_stats; -SortedSymbolClosure* ArchiveCompactor::_ssc; ArchiveCompactor::RelocationTable* ArchiveCompactor::_new_loc_table; void VM_PopulateDumpSharedSpace::dump_symbols() { diff --git a/src/hotspot/share/memory/metaspaceShared.hpp b/src/hotspot/share/memory/metaspaceShared.hpp index 326522c4ae0..15efa49e947 100644 --- a/src/hotspot/share/memory/metaspaceShared.hpp +++ b/src/hotspot/share/memory/metaspaceShared.hpp @@ -213,6 +213,8 @@ class MetaspaceShared : AllStatic { TRAPS) NOT_CDS_RETURN_(0); static GrowableArray* collected_klasses(); + static GrowableArray* collected_symbols(); + static void add_symbol(Symbol* sym) NOT_CDS_RETURN; static ReservedSpace* shared_rs() { CDS_ONLY(return &_shared_rs); diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 330e6856c8d..ce638deb25a 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -369,6 +369,7 @@ void Method::metaspace_pointers_do(MetaspaceClosure* it) { void Method::remove_unshareable_info() { unlink_method(); + JFR_ONLY(REMOVE_METHOD_ID(this);) } void Method::set_vtable_index(int index) { diff --git a/src/hotspot/share/opto/block.cpp b/src/hotspot/share/opto/block.cpp index bbc9626bf6f..22e6d927c34 100644 --- a/src/hotspot/share/opto/block.cpp +++ b/src/hotspot/share/opto/block.cpp @@ -403,11 +403,10 @@ PhaseCFG::PhaseCFG(Arena* arena, RootNode* root, Matcher& matcher) // The RootNode both starts and ends it's own block. Do this with a recursive // backwards walk over the control edges. uint PhaseCFG::build_cfg() { - Arena *a = Thread::current()->resource_area(); - VectorSet visited(a); + VectorSet visited; // Allocate stack with enough space to avoid frequent realloc - Node_Stack nstack(a, C->live_nodes() >> 1); + Node_Stack nstack(C->live_nodes() >> 1); nstack.push(_root, 0); uint sum = 0; // Counter for blocks diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index 6cc69a0087e..3e1218cb784 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -246,9 +246,6 @@ develop(bool, UseUniqueSubclasses, true, \ "Narrow an abstract reference to the unique concrete subclass") \ \ - develop(bool, UseExactTypes, true, \ - "Use exact types to eliminate array store checks and v-calls") \ - \ product(intx, TrackedInitializationLimit, 50, \ "When initializing fields, track up to this many words") \ range(0, 65535) \ diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 4d90e73d6a7..dfb3799b4c4 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -347,9 +347,8 @@ bool RegionNode::is_unreachable_region(PhaseGVN *phase) const { // Unsafe case - check if the Region node is reachable from root. ResourceMark rm; - Arena *a = Thread::current()->resource_area(); - Node_List nstack(a); - VectorSet visited(a); + Node_List nstack; + VectorSet visited; // Mark all control nodes reachable from root outputs Node *n = (Node*)phase->C->root(); @@ -1047,7 +1046,7 @@ void PhiNode::verify_adr_type(bool recursive) const { "Phi::adr_type must be pre-normalized"); if (recursive) { - VectorSet visited(Thread::current()->resource_area()); + VectorSet visited; verify_adr_type(visited, _adr_type); } } @@ -1790,9 +1789,8 @@ bool PhiNode::is_unsafe_data_reference(Node *in) const { ResourceMark rm; - Arena *a = Thread::current()->resource_area(); - Node_List nstack(a); - VectorSet visited(a); + Node_List nstack; + VectorSet visited; nstack.push(in); // Start with unique input. visited.set(in->_idx); diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp index 71f6a7c3382..88de3924686 100644 --- a/src/hotspot/share/opto/chaitin.cpp +++ b/src/hotspot/share/opto/chaitin.cpp @@ -202,8 +202,6 @@ PhaseChaitin::PhaseChaitin(uint unique, PhaseCFG &cfg, Matcher &matcher, bool sc #endif ) , _live(0) - , _spilled_once(Thread::current()->resource_area()) - , _spilled_twice(Thread::current()->resource_area()) , _lo_degree(0), _lo_stk_degree(0), _hi_degree(0), _simplified(0) , _oldphi(unique) #ifndef PRODUCT diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index a8b7196bdc3..bc0f0c2e5fd 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -1018,6 +1018,7 @@ void Compile::Init(int aliaslevel) { register_library_intrinsics(); #ifdef ASSERT _type_verify_symmetry = true; + _phase_optimize_finished = false; #endif } @@ -2659,6 +2660,7 @@ void Compile::Optimize() { } print_method(PHASE_OPTIMIZE_FINISHED, 2); + DEBUG_ONLY(set_phase_optimize_finished();) } //---------------------------- Bitwise operation packing optimization --------------------------- @@ -3103,8 +3105,7 @@ struct Final_Reshape_Counts : public StackObj { Final_Reshape_Counts() : _call_count(0), _float_count(0), _double_count(0), - _java_call_count(0), _inner_loop_count(0), - _visited( Thread::current()->resource_area() ) { } + _java_call_count(0), _inner_loop_count(0) { } void inc_call_count () { _call_count ++; } void inc_float_count () { _float_count ++; } @@ -3933,8 +3934,7 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f // Replacing Opaque nodes with their input in final_graph_reshaping_impl(), // requires that the walk visits a node's inputs before visiting the node. void Compile::final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &frc ) { - ResourceArea *area = Thread::current()->resource_area(); - Unique_Node_List sfpt(area); + Unique_Node_List sfpt; frc._visited.set(root->_idx); // first, mark node as visited uint cnt = root->req(); @@ -4296,14 +4296,13 @@ bool Compile::needs_clinit_barrier(ciInstanceKlass* holder, ciMethod* accessing_ // between Use-Def edges and Def-Use edges in the graph. void Compile::verify_graph_edges(bool no_dead_code) { if (VerifyGraphEdges) { - ResourceArea *area = Thread::current()->resource_area(); - Unique_Node_List visited(area); + Unique_Node_List visited; // Call recursive graph walk to check edges _root->verify_edges(visited); if (no_dead_code) { // Now make sure that no visited node is used by an unvisited node. bool dead_nodes = false; - Unique_Node_List checked(area); + Unique_Node_List checked; while (visited.size() > 0) { Node* n = visited.pop(); checked.push(n); diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 3d2085a3c55..4b17dfdadf3 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -332,7 +332,8 @@ class Compile : public Phase { VectorSet _dead_node_list; // Set of dead nodes uint _dead_node_count; // Number of dead nodes; VectorSet::Size() is O(N). // So use this to keep count and make the call O(1). - DEBUG_ONLY( Unique_Node_List* _modified_nodes; ) // List of nodes which inputs were modified + DEBUG_ONLY(Unique_Node_List* _modified_nodes;) // List of nodes which inputs were modified + DEBUG_ONLY(bool _phase_optimize_finished;) // Used for live node verification while creating new nodes debug_only(static int _debug_idx;) // Monotonic counter (not reset), use -XX:BreakAtNode= Arena _node_arena; // Arena for new-space Nodes @@ -803,6 +804,8 @@ class Compile : public Phase { return (uint) val; } #ifdef ASSERT + void set_phase_optimize_finished() { _phase_optimize_finished = true; } + bool phase_optimize_finished() const { return _phase_optimize_finished; } uint count_live_nodes_by_graph_walk(); void print_missing_nodes(); #endif diff --git a/src/hotspot/share/opto/domgraph.cpp b/src/hotspot/share/opto/domgraph.cpp index 7af4d07264f..03b0c52ab55 100644 --- a/src/hotspot/share/opto/domgraph.cpp +++ b/src/hotspot/share/opto/domgraph.cpp @@ -404,7 +404,7 @@ void PhaseIdealLoop::Dominators() { // Tarjan's algorithm, almost verbatim: // Step 1: - VectorSet visited(Thread::current()->resource_area()); + VectorSet visited; int dfsnum = NTarjan::DFS( ntarjan, visited, this, dfsorder); // Tarjan is using 1-based arrays, so these are some initialize flags diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index ab9729d4286..29a39ee9687 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -2988,8 +2988,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, GrowableArray orig_phis; PhaseIterGVN *igvn = _igvn; uint new_index_start = (uint) _compile->num_alias_types(); - Arena* arena = Thread::current()->resource_area(); - VectorSet visited(arena); + VectorSet visited; ideal_nodes.clear(); // Reset for use with set_map/get_map. uint unique_old = _compile->unique(); diff --git a/src/hotspot/share/opto/gcm.cpp b/src/hotspot/share/opto/gcm.cpp index 15ba69e8377..f6109adfdf3 100644 --- a/src/hotspot/share/opto/gcm.cpp +++ b/src/hotspot/share/opto/gcm.cpp @@ -1396,15 +1396,14 @@ void PhaseCFG::global_code_motion() { } // Set the basic block for Nodes pinned into blocks - Arena* arena = Thread::current()->resource_area(); - VectorSet visited(arena); + VectorSet visited; schedule_pinned_nodes(visited); // Find the earliest Block any instruction can be placed in. Some // instructions are pinned into Blocks. Unpinned instructions can // appear in last block in which all their inputs occur. visited.clear(); - Node_Stack stack(arena, (C->live_nodes() >> 2) + 16); // pre-grow + Node_Stack stack((C->live_nodes() >> 2) + 16); // pre-grow if (!schedule_early(visited, stack)) { // Bailout without retry C->record_method_not_compilable("early schedule failed"); diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index eef11f82f7e..c7f1a17aa8c 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -589,7 +589,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set) { - VectorSet visited(Thread::current()->resource_area()); + VectorSet visited; GrowableArray nodeStack(Thread::current()->resource_area(), 0, 0, NULL); nodeStack.push(start); visited.test_set(start->_idx); @@ -646,7 +646,7 @@ void IdealGraphPrinter::print(const char *name, Node *node) { print_attr(GRAPH_NAME_PROPERTY, (const char *)name); end_head(); - VectorSet temp_set(Thread::current()->resource_area()); + VectorSet temp_set; head(NODES_ELEMENT); walk_nodes(node, false, &temp_set); diff --git a/src/hotspot/share/opto/lcm.cpp b/src/hotspot/share/opto/lcm.cpp index 127237f8e37..e9956ec4ace 100644 --- a/src/hotspot/share/opto/lcm.cpp +++ b/src/hotspot/share/opto/lcm.cpp @@ -153,7 +153,6 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo // Search the successor block for a load or store who's base value is also // the tested value. There may be several. - Node_List *out = new Node_List(Thread::current()->resource_area()); MachNode *best = NULL; // Best found so far for (DUIterator i = val->outs(); val->has_out(i); i++) { Node *m = val->out(i); @@ -1256,7 +1255,7 @@ Node* PhaseCFG::catch_cleanup_find_cloned_def(Block *use_blk, Node *def, Block * if( j == def_blk->_num_succs ) { // Block at same level in dom-tree is not a successor. It needs a // PhiNode, the PhiNode uses from the def and IT's uses need fixup. - Node_Array inputs = new Node_List(Thread::current()->resource_area()); + Node_Array inputs = new Node_List(); for(uint k = 1; k < use_blk->num_preds(); k++) { Block* block = get_block_for_node(use_blk->pred(k)); inputs.map(k, catch_cleanup_find_cloned_def(block, def, def_blk, n_clone_idx)); @@ -1367,7 +1366,7 @@ void PhaseCFG::call_catch_cleanup(Block* block) { uint n_clone_idx = i2-beg+1; // Index of clone of n in each successor block Node *n = block->get_node(i2); // Node that got cloned // Need DU safe iterator because of edge manipulation in calls. - Unique_Node_List *out = new Unique_Node_List(Thread::current()->resource_area()); + Unique_Node_List* out = new Unique_Node_List(); for (DUIterator_Fast j1max, j1 = n->fast_outs(j1max); j1 < j1max; j1++) { out->push(n->fast_out(j1)); } diff --git a/src/hotspot/share/opto/live.cpp b/src/hotspot/share/opto/live.cpp index 9843f2c72c7..076de5b52ce 100644 --- a/src/hotspot/share/opto/live.cpp +++ b/src/hotspot/share/opto/live.cpp @@ -89,7 +89,7 @@ void PhaseLive::compute(uint maxlrg) { _free_IndexSet = NULL; // Blocks having done pass-1 - VectorSet first_pass(Thread::current()->resource_area()); + VectorSet first_pass; // Outer loop: must compute local live-in sets and push into predecessors. for (uint j = _cfg.number_of_blocks(); j > 0; j--) { diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index b85347ed5c3..c15c278231c 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -1337,17 +1337,17 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { ConNode* zero = _igvn.intcon(0); set_ctrl(zero, C->root()); - ResourceArea *area = Thread::current()->resource_area(); + ResourceArea* area = Thread::current()->resource_area(); Invariance invar(area, loop); // Create list of if-projs such that a newer proj dominates all older // projs in the list, and they all dominate loop->tail() - Node_List if_proj_list(area); - Node_List regions(area); - Node *current_proj = loop->tail(); //start from tail + Node_List if_proj_list; + Node_List regions; + Node* current_proj = loop->tail(); // start from tail - Node_List controls(area); + Node_List controls; while (current_proj != head) { if (loop == get_loop(current_proj) && // still in the loop ? current_proj->is_Proj() && // is a projection ? @@ -1416,7 +1416,7 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { // And look into all branches Node_Stack stack(0); - VectorSet seen(Thread::current()->resource_area()); + VectorSet seen; Node_List if_proj_list_freq(area); while (regions.size() > 0) { Node* c = regions.pop(); diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index aa039f1d1dd..19af0c9e8b5 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1463,9 +1463,8 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n outer_main_head->set_req(LoopNode::EntryControl, min_taken); set_idom(outer_main_head, min_taken, dd_main_head); - Arena *a = Thread::current()->resource_area(); - VectorSet visited(a); - Node_Stack clones(a, main_head->back_control()->outcnt()); + VectorSet visited; + Node_Stack clones(main_head->back_control()->outcnt()); // Step B3: Make the fall-in values to the main-loop come from the // fall-out values of the pre-loop. for (DUIterator_Fast i2max, i2 = main_head->fast_outs(i2max); i2 < i2max; i2++) { @@ -1751,9 +1750,8 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree *loop, Node_List &old_new, post_head->set_req(LoopNode::EntryControl, zer_taken); set_idom(post_head, zer_taken, dd_main_exit); - Arena *a = Thread::current()->resource_area(); - VectorSet visited(a); - Node_Stack clones(a, main_head->back_control()->outcnt()); + VectorSet visited; + Node_Stack clones(main_head->back_control()->outcnt()); // Step A3: Make the fall-in values to the post-loop come from the // fall-out values of the main-loop. for (DUIterator_Fast imax, i = main_head->fast_outs(imax); i < imax; i++) { @@ -1848,10 +1846,9 @@ void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adj } if (C->do_vector_loop() && (PrintOpto && (VerifyLoopOptimizations || TraceLoopOpts))) { - Arena* arena = Thread::current()->resource_area(); - Node_Stack stack(arena, C->live_nodes() >> 2); + Node_Stack stack(C->live_nodes() >> 2); Node_List rpo_list; - VectorSet visited(arena); + VectorSet visited; visited.set(loop_head->_idx); rpo(loop_head, stack, visited, rpo_list); dump(loop, rpo_list.size(), rpo_list); @@ -3598,7 +3595,7 @@ bool PhaseIdealLoop::match_fill_loop(IdealLoopTree* lpt, Node*& store, Node*& st } // No make sure all the other nodes in the loop can be handled - VectorSet ok(Thread::current()->resource_area()); + VectorSet ok; // store related values are ok ok.set(store->_idx); @@ -3642,10 +3639,21 @@ bool PhaseIdealLoop::match_fill_loop(IdealLoopTree* lpt, Node*& store, Node*& st for (SimpleDUIterator iter(n); iter.has_next(); iter.next()) { Node* use = iter.get(); if (!lpt->_body.contains(use)) { - msg = "node is used outside loop"; - // lpt->_body.dump(); - msg_node = n; - break; + if (n->is_CountedLoop() && n->as_CountedLoop()->is_strip_mined()) { + // In strip-mined counted loops, the CountedLoopNode may be + // used by the address polling node of the outer safepoint. + // Skip this use because it's safe. +#ifdef ASSERT + Node* sfpt = n->as_CountedLoop()->outer_safepoint(); + Node* polladr = sfpt->in(TypeFunc::Parms+0); + assert(use == polladr, "the use should be a safepoint polling"); +#endif + continue; + } else { + msg = "node is used outside loop"; + msg_node = n; + break; + } } } } diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 3be93ec8073..2ae128d2c1b 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -2942,8 +2942,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { _created_loop_node = false; - Arena *a = Thread::current()->resource_area(); - VectorSet visited(a); + VectorSet visited; // Pre-grow the mapping from Nodes to IdealLoopTrees. _nodes.map(C->unique(), NULL); memset(_nodes.adr(), 0, wordSize * C->unique()); @@ -3044,7 +3043,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { // Given dominators, try to find inner loops with calls that must // always be executed (call dominates loop tail). These loops do // not need a separate safepoint. - Node_List cisstack(a); + Node_List cisstack; _ltree_root->check_safepts(visited, cisstack); } @@ -3055,10 +3054,10 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { // Allocate stack with enough space to avoid frequent realloc int stack_size = (C->live_nodes() >> 1) + 16; // (live_nodes>>1)+16 from Java2D stats - Node_Stack nstack( a, stack_size ); + Node_Stack nstack(stack_size); visited.clear(); - Node_List worklist(a); + Node_List worklist; // Don't need C->root() on worklist since // it will be processed among C->top() inputs worklist.push(C->top()); @@ -3327,12 +3326,12 @@ static int fail; // debug only, so its multi-thread dont care void PhaseIdealLoop::verify() const { int old_progress = C->major_progress(); ResourceMark rm; - PhaseIdealLoop loop_verify( _igvn, this ); - VectorSet visited(Thread::current()->resource_area()); + PhaseIdealLoop loop_verify(_igvn, this); + VectorSet visited; fail = 0; - verify_compare( C->root(), &loop_verify, visited ); - assert( fail == 0, "verify loops failed" ); + verify_compare(C->root(), &loop_verify, visited); + assert(fail == 0, "verify loops failed"); // Verify loop structure is the same _ltree_root->verify_tree(loop_verify._ltree_root, NULL); // Reset major-progress. It was cleared by creating a verify version of @@ -4681,10 +4680,9 @@ void PhaseIdealLoop::dump_bad_graph(const char* msg, Node* n, Node* early, Node* //------------------------------dump------------------------------------------- void PhaseIdealLoop::dump() const { ResourceMark rm; - Arena* arena = Thread::current()->resource_area(); - Node_Stack stack(arena, C->live_nodes() >> 2); + Node_Stack stack(C->live_nodes() >> 2); Node_List rpo_list; - VectorSet visited(arena); + VectorSet visited; visited.set(C->top()->_idx); rpo(C->root(), stack, visited, rpo_list); // Dump root loop indexed by last element in PO order diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index c1a092fc8ff..14a88fbbcbe 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -488,6 +488,7 @@ class IdealLoopTree : public ResourceObj { Node *_head; // Head of loop Node *_tail; // Tail of loop inline Node *tail(); // Handle lazy update of _tail field + inline Node *head(); // Handle lazy update of _head field PhaseIdealLoop* _phase; int _local_loop_unroll_limit; int _local_loop_unroll_factor; @@ -1409,14 +1410,17 @@ class PhaseIdealLoop : public PhaseTransform { void require_nodes_final(uint live_at_begin, bool check_estimate) { assert(_nodes_required < UINT_MAX, "Bad state (final)."); +#ifdef ASSERT if (check_estimate) { - // Assert that the node budget request was not off by too much (x2). + // Check that the node budget request was not off by too much (x2). // Should this be the case we _surely_ need to improve the estimates // used in our budget calculations. - assert(C->live_nodes() - live_at_begin <= 2 * _nodes_required, - "Bad node estimate: actual = %d >> request = %d", - C->live_nodes() - live_at_begin, _nodes_required); + if (C->live_nodes() - live_at_begin > 2 * _nodes_required) { + log_info(compilation)("Bad node estimate: actual = %d >> request = %d", + C->live_nodes() - live_at_begin, _nodes_required); + } } +#endif // Assert that we have stayed within the node budget limit. assert(C->live_nodes() < C->max_node_limit(), "Exceeding node budget limit: %d + %d > %d (request = %d)", @@ -1580,6 +1584,13 @@ inline Node* IdealLoopTree::tail() { return _tail; } +inline Node* IdealLoopTree::head() { + // Handle lazy update of _head field. + if (_head->in(0) == NULL) { + _head = _phase->get_ctrl(_head); + } + return _head; +} // Iterate over the loop tree using a preorder, left-to-right traversal. // diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index c7a5a046397..32bfa05f545 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1855,22 +1855,19 @@ void PhaseIdealLoop::clone_loop_handle_data_uses(Node* old, Node_List &old_new, // Since this code is highly unlikely, we lazily build the worklist // of such Nodes to go split. if (!split_if_set) { - ResourceArea *area = Thread::current()->resource_area(); - split_if_set = new Node_List(area); + split_if_set = new Node_List(); } split_if_set->push(use); } if (use->is_Bool()) { if (!split_bool_set) { - ResourceArea *area = Thread::current()->resource_area(); - split_bool_set = new Node_List(area); + split_bool_set = new Node_List(); } split_bool_set->push(use); } if (use->Opcode() == Op_CreateEx) { if (!split_cex_set) { - ResourceArea *area = Thread::current()->resource_area(); - split_cex_set = new Node_List(area); + split_cex_set = new Node_List(); } split_cex_set->push(use); } @@ -2203,8 +2200,7 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd _igvn.hash_find_insert(nnn); } - ResourceArea *area = Thread::current()->resource_area(); - Node_List extra_data_nodes(area); // data nodes in the outer strip mined loop + Node_List extra_data_nodes; // data nodes in the outer strip mined loop clone_outer_loop(head, mode, loop, outer_loop, dd, old_new, extra_data_nodes); // Step 3: Now fix control uses. Loop varying control uses have already @@ -2212,7 +2208,7 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd // control uses must be either an IfFalse or an IfTrue. Make a merge // point to merge the old and new IfFalse/IfTrue nodes; make the use // refer to this. - Node_List worklist(area); + Node_List worklist; uint new_counter = C->unique(); for( i = 0; i < loop->_body.size(); i++ ) { Node* old = loop->_body.at(i); @@ -2693,9 +2689,8 @@ void PhaseIdealLoop::remove_cmpi_loop_exit(IfNode* if_cmp, IdealLoopTree *loop) void PhaseIdealLoop::scheduled_nodelist( IdealLoopTree *loop, VectorSet& member, Node_List &sched ) { assert(member.test(loop->_head->_idx), "loop head must be in member set"); - Arena *a = Thread::current()->resource_area(); - VectorSet visited(a); - Node_Stack nstack(a, loop->_body.size()); + VectorSet visited; + Node_Stack nstack(loop->_body.size()); Node* n = loop->_head; // top of stack is cached in "n" uint idx = 0; @@ -3271,12 +3266,11 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) { } } #endif - ResourceArea *area = Thread::current()->resource_area(); - VectorSet peel(area); - VectorSet not_peel(area); - Node_List peel_list(area); - Node_List worklist(area); - Node_List sink_list(area); + VectorSet peel; + VectorSet not_peel; + Node_List peel_list; + Node_List worklist; + Node_List sink_list; uint estimate = loop->est_loop_clone_sz(1); if (exceeding_node_budget(estimate)) { @@ -3543,7 +3537,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) { #ifndef PRODUCT if (TracePartialPeeling) { tty->print_cr("\nafter partial peel one iteration"); - Node_List wl(area); + Node_List wl; Node* t = last_peel; while (true) { wl.push(t); diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index 5133ba998ba..6fee45f0651 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -502,8 +502,7 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, Node *sfpt_ctl, BasicType int offset = adr_t->flattened_offset(); Node *start_mem = C->start()->proj_out_or_null(TypeFunc::Memory); Node *alloc_mem = alloc->in(TypeFunc::Memory); - Arena *a = Thread::current()->resource_area(); - VectorSet visited(a); + VectorSet visited; bool done = sfpt_mem == alloc_mem; Node *mem = sfpt_mem; @@ -572,8 +571,8 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, Node *sfpt_ctl, BasicType return n; } else if (mem->is_Phi()) { // attempt to produce a Phi reflecting the values on the input paths of the Phi - Node_Stack value_phis(a, 8); - Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, ValueSearchLimit); + Node_Stack value_phis(8); + Node* phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, ValueSearchLimit); if (phi != NULL) { return phi; } else { diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 97e4e808f44..31ada10441e 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -153,7 +153,7 @@ void Matcher::verify_new_nodes_only(Node* xroot) { // Make sure that the new graph only references new nodes ResourceMark rm; Unique_Node_List worklist; - VectorSet visited(Thread::current()->resource_area()); + VectorSet visited; worklist.push(xroot); while (worklist.size() > 0) { Node* n = worklist.pop(); @@ -2026,7 +2026,7 @@ void Matcher::find_shared(Node* n) { // Allocate stack of size C->live_nodes() * 2 to avoid frequent realloc MStack mstack(C->live_nodes() * 2); // Mark nodes as address_visited if they are inputs to an address expression - VectorSet address_visited(Thread::current()->resource_area()); + VectorSet address_visited; mstack.push(n, Visit); // Don't need to pre-visit root node while (mstack.is_nonempty()) { n = mstack.node(); // Leave node on stack diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 277074df9c2..7cf9e1e6576 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -462,9 +462,8 @@ bool MemNode::all_controls_dominate(Node* dom, Node* sub) { // Check all control edges of 'dom'. ResourceMark rm; - Arena* arena = Thread::current()->resource_area(); - Node_List nlist(arena); - Unique_Node_List dom_list(arena); + Node_List nlist; + Unique_Node_List dom_list; dom_list.push(dom); bool only_dominating_controls = false; @@ -2267,7 +2266,6 @@ const Type* LoadNode::klass_value_common(PhaseGVN* phase) const { // See if we can become precise: no subklasses and no interface // (Note: We need to support verified interfaces.) if (!ik->is_interface() && !ik->has_subklass()) { - //assert(!UseExactTypes, "this code should be useless with exact types"); // Add a dependence; if any subclass added we need to recompile if (!ik->is_final()) { // %%% should use stronger assert_unique_concrete_subtype instead @@ -2301,7 +2299,6 @@ const Type* LoadNode::klass_value_common(PhaseGVN* phase) const { ciInstanceKlass *ik = base_k->as_instance_klass(); // See if we can become precise: no subklasses and no interface if (!ik->is_interface() && !ik->has_subklass()) { - //assert(!UseExactTypes, "this code should be useless with exact types"); // Add a dependence; if any subclass added we need to recompile if (!ik->is_final()) { phase->C->dependencies()->assert_leaf_type(ik); @@ -3360,7 +3357,7 @@ void MemBarNode::set_load_store_pair(MemBarNode* leading, MemBarNode* trailing) MemBarNode* MemBarNode::trailing_membar() const { ResourceMark rm; Node* trailing = (Node*)this; - VectorSet seen(Thread::current()->resource_area()); + VectorSet seen; Node_Stack multis(0); do { Node* c = trailing; @@ -3404,7 +3401,7 @@ MemBarNode* MemBarNode::trailing_membar() const { MemBarNode* MemBarNode::leading_membar() const { ResourceMark rm; - VectorSet seen(Thread::current()->resource_area()); + VectorSet seen; Node_Stack regions(0); Node* leading = in(0); while (leading != NULL && (!leading->is_MemBar() || !leading->as_MemBar()->leading())) { diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index e5532d0c2b2..c10cb236f19 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -67,21 +67,27 @@ extern int nodes_created; void Node::verify_construction() { _debug_orig = NULL; int old_debug_idx = Compile::debug_idx(); - int new_debug_idx = old_debug_idx+1; + int new_debug_idx = old_debug_idx + 1; if (new_debug_idx > 0) { // Arrange that the lowest five decimal digits of _debug_idx // will repeat those of _idx. In case this is somehow pathological, // we continue to assign negative numbers (!) consecutively. const int mod = 100000; int bump = (int)(_idx - new_debug_idx) % mod; - if (bump < 0) bump += mod; + if (bump < 0) { + bump += mod; + } assert(bump >= 0 && bump < mod, ""); new_debug_idx += bump; } Compile::set_debug_idx(new_debug_idx); - set_debug_idx( new_debug_idx ); - assert(Compile::current()->unique() < (INT_MAX - 1), "Node limit exceeded INT_MAX"); - assert(Compile::current()->live_nodes() < Compile::current()->max_node_limit(), "Live Node limit exceeded limit"); + set_debug_idx(new_debug_idx); + Compile* C = Compile::current(); + assert(C->unique() < (INT_MAX - 1), "Node limit exceeded INT_MAX"); + if (!C->phase_optimize_finished()) { + // Only check assert during parsing and optimization phase. Skip it while generating code. + assert(C->live_nodes() <= C->max_node_limit(), "Live Node limit exceeded limit"); + } if (BreakAtNode != 0 && (_debug_idx == BreakAtNode || (int)_idx == BreakAtNode)) { tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx); BREAKPOINT; @@ -1334,7 +1340,7 @@ static void kill_dead_code( Node *dead, PhaseIterGVN *igvn ) { if( dead->is_Con() ) return; ResourceMark rm; - Node_List nstack(Thread::current()->resource_area()); + Node_List nstack; Node *top = igvn->C->top(); nstack.push(dead); @@ -1610,20 +1616,18 @@ Node* find_node(int idx) { //------------------------------find------------------------------------------- Node* Node::find(int idx) const { - ResourceArea *area = Thread::current()->resource_area(); - VectorSet old_space(area), new_space(area); + VectorSet old_space, new_space; Node* result = NULL; - find_recur(Compile::current(), result, (Node*) this, idx, false, &old_space, &new_space ); + find_recur(Compile::current(), result, (Node*) this, idx, false, &old_space, &new_space); return result; } //------------------------------find_ctrl-------------------------------------- // Find an ancestor to this node in the control history with given _idx Node* Node::find_ctrl(int idx) const { - ResourceArea *area = Thread::current()->resource_area(); - VectorSet old_space(area), new_space(area); + VectorSet old_space, new_space; Node* result = NULL; - find_recur(Compile::current(), result, (Node*) this, idx, true, &old_space, &new_space ); + find_recur(Compile::current(), result, (Node*)this, idx, true, &old_space, &new_space); return result; } #endif @@ -2167,10 +2171,9 @@ void Node::verify_edges(Unique_Node_List &visited) { void Node::verify(Node* n, int verify_depth) { assert(verify_depth != 0, "depth should not be 0"); ResourceMark rm; - ResourceArea* area = Thread::current()->resource_area(); - VectorSet old_space(area); - VectorSet new_space(area); - Node_List worklist(area); + VectorSet old_space; + VectorSet new_space; + Node_List worklist; worklist.push(n); Compile* C = Compile::current(); uint last_index_on_current_depth = 0; @@ -2239,7 +2242,7 @@ void Node::verify(Node* n, int verify_depth) { //------------------------------walk------------------------------------------- // Graph walk, with both pre-order and post-order functions void Node::walk(NFunc pre, NFunc post, void *env) { - VectorSet visited(Thread::current()->resource_area()); // Setup for local walk + VectorSet visited; // Setup for local walk walk_(pre, post, env, visited); } diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index b413c036829..228affa97de 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1535,7 +1535,7 @@ class Unique_Node_List : public Node_List { VectorSet _in_worklist; uint _clock_index; // Index in list where to pop from next public: - Unique_Node_List() : Node_List(), _in_worklist(Thread::current()->resource_area()), _clock_index(0) {} + Unique_Node_List() : Node_List(), _clock_index(0) {} Unique_Node_List(Arena *a) : Node_List(a), _in_worklist(a), _clock_index(0) {} void remove( Node *n ); diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index ef6ced4acc8..1740f5f8303 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -401,8 +401,7 @@ void NodeHash::operator=(const NodeHash& nh) { //============================================================================= //------------------------------PhaseRemoveUseless----------------------------- // 1) Use a breadthfirst walk to collect useful nodes reachable from root. -PhaseRemoveUseless::PhaseRemoveUseless(PhaseGVN *gvn, Unique_Node_List *worklist, PhaseNumber phase_num) : Phase(phase_num), - _useful(Thread::current()->resource_area()) { +PhaseRemoveUseless::PhaseRemoveUseless(PhaseGVN* gvn, Unique_Node_List* worklist, PhaseNumber phase_num) : Phase(phase_num) { // Implementation requires 'UseLoopSafepoints == true' and an edge from root // to each SafePointNode at a backward branch. Inserted in add_safepoint(). @@ -456,7 +455,6 @@ PhaseRenumberLive::PhaseRenumberLive(PhaseGVN* gvn, PhaseRemoveUseless(gvn, worklist, Remove_Useless_And_Renumber_Live), _new_type_array(C->comp_arena()), _old2new_map(C->unique(), C->unique(), -1), - _delayed(Thread::current()->resource_area()), _is_pass_finished(false), _live_node_count(C->live_nodes()) { @@ -662,9 +660,9 @@ void PhaseTransform::dump_types( ) const { } //------------------------------dump_nodes_and_types--------------------------- -void PhaseTransform::dump_nodes_and_types(const Node *root, uint depth, bool only_ctrl) { - VectorSet visited(Thread::current()->resource_area()); - dump_nodes_and_types_recur( root, depth, only_ctrl, visited ); +void PhaseTransform::dump_nodes_and_types(const Node* root, uint depth, bool only_ctrl) { + VectorSet visited; + dump_nodes_and_types_recur(root, depth, only_ctrl, visited); } //------------------------------dump_nodes_and_types_recur--------------------- diff --git a/src/hotspot/share/opto/regalloc.cpp b/src/hotspot/share/opto/regalloc.cpp index f9726140fe2..df5071635c7 100644 --- a/src/hotspot/share/opto/regalloc.cpp +++ b/src/hotspot/share/opto/regalloc.cpp @@ -40,7 +40,6 @@ PhaseRegAlloc::PhaseRegAlloc( uint unique, PhaseCFG &cfg, Phase(Register_Allocation), _node_regs(0), _node_regs_max_index(0), - _node_oops(Thread::current()->resource_area()), _cfg(cfg), _framesize(0xdeadbeef), _matcher(matcher) diff --git a/src/hotspot/share/opto/stringopts.cpp b/src/hotspot/share/opto/stringopts.cpp index bc270a6baf4..084818e833e 100644 --- a/src/hotspot/share/opto/stringopts.cpp +++ b/src/hotspot/share/opto/stringopts.cpp @@ -584,8 +584,7 @@ StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) { PhaseStringOpts::PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List*): Phase(StringOpts), - _gvn(gvn), - _visited(Thread::current()->resource_area()) { + _gvn(gvn) { assert(OptimizeStringConcat, "shouldn't be here"); diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 4e97b03a13a..004bf06a5e8 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1446,6 +1446,34 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { return new BoolNode( cmp, _test.commute() ); } + // Change "bool eq/ne (cmp (and X 16) 16)" into "bool ne/eq (cmp (and X 16) 0)". + if (cop == Op_CmpI && + (_test._test == BoolTest::eq || _test._test == BoolTest::ne) && + cmp1->Opcode() == Op_AndI && cmp2->Opcode() == Op_ConI && + cmp1->in(2)->Opcode() == Op_ConI) { + const TypeInt *t12 = phase->type(cmp2)->isa_int(); + const TypeInt *t112 = phase->type(cmp1->in(2))->isa_int(); + if (t12 && t12->is_con() && t112 && t112->is_con() && + t12->get_con() == t112->get_con() && is_power_of_2(t12->get_con())) { + Node *ncmp = phase->transform(new CmpINode(cmp1, phase->intcon(0))); + return new BoolNode(ncmp, _test.negate()); + } + } + + // Same for long type: change "bool eq/ne (cmp (and X 16) 16)" into "bool ne/eq (cmp (and X 16) 0)". + if (cop == Op_CmpL && + (_test._test == BoolTest::eq || _test._test == BoolTest::ne) && + cmp1->Opcode() == Op_AndL && cmp2->Opcode() == Op_ConL && + cmp1->in(2)->Opcode() == Op_ConL) { + const TypeLong *t12 = phase->type(cmp2)->isa_long(); + const TypeLong *t112 = phase->type(cmp1->in(2))->isa_long(); + if (t12 && t12->is_con() && t112 && t112->is_con() && + t12->get_con() == t112->get_con() && is_power_of_2(t12->get_con())) { + Node *ncmp = phase->transform(new CmpLNode(cmp1, phase->longcon(0))); + return new BoolNode(ncmp, _test.negate()); + } + } + // Change "bool eq/ne (cmp (xor X 1) 0)" into "bool ne/eq (cmp X 0)". // The XOR-1 is an idiom used to flip the sense of a bool. We flip the // test instead. diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index fa782418106..91401d51da1 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -2364,7 +2364,6 @@ bool TypeAry::empty(void) const { //--------------------------ary_must_be_exact---------------------------------- bool TypeAry::ary_must_be_exact() const { - if (!UseExactTypes) return false; // This logic looks at the element type of an array, and returns true // if the element type is either a primitive or a final instance class. // In such cases, an array built on this ary must have no subclasses. @@ -3455,13 +3454,11 @@ const TypeOopPtr* TypeOopPtr::make_from_klass_common(ciKlass *klass, bool klass_ klass_is_exact = sub->is_final(); } } - if (!klass_is_exact && try_for_exact - && deps != NULL && UseExactTypes) { - if (!ik->is_interface() && !ik->has_subklass()) { - // Add a dependence; if concrete subclass added we need to recompile - deps->assert_leaf_type(ik); - klass_is_exact = true; - } + if (!klass_is_exact && try_for_exact && deps != NULL && + !ik->is_interface() && !ik->has_subklass()) { + // Add a dependence; if concrete subclass added we need to recompile + deps->assert_leaf_type(ik); + klass_is_exact = true; } } return TypeInstPtr::make(TypePtr::BotPTR, klass, klass_is_exact, NULL, Offset(0), klass->flatten_array()); @@ -3805,8 +3802,7 @@ const TypeInstPtr *TypeInstPtr::make(PTR ptr, // Ptr is never Null assert( ptr != Null, "NULL pointers are not typed" ); - assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); - if (!UseExactTypes) xk = false; + assert(instance_id <= 0 || xk, "instances are always exactly typed"); if (ptr == Constant) { // Note: This case includes meta-object constants, such as methods. xk = true; @@ -3858,7 +3854,6 @@ const Type *TypeInstPtr::cast_to_ptr_type(PTR ptr) const { //-----------------------------cast_to_exactness------------------------------- const Type *TypeInstPtr::cast_to_exactness(bool klass_is_exact) const { if( klass_is_exact == _klass_is_exact ) return this; - if (!UseExactTypes) return this; if (!_klass->is_loaded()) return this; ciInstanceKlass* ik = _klass->as_instance_klass(); if( (ik->is_final() || _const_oop) ) return this; // cannot clear xk @@ -4409,9 +4404,8 @@ const TypeAryPtr* TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool int instance_id, const TypePtr* speculative, int inline_depth) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); - if (!xk) xk = ary->ary_must_be_exact(); - assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); - if (!UseExactTypes) xk = (ptr == Constant); + if (!xk) xk = ary->ary_must_be_exact(); + assert(instance_id <= 0 || xk, "instances are always exactly typed"); return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, field_offset, instance_id, false, speculative, inline_depth))->hashcons(); } @@ -4423,8 +4417,7 @@ const TypeAryPtr* TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciK "integral arrays must be pre-equipped with a class"); assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" ); if (!xk) xk = (o != NULL) || ary->ary_must_be_exact(); - assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); - if (!UseExactTypes) xk = (ptr == Constant); + assert(instance_id <= 0 || xk, "instances are always exactly typed"); return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, field_offset, instance_id, is_autobox_cache, speculative, inline_depth))->hashcons(); } @@ -4438,7 +4431,6 @@ const Type *TypeAryPtr::cast_to_ptr_type(PTR ptr) const { //-----------------------------cast_to_exactness------------------------------- const Type *TypeAryPtr::cast_to_exactness(bool klass_is_exact) const { if( klass_is_exact == _klass_is_exact ) return this; - if (!UseExactTypes) return this; if (_ary->ary_must_be_exact()) return this; // cannot clear xk const TypeAry* new_ary = _ary; @@ -5516,7 +5508,6 @@ const Type *TypeKlassPtr::cast_to_ptr_type(PTR ptr) const { //-----------------------------cast_to_exactness------------------------------- const Type *TypeKlassPtr::cast_to_exactness(bool klass_is_exact) const { if( klass_is_exact == _klass_is_exact ) return this; - if (!UseExactTypes) return this; return make(klass_is_exact ? Constant : NotNull, _klass, _offset, _flat_array); } diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 2dc4a95e179..4aa584491cf 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -494,11 +494,6 @@ JVM_END JVM_ENTRY_NO_ENV(void, JVM_GC(void)) JVMWrapper("JVM_GC"); if (!DisableExplicitGC) { - if (AsyncDeflateIdleMonitors) { - // AsyncDeflateIdleMonitors needs to know when System.gc() is - // called so any special deflation can be done at a safepoint. - ObjectSynchronizer::set_is_special_deflation_requested(true); - } Universe::heap()->collect(GCCause::_java_lang_system_gc); } JVM_END diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index bebfa49ffa0..895512351f6 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -1213,8 +1213,8 @@ JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count } else { // get owned monitors info with handshake GetOwnedMonitorInfoClosure op(calling_thread, this, owned_monitors_list); - Handshake::execute_direct(&op, java_thread); - err = op.result(); + bool executed = Handshake::execute_direct(&op, java_thread); + err = executed ? op.result() : JVMTI_ERROR_THREAD_NOT_ALIVE; } jint owned_monitor_count = owned_monitors_list->length(); if (err == JVMTI_ERROR_NONE) { @@ -1258,8 +1258,8 @@ JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_i } else { // get owned monitors info with handshake GetOwnedMonitorInfoClosure op(calling_thread, this, owned_monitors_list); - Handshake::execute_direct(&op, java_thread); - err = op.result(); + bool executed = Handshake::execute_direct(&op, java_thread); + err = executed ? op.result() : JVMTI_ERROR_THREAD_NOT_ALIVE; } jint owned_monitor_count = owned_monitors_list->length(); @@ -1302,8 +1302,8 @@ JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_p } else { // get contended monitor information with handshake GetCurrentContendedMonitorClosure op(calling_thread, this, monitor_ptr); - Handshake::execute_direct(&op, java_thread); - err = op.result(); + bool executed = Handshake::execute_direct(&op, java_thread); + err = executed ? op.result() : JVMTI_ERROR_THREAD_NOT_ALIVE; } return err; } /* end GetCurrentContendedMonitor */ diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index 2c719ffbc4a..6ca7fdf8617 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -1512,12 +1512,24 @@ VM_SetFramePop::doit() { void GetOwnedMonitorInfoClosure::do_thread(Thread *target) { - _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, (JavaThread *)target, _owned_monitors_list); + assert(target->is_Java_thread(), "just checking"); + JavaThread *jt = (JavaThread *)target; + if (!jt->is_exiting() && (jt->threadObj() != NULL)) { + _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, + jt, + _owned_monitors_list); + } } void GetCurrentContendedMonitorClosure::do_thread(Thread *target) { - _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread, (JavaThread *)target, _owned_monitor_ptr); + assert(target->is_Java_thread(), "just checking"); + JavaThread *jt = (JavaThread *)target; + if (!jt->is_exiting() && (jt->threadObj() != NULL)) { + _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread, + jt, + _owned_monitor_ptr); + } } void diff --git a/src/hotspot/share/prims/jvmtiEnvBase.hpp b/src/hotspot/share/prims/jvmtiEnvBase.hpp index 1b8dd64aca0..36c684d31ce 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.hpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.hpp @@ -387,7 +387,7 @@ class GetOwnedMonitorInfoClosure : public HandshakeClosure { : HandshakeClosure("GetOwnedMonitorInfo"), _calling_thread(calling_thread), _env(env), - _result(JVMTI_ERROR_NONE), + _result(JVMTI_ERROR_THREAD_NOT_ALIVE), _owned_monitors_list(owned_monitor_list) {} jvmtiError result() { return _result; } void do_thread(Thread *target); diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp index 5d49d1b192a..bb70acf3ecc 100644 --- a/src/hotspot/share/prims/unsafe.cpp +++ b/src/hotspot/share/prims/unsafe.cpp @@ -1091,6 +1091,7 @@ UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetReference(JNIEnv *env, jobject unsafe UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) { oop p = JNIHandles::resolve(obj); + GuardUnsafeAccess guard(thread); if (p == NULL) { volatile jint* addr = (volatile jint*)index_oop_from_field_offset_long(p, offset); return RawAccess<>::atomic_cmpxchg(addr, e, x) == e; @@ -1102,6 +1103,7 @@ UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobj UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) { oop p = JNIHandles::resolve(obj); + GuardUnsafeAccess guard(thread); if (p == NULL) { volatile jlong* addr = (volatile jlong*)index_oop_from_field_offset_long(p, offset); return RawAccess<>::atomic_cmpxchg(addr, e, x) == e; diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 1bd6a42dc1c..7b0f9bdad15 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -41,6 +41,7 @@ #include "gc/shared/genArguments.hpp" #include "gc/shared/genCollectedHeap.hpp" #include "jvmtifiles/jvmtiEnv.hpp" +#include "logging/log.hpp" #include "memory/filemap.hpp" #include "memory/heapShared.inline.hpp" #include "memory/metaspaceShared.hpp" @@ -480,12 +481,6 @@ WB_END WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o)) if (UseG1GC) { - if (AsyncDeflateIdleMonitors) { - // AsyncDeflateIdleMonitors needs to know when System.gc() or - // the equivalent is called so any special clean up can be done - // at a safepoint, e.g., TestHumongousClassLoader.java. - ObjectSynchronizer::set_is_special_deflation_requested(true); - } G1CollectedHeap* g1h = G1CollectedHeap::heap(); if (!g1h->concurrent_mark()->cm_thread()->during_cycle()) { g1h->collect(GCCause::_wb_conc_mark); @@ -1457,12 +1452,6 @@ WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString WB_END WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o)) - if (AsyncDeflateIdleMonitors) { - // AsyncDeflateIdleMonitors needs to know when System.gc() or - // the equivalent is called so any special clean up can be done - // at a safepoint, e.g., TestHumongousClassLoader.java. - ObjectSynchronizer::set_is_special_deflation_requested(true); - } Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(true); Universe::heap()->collect(GCCause::_wb_full_gc); #if INCLUDE_G1GC @@ -1811,14 +1800,12 @@ WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj)) return (jboolean) obj_oop->mark().has_monitor(); WB_END +WB_ENTRY(jboolean, WB_DeflateIdleMonitors(JNIEnv* env, jobject wb)) + log_info(monitorinflation)("WhiteBox initiated DeflateIdleMonitors"); + return ObjectSynchronizer::request_deflate_idle_monitors(); +WB_END + WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb)) - if (AsyncDeflateIdleMonitors) { - // AsyncDeflateIdleMonitors needs to know when System.gc() or - // the equivalent is called so any special clean up can be done - // at a safepoint, e.g., TestRTMTotalCountIncrRate.java or - // TestUseRTMForStackLocks.java. - ObjectSynchronizer::set_is_special_deflation_requested(true); - } VM_ForceSafepoint force_safepoint_op; VMThread::execute(&force_safepoint_op); WB_END @@ -2574,6 +2561,7 @@ static JNINativeMethod methods[] = { (void*)&WB_AddModuleExportsToAll }, {CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls }, {CC"assertSpecialLock", CC"(ZZ)V", (void*)&WB_AssertSpecialLock }, + {CC"deflateIdleMonitors", CC"()Z", (void*)&WB_DeflateIdleMonitors }, {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, {CC"getConstantPool0", CC"(Ljava/lang/Class;)J", (void*)&WB_GetConstantPool }, diff --git a/src/hotspot/share/runtime/javaCalls.cpp b/src/hotspot/share/runtime/javaCalls.cpp index c4ba5736235..7a53d99be17 100644 --- a/src/hotspot/share/runtime/javaCalls.cpp +++ b/src/hotspot/share/runtime/javaCalls.cpp @@ -30,6 +30,9 @@ #include "compiler/compileBroker.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/linkResolver.hpp" +#if INCLUDE_JVMCI +#include "jvmci/jvmciJavaClasses.hpp" +#endif #include "memory/universe.hpp" #include "oops/method.inline.hpp" #include "oops/oop.inline.hpp" @@ -362,27 +365,15 @@ void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaC assert(!SafepointSynchronize::is_at_safepoint(), "call to Java code during VM operation"); assert(!thread->handle_area()->no_handle_mark_active(), "cannot call out to Java here"); -#if INCLUDE_JVMCI - // Gets the nmethod (if any) that should be called instead of normal target - nmethod* alternative_target = args->alternative_target(); - if (alternative_target == NULL) { -#endif -// Verify the arguments - - if (CheckJNICalls) { + // Verify the arguments + if (JVMCI_ONLY(args->alternative_target().is_null() &&) (DEBUG_ONLY(true ||) CheckJNICalls)) { args->verify(method, result->get_type()); } - else debug_only(args->verify(method, result->get_type())); -#if INCLUDE_JVMCI - } -#else - // Ignore call if method is empty - if (method->is_empty_method()) { + if (JVMCI_ONLY(args->alternative_target().is_null() &&) method->is_empty_method()) { assert(result->get_type() == T_VOID, "an empty method must return a void value"); return; } -#endif #ifdef ASSERT { InstanceKlass* holder = method->method_holder(); @@ -430,17 +421,6 @@ void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaC os::map_stack_shadow_pages(sp); } -#if INCLUDE_JVMCI - if (alternative_target != NULL) { - if (alternative_target->is_alive() && !alternative_target->is_unloading()) { - thread->set_jvmci_alternate_call_target(alternative_target->verified_entry_point()); - entry_point = method->adapter()->get_i2c_entry(); - } else { - THROW(vmSymbols::jdk_vm_ci_code_InvalidInstalledCodeException()); - } - } -#endif - jobject value_buffer = NULL; if (InlineTypeReturnedAsFields && result->get_type() == T_INLINE_TYPE) { // Pre allocate a buffered inline type in case the result is returned @@ -461,7 +441,20 @@ void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaC // the call to call_stub, the optimizer produces wrong code. intptr_t* result_val_address = (intptr_t*)(result->get_value_addr()); intptr_t* parameter_address = args->parameters(); - +#if INCLUDE_JVMCI + // Gets the alternative target (if any) that should be called + Handle alternative_target = args->alternative_target(); + if (!alternative_target.is_null()) { + // Must extract verified entry point from HotSpotNmethod after VM to Java + // transition in JavaCallWrapper constructor so that it is safe with + // respect to nmethod sweeping. + address verified_entry_point = (address) HotSpotJVMCI::InstalledCode::entryPoint(NULL, alternative_target()); + if (verified_entry_point != NULL) { + thread->set_jvmci_alternate_call_target(verified_entry_point); + entry_point = method->adapter()->get_i2c_entry(); + } + } +#endif StubRoutines::call_stub()( (address)&link, // (intptr_t*)&(result->_value), // see NOTE above (compiler problem) diff --git a/src/hotspot/share/runtime/javaCalls.hpp b/src/hotspot/share/runtime/javaCalls.hpp index 73ecde86eb5..6a22cb23ec1 100644 --- a/src/hotspot/share/runtime/javaCalls.hpp +++ b/src/hotspot/share/runtime/javaCalls.hpp @@ -88,7 +88,10 @@ class JavaCallArguments : public StackObj { int _size; int _max_size; bool _start_at_zero; // Support late setting of receiver - JVMCI_ONLY(nmethod* _alternative_target;) // Nmethod that should be called instead of normal target +#if INCLUDE_JVMCI + Handle _alternative_target; // HotSpotNmethod wrapping an nmethod whose verified entry point + // should be called instead of the normal target +#endif void initialize() { // Starts at first element to support set_receiver. @@ -98,7 +101,6 @@ class JavaCallArguments : public StackObj { _max_size = _default_size; _size = 0; _start_at_zero = false; - JVMCI_ONLY(_alternative_target = NULL;) } // Helper for push_oop and the like. The value argument is a @@ -138,18 +140,17 @@ class JavaCallArguments : public StackObj { _max_size = max_size; _size = 0; _start_at_zero = false; - JVMCI_ONLY(_alternative_target = NULL;) } else { initialize(); } } #if INCLUDE_JVMCI - void set_alternative_target(nmethod* target) { + void set_alternative_target(Handle target) { _alternative_target = target; } - nmethod* alternative_target() { + Handle alternative_target() { return _alternative_target; } #endif diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index e45e8982768..c56e46d8355 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -151,6 +151,7 @@ Mutex* CDSClassFileStream_lock = NULL; #endif Mutex* DumpTimeTable_lock = NULL; Mutex* CDSLambda_lock = NULL; +Mutex* CDSAddSymbol_lock = NULL; #endif // INCLUDE_CDS #if INCLUDE_JVMCI @@ -344,8 +345,9 @@ void mutex_init() { #if INCLUDE_JVMTI def(CDSClassFileStream_lock , PaddedMutex , max_nonleaf, false, _safepoint_check_always); #endif - def(DumpTimeTable_lock , PaddedMutex , leaf - 1, true, _safepoint_check_never); + def(DumpTimeTable_lock , PaddedMutex , leaf - 1, true, _safepoint_check_never); def(CDSLambda_lock , PaddedMutex , leaf, true, _safepoint_check_never); + def(CDSAddSymbol_lock , PaddedMutex , leaf - 1, true, _safepoint_check_never); #endif // INCLUDE_CDS #if INCLUDE_JVMCI diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index 90b17b0c234..5b5f806d7b4 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -130,6 +130,7 @@ extern Mutex* CDSClassFileStream_lock; // FileMapInfo::open_stream_for #endif extern Mutex* DumpTimeTable_lock; // SystemDictionaryShared::find_or_allocate_info_for extern Mutex* CDSLambda_lock; // SystemDictionaryShared::get_shared_lambda_proxy_class +extern Mutex* CDSAddSymbol_lock; // SystemDictionaryShared::add_symbol #endif // INCLUDE_CDS #if INCLUDE_JFR extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 84d5a6d26d5..42cbec80947 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -29,7 +29,6 @@ #include "jvmtifiles/jvmti.h" #include "metaprogramming/isRegisteredEnum.hpp" #include "metaprogramming/integralConstant.hpp" -#include "runtime/extendedPC.hpp" #include "utilities/exceptions.hpp" #include "utilities/ostream.hpp" #include "utilities/macros.hpp" @@ -473,9 +472,8 @@ class os: AllStatic { static int pd_self_suspend_thread(Thread* thread); - static ExtendedPC fetch_frame_from_context(const void* ucVoid, intptr_t** sp, intptr_t** fp); + static address fetch_frame_from_context(const void* ucVoid, intptr_t** sp, intptr_t** fp); static frame fetch_frame_from_context(const void* ucVoid); - static frame fetch_frame_from_ucontext(Thread* thread, void* ucVoid); static void breakpoint(); static bool start_debugging(char *buf, int buflen); diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index eed5aa0e9d0..b482e363158 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -121,7 +121,6 @@ static volatile intptr_t gInflationLocks[NINFLATIONLOCKS]; // global list of blocks of monitors PaddedObjectMonitor* ObjectSynchronizer::g_block_list = NULL; bool volatile ObjectSynchronizer::_is_async_deflation_requested = false; -bool volatile ObjectSynchronizer::_is_special_deflation_requested = false; jlong ObjectSynchronizer::_last_async_deflation_time_ns = 0; struct ObjectMonitorListGlobals { @@ -1337,30 +1336,60 @@ bool ObjectSynchronizer::is_async_deflation_needed() { // are too many monitors in use. We don't deflate more frequently // than AsyncDeflationInterval (unless is_async_deflation_requested) // in order to not swamp the ServiceThread. - _last_async_deflation_time_ns = os::javaTimeNanos(); return true; } return false; } bool ObjectSynchronizer::is_safepoint_deflation_needed() { - if (!AsyncDeflateIdleMonitors) { - if (monitors_used_above_threshold()) { - // Too many monitors in use. - return true; + return !AsyncDeflateIdleMonitors && + monitors_used_above_threshold(); // Too many monitors in use. +} + +bool ObjectSynchronizer::request_deflate_idle_monitors() { + bool is_JavaThread = Thread::current()->is_Java_thread(); + bool ret_code = false; + + if (AsyncDeflateIdleMonitors) { + jlong last_time = last_async_deflation_time_ns(); + set_is_async_deflation_requested(true); + { + MonitorLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); + ml.notify_all(); + } + const int N_CHECKS = 5; + for (int i = 0; i < N_CHECKS; i++) { // sleep for at most 5 seconds + if (last_async_deflation_time_ns() > last_time) { + log_info(monitorinflation)("Async Deflation happened after %d check(s).", i); + ret_code = true; + break; + } + if (is_JavaThread) { + // JavaThread has to honor the blocking protocol. + ThreadBlockInVM tbivm(JavaThread::current()); + os::naked_short_sleep(999); // sleep for almost 1 second + } else { + os::naked_short_sleep(999); // sleep for almost 1 second + } } - return false; - } - if (is_special_deflation_requested()) { - // For AsyncDeflateIdleMonitors only do a safepoint deflation - // if there is a special deflation request. - return true; + if (!ret_code) { + log_info(monitorinflation)("Async Deflation DID NOT happen after %d checks.", N_CHECKS); + } + } else { + // Only need to force this safepoint if we are not using async + // deflation. The VMThread won't call this function before the + // final safepoint if we are not using async deflation so we + // don't have to reason about the VMThread executing a VM-op here. + VM_ForceSafepoint force_safepoint_op; + VMThread::execute(&force_safepoint_op); + ret_code = true; } - return false; + + return ret_code; } jlong ObjectSynchronizer::time_since_last_async_deflation_ms() { - return (os::javaTimeNanos() - _last_async_deflation_time_ns) / (NANOUNITS / MILLIUNITS); + return (os::javaTimeNanos() - last_async_deflation_time_ns()) / (NANOUNITS / MILLIUNITS); } void ObjectSynchronizer::oops_do(OopClosure* f) { @@ -2049,9 +2078,8 @@ void ObjectSynchronizer::do_safepoint_work(DeflateMonitorCounters* counters) { // The per-thread in-use lists are handled in // ParallelSPCleanupThreadClosure::do_thread(). - if (!AsyncDeflateIdleMonitors || is_special_deflation_requested()) { - // Use the older mechanism for the global in-use list or if a - // special deflation has been requested before the safepoint. + if (!AsyncDeflateIdleMonitors) { + // Use the older mechanism for the global in-use list. ObjectSynchronizer::deflate_idle_monitors(counters); return; } @@ -2470,10 +2498,8 @@ void ObjectSynchronizer::deflate_idle_monitors(DeflateMonitorCounters* counters) if (AsyncDeflateIdleMonitors) { // Nothing to do when global idle ObjectMonitors are deflated using - // a JavaThread unless a special deflation has been requested. - if (!is_special_deflation_requested()) { - return; - } + // a JavaThread. + return; } bool deflated = false; @@ -2566,6 +2592,7 @@ void ObjectSynchronizer::deflate_idle_monitors_using_JT() { Atomic::load(&om_list_globals._wait_count)); // The ServiceThread's async deflation request has been processed. + _last_async_deflation_time_ns = os::javaTimeNanos(); set_is_async_deflation_requested(false); if (Atomic::load(&om_list_globals._wait_count) > 0) { @@ -2641,16 +2668,6 @@ void ObjectSynchronizer::deflate_common_idle_monitors_using_JT(bool is_global, J } do { - if (saved_mid_in_use_p != NULL) { - // We looped around because deflate_monitor_list_using_JT() - // detected a pending safepoint. Honoring the safepoint is good, - // but as long as is_special_deflation_requested() is supported, - // we can't safely restart using saved_mid_in_use_p. That saved - // ObjectMonitor could have been deflated by safepoint based - // deflation and would no longer be on the in-use list where we - // originally found it. - saved_mid_in_use_p = NULL; - } int local_deflated_count; if (is_global) { local_deflated_count = @@ -2733,10 +2750,9 @@ void ObjectSynchronizer::finish_deflate_idle_monitors(DeflateMonitorCounters* co // than a beginning to end measurement of the phase. log_info(safepoint, cleanup)("deflating per-thread idle monitors, %3.7f secs, monitors=%d", counters->per_thread_times, counters->per_thread_scavenged); - bool needs_special_deflation = is_special_deflation_requested(); - if (AsyncDeflateIdleMonitors && !needs_special_deflation) { + if (AsyncDeflateIdleMonitors) { // Nothing to do when idle ObjectMonitors are deflated using - // a JavaThread unless a special deflation has been requested. + // a JavaThread. return; } @@ -2761,17 +2777,14 @@ void ObjectSynchronizer::finish_deflate_idle_monitors(DeflateMonitorCounters* co GVars.stw_random = os::random(); GVars.stw_cycle++; - - if (needs_special_deflation) { - set_is_special_deflation_requested(false); // special deflation is done - } } void ObjectSynchronizer::deflate_thread_local_monitors(Thread* thread, DeflateMonitorCounters* counters) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - if (AsyncDeflateIdleMonitors && !is_special_deflation_requested()) { - // Nothing to do if a special deflation has NOT been requested. + if (AsyncDeflateIdleMonitors) { + // Nothing to do when per-thread idle ObjectMonitors are deflated + // using a JavaThread. return; } diff --git a/src/hotspot/share/runtime/synchronizer.hpp b/src/hotspot/share/runtime/synchronizer.hpp index 78b0eb34920..16df004a706 100644 --- a/src/hotspot/share/runtime/synchronizer.hpp +++ b/src/hotspot/share/runtime/synchronizer.hpp @@ -161,9 +161,9 @@ class ObjectSynchronizer : AllStatic { static bool is_async_deflation_needed(); static bool is_safepoint_deflation_needed(); static bool is_async_deflation_requested() { return _is_async_deflation_requested; } - static bool is_special_deflation_requested() { return _is_special_deflation_requested; } + static jlong last_async_deflation_time_ns() { return _last_async_deflation_time_ns; } + static bool request_deflate_idle_monitors(); // for whitebox test support and VM exit logging static void set_is_async_deflation_requested(bool new_value) { _is_async_deflation_requested = new_value; } - static void set_is_special_deflation_requested(bool new_value) { _is_special_deflation_requested = new_value; } static jlong time_since_last_async_deflation_ms(); static void oops_do(OopClosure* f); // Process oops in thread local used monitors @@ -200,7 +200,6 @@ class ObjectSynchronizer : AllStatic { // global list of blocks of monitors static PaddedObjectMonitor* g_block_list; static volatile bool _is_async_deflation_requested; - static volatile bool _is_special_deflation_requested; static jlong _last_async_deflation_time_ns; // Function to prepend new blocks to the appropriate lists: diff --git a/src/hotspot/share/runtime/vmOperations.cpp b/src/hotspot/share/runtime/vmOperations.cpp index c7806fb71b2..d66ace1ee37 100644 --- a/src/hotspot/share/runtime/vmOperations.cpp +++ b/src/hotspot/share/runtime/vmOperations.cpp @@ -432,11 +432,10 @@ int VM_Exit::wait_for_threads_in_native_to_block() { bool VM_Exit::doit_prologue() { if (AsyncDeflateIdleMonitors && log_is_enabled(Info, monitorinflation)) { - // AsyncDeflateIdleMonitors does a special deflation at the VM_Exit - // safepoint in order to reduce the in-use monitor population that - // is reported by ObjectSynchronizer::log_in_use_monitor_details() - // at VM exit. - ObjectSynchronizer::set_is_special_deflation_requested(true); + // AsyncDeflateIdleMonitors does a special deflation in order + // to reduce the in-use monitor population that is reported by + // ObjectSynchronizer::log_in_use_monitor_details() at VM exit. + ObjectSynchronizer::request_deflate_idle_monitors(); } return true; } diff --git a/src/hotspot/share/runtime/vmThread.cpp b/src/hotspot/share/runtime/vmThread.cpp index b24b50e44dc..df73d4afb70 100644 --- a/src/hotspot/share/runtime/vmThread.cpp +++ b/src/hotspot/share/runtime/vmThread.cpp @@ -261,11 +261,10 @@ void VMThread::run() { } if (AsyncDeflateIdleMonitors && log_is_enabled(Info, monitorinflation)) { - // AsyncDeflateIdleMonitors does a special deflation at the final - // safepoint in order to reduce the in-use monitor population that - // is reported by ObjectSynchronizer::log_in_use_monitor_details() - // at VM exit. - ObjectSynchronizer::set_is_special_deflation_requested(true); + // AsyncDeflateIdleMonitors does a special deflation in order + // to reduce the in-use monitor population that is reported by + // ObjectSynchronizer::log_in_use_monitor_details() at VM exit. + ObjectSynchronizer::request_deflate_idle_monitors(); } // 4526887 let VM thread exit at Safepoint diff --git a/src/hotspot/share/services/threadService.hpp b/src/hotspot/share/services/threadService.hpp index e9a2748fa4d..7fe5a886a94 100644 --- a/src/hotspot/share/services/threadService.hpp +++ b/src/hotspot/share/services/threadService.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_SERVICES_THREADSERVICE_HPP #define SHARE_SERVICES_THREADSERVICE_HPP +#include "classfile/classLoader.hpp" #include "classfile/javaClasses.hpp" #include "runtime/handles.hpp" #include "runtime/init.hpp" @@ -140,8 +141,8 @@ class ThreadStatistics : public CHeapObj { bool _timer_pending_reset; // Keep accurate times for potentially recursive class operations - int _perf_recursion_counts[6]; - elapsedTimer _perf_timers[6]; + int _perf_recursion_counts[PerfClassTraceTime::EVENT_TYPE_COUNT]; + elapsedTimer _perf_timers[PerfClassTraceTime::EVENT_TYPE_COUNT]; // utility functions void check_and_reset_count() { diff --git a/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp b/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp index 510816b92f9..a929b989f2d 100644 --- a/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp +++ b/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp @@ -111,7 +111,6 @@ inline int g_isfinite(jdouble f) { return _finite(f); } // Miscellaneous // Visual Studio 2005 deprecates POSIX names - use ISO C++ names instead -#if _MSC_VER >= 1400 #define open _open #define close _close #define read _read @@ -119,34 +118,6 @@ inline int g_isfinite(jdouble f) { return _finite(f); } #define lseek _lseek #define unlink _unlink #define strdup _strdup -#endif - -#if _MSC_VER < 1800 -// Visual Studio 2013 introduced strtoull(); before, one has to use _strtoui64() instead. -#define strtoull _strtoui64 -// Visual Studio prior to 2013 had no va_copy, but could safely copy va_list by assignement -#define va_copy(dest, src) dest = src -// Fixes some wrong warnings about 'this' : used in base member initializer list -#pragma warning( disable : 4355 ) -#endif - - -#pragma warning( disable : 4100 ) // unreferenced formal parameter -#pragma warning( disable : 4127 ) // conditional expression is constant -#pragma warning( disable : 4514 ) // unreferenced inline function has been removed -#pragma warning( disable : 4244 ) // possible loss of data -#pragma warning( disable : 4512 ) // assignment operator could not be generated -#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union (needed in windows.h) -#pragma warning( disable : 4511 ) // copy constructor could not be generated -#pragma warning( disable : 4291 ) // no matching operator delete found; memory will not be freed if initialization thows an exception -#pragma warning( disable : 4351 ) // new behavior: elements of array ... will be default initialized -#ifdef CHECK_UNHANDLED_OOPS -#pragma warning( disable : 4521 ) // class has multiple copy ctors of a single type -#pragma warning( disable : 4522 ) // class has multiple assignment operators of a single type -#endif // CHECK_UNHANDLED_OOPS -#if _MSC_VER >= 1400 -#pragma warning( disable : 4996 ) // unsafe string functions. Same as define _CRT_SECURE_NO_WARNINGS/_CRT_SECURE_NO_DEPRICATE -#endif // Formatting. #define FORMAT64_MODIFIER "I64" diff --git a/src/hotspot/share/utilities/stack.hpp b/src/hotspot/share/utilities/stack.hpp index 0b3d6ef921b..cca1c4fd57a 100644 --- a/src/hotspot/share/utilities/stack.hpp +++ b/src/hotspot/share/utilities/stack.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,10 +85,6 @@ template class StackBase size_t _cache_size; // Number of segments in the cache. }; -#ifdef __GNUC__ -#define inline -#endif // __GNUC__ - template class Stack: public StackBase { @@ -207,8 +203,4 @@ class StackIterator: public StackObj size_t _full_seg_size; }; -#ifdef __GNUC__ -#undef inline -#endif // __GNUC__ - #endif // SHARE_UTILITIES_STACK_HPP diff --git a/src/hotspot/share/utilities/stack.inline.hpp b/src/hotspot/share/utilities/stack.inline.hpp index 7c086beb78b..4502a8ac84d 100644 --- a/src/hotspot/share/utilities/stack.inline.hpp +++ b/src/hotspot/share/utilities/stack.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,23 +61,27 @@ template void Stack::push(E item) { assert(!is_full(), "pushing onto a full stack"); - if (this->_cur_seg_size == this->_seg_size) { + size_t index = this->_cur_seg_size; + if (index == this->_seg_size) { push_segment(); + index = 0; // Instead of fetching known zero _cur_seg_size. } - this->_cur_seg[this->_cur_seg_size] = item; - ++this->_cur_seg_size; + this->_cur_seg[index] = item; + this->_cur_seg_size = index + 1; } template E Stack::pop() { assert(!is_empty(), "popping from an empty stack"); - if (this->_cur_seg_size == 1) { - E tmp = _cur_seg[--this->_cur_seg_size]; - pop_segment(); - return tmp; - } - return this->_cur_seg[--this->_cur_seg_size]; + // _cur_seg_size is never 0 if not empty. pop that empties a + // segment also pops the segment. push that adds a segment always + // adds an entry to the new segment. + assert(this->_cur_seg_size != 0, "invariant"); + size_t index = --this->_cur_seg_size; + E result = _cur_seg[index]; + if (index == 0) pop_segment(); + return result; } template @@ -145,9 +149,8 @@ void Stack::free(E* addr, size_t bytes) // Stack is used by the GC code and in some hot paths a lot of the Stack // code gets inlined. This is generally good, but when too much code has -// been inlined, no further inlining is allowed by GCC. Therefore we need -// to prevent parts of the slow path in Stack to be inlined to allow other -// code to be. +// been inlined, further inlining in the caller might be inhibited. So +// prevent infrequent slow path segment manipulation from being inlined. template NOINLINE void Stack::push_segment() { @@ -170,7 +173,7 @@ NOINLINE void Stack::push_segment() } template -void Stack::pop_segment() +NOINLINE void Stack::pop_segment() { assert(this->_cur_seg_size == 0, "current segment is not empty"); E* const prev = get_link(_cur_seg); diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 4aa0ff6ed02..0a67b80bc46 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -2139,11 +2139,6 @@ private Enum readEnum(boolean unshared) throws IOException { return result; } - @SuppressWarnings("preview") - private static boolean isRecord(Class cls) { - return cls.isRecord(); - } - /** * Reads and returns "ordinary" (i.e., not a String, Class, * ObjectStreamClass, array, or enum constant) object, or null if object's @@ -2182,7 +2177,7 @@ private Object readOrdinaryObject(boolean unshared) handles.markException(passHandle, resolveEx); } - final boolean isRecord = cl != null && isRecord(cl) ? true : false; + final boolean isRecord = desc.isRecord(); if (isRecord) { assert obj == null; obj = readRecord(desc); @@ -2289,14 +2284,14 @@ private Object readRecord(ObjectStreamClass desc) throws IOException { FieldValues fieldValues = defaultReadFields(null, desc); - // retrieve the canonical constructor - MethodHandle ctrMH = desc.getRecordConstructor(); - - // bind the stream field values - ctrMH = RecordSupport.bindCtrValues(ctrMH, desc, fieldValues); + // get canonical record constructor adapted to take two arguments: + // - byte[] primValues + // - Object[] objValues + // and return Object + MethodHandle ctrMH = RecordSupport.deserializationCtr(desc); try { - return ctrMH.invoke(); + return (Object) ctrMH.invokeExact(fieldValues.primValues, fieldValues.objValues); } catch (Exception e) { InvalidObjectException ioe = new InvalidObjectException(e.getMessage()); ioe.initCause(e); diff --git a/src/java.base/share/classes/java/io/ObjectStreamClass.java b/src/java.base/share/classes/java/io/ObjectStreamClass.java index b20a4c3db03..0fbeec9d02b 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -27,6 +27,7 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; @@ -56,6 +57,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -192,8 +194,14 @@ InvalidClassException newInvalidClassException() { /** serialization-appropriate constructor, or null if none */ private Constructor cons; - /** record canonical constructor, or null */ + /** record canonical constructor (shared among OSCs for same class), or null */ private MethodHandle canonicalCtr; + /** cache of record deserialization constructors per unique set of stream fields + * (shared among OSCs for same class), or null */ + private DeserializationConstructorsCache deserializationCtrs; + /** session-cache of record deserialization constructor + * (in de-serialized OSC only), or null */ + private MethodHandle deserializationCtr; /** protection domains that need to be checked when calling the constructor */ private ProtectionDomain[] domains; @@ -527,6 +535,7 @@ public Void run() { if (isRecord) { canonicalCtr = canonicalRecordCtr(cl); + deserializationCtrs = new DeserializationConstructorsCache(); } else if (externalizable) { cons = getExternalizableConstructor(cl); } else { @@ -742,10 +751,6 @@ void initNonProxy(ObjectStreamClass model, } this.cl = cl; - if (cl != null) { - this.isRecord = isRecord(cl); - this.canonicalCtr = osc.canonicalCtr; - } this.resolveEx = resolveEx; this.superDesc = superDesc; name = model.name; @@ -762,6 +767,11 @@ void initNonProxy(ObjectStreamClass model, if (osc != null) { localDesc = osc; + isRecord = localDesc.isRecord; + // canonical record constructor is shared + canonicalCtr = localDesc.canonicalCtr; + // cache of deserialization constructors is shared + deserializationCtrs = localDesc.deserializationCtrs; writeObjectMethod = localDesc.writeObjectMethod; readObjectMethod = localDesc.readObjectMethod; readObjectNoDataMethod = localDesc.readObjectNoDataMethod; @@ -2534,14 +2544,135 @@ public boolean equals(Object obj) { } } + // a LRA cache of record deserialization constructors + @SuppressWarnings("serial") + private static final class DeserializationConstructorsCache + extends ConcurrentHashMap { + + // keep max. 10 cached entries - when the 11th element is inserted the oldest + // is removed and 10 remains - 11 is the biggest map size where internal + // table of 16 elements is sufficient (inserting 12th element would resize it to 32) + private static final int MAX_SIZE = 10; + private Key.Impl first, last; // first and last in FIFO queue + + DeserializationConstructorsCache() { + // start small - if there is more than one shape of ObjectStreamClass + // deserialized, there will typically be two (current version and previous version) + super(2); + } + + MethodHandle get(ObjectStreamField[] fields) { + return get(new Key.Lookup(fields)); + } + + synchronized MethodHandle putIfAbsentAndGet(ObjectStreamField[] fields, MethodHandle mh) { + Key.Impl key = new Key.Impl(fields); + var oldMh = putIfAbsent(key, mh); + if (oldMh != null) return oldMh; + // else we did insert new entry -> link the new key as last + if (last == null) { + last = first = key; + } else { + last = (last.next = key); + } + // may need to remove first + if (size() > MAX_SIZE) { + assert first != null; + remove(first); + first = first.next; + if (first == null) { + last = null; + } + } + return mh; + } + + // a key composed of ObjectStreamField[] names and types + static abstract class Key { + abstract int length(); + abstract String fieldName(int i); + abstract Class fieldType(int i); + + @Override + public final int hashCode() { + int n = length(); + int h = 0; + for (int i = 0; i < n; i++) h = h * 31 + fieldType(i).hashCode(); + for (int i = 0; i < n; i++) h = h * 31 + fieldName(i).hashCode(); + return h; + } + + @Override + public final boolean equals(Object obj) { + if (!(obj instanceof Key)) return false; + Key other = (Key) obj; + int n = length(); + if (n != other.length()) return false; + for (int i = 0; i < n; i++) if (fieldType(i) != other.fieldType(i)) return false; + for (int i = 0; i < n; i++) if (!fieldName(i).equals(other.fieldName(i))) return false; + return true; + } + + // lookup key - just wraps ObjectStreamField[] + static final class Lookup extends Key { + final ObjectStreamField[] fields; + + Lookup(ObjectStreamField[] fields) { this.fields = fields; } + + @Override + int length() { return fields.length; } + + @Override + String fieldName(int i) { return fields[i].getName(); } + + @Override + Class fieldType(int i) { return fields[i].getType(); } + } + + // real key - copies field names and types and forms FIFO queue in cache + static final class Impl extends Key { + Impl next; + final String[] fieldNames; + final Class[] fieldTypes; + + Impl(ObjectStreamField[] fields) { + this.fieldNames = new String[fields.length]; + this.fieldTypes = new Class[fields.length]; + for (int i = 0; i < fields.length; i++) { + fieldNames[i] = fields[i].getName(); + fieldTypes[i] = fields[i].getType(); + } + } + + @Override + int length() { return fieldNames.length; } + + @Override + String fieldName(int i) { return fieldNames[i]; } + + @Override + Class fieldType(int i) { return fieldTypes[i]; } + } + } + } + /** Record specific support for retrieving and binding stream field values. */ static final class RecordSupport { - - /** Binds the given stream field values to the given method handle. */ + /** + * Returns canonical record constructor adapted to take two arguments: + * {@code (byte[] primValues, Object[] objValues)} + * and return + * {@code Object} + */ @SuppressWarnings("preview") - static MethodHandle bindCtrValues(MethodHandle ctrMH, - ObjectStreamClass desc, - ObjectInputStream.FieldValues fieldValues) { + static MethodHandle deserializationCtr(ObjectStreamClass desc) { + // check the cached value 1st + MethodHandle mh = desc.deserializationCtr; + if (mh != null) return mh; + mh = desc.deserializationCtrs.get(desc.getFields(false)); + if (mh != null) return desc.deserializationCtr = mh; + + // retrieve record components RecordComponent[] recordComponents; try { Class cls = desc.forClass(); @@ -2551,15 +2682,36 @@ static MethodHandle bindCtrValues(MethodHandle ctrMH, throw new InternalError(e.getCause()); } - Object[] args = new Object[recordComponents.length]; - for (int i = 0; i < recordComponents.length; i++) { + // retrieve the canonical constructor + // (T1, T2, ..., Tn):TR + mh = desc.getRecordConstructor(); + + // change return type to Object + // (T1, T2, ..., Tn):TR -> (T1, T2, ..., Tn):Object + mh = mh.asType(mh.type().changeReturnType(Object.class)); + + // drop last 2 arguments representing primValues and objValues arrays + // (T1, T2, ..., Tn):Object -> (T1, T2, ..., Tn, byte[], Object[]):Object + mh = MethodHandles.dropArguments(mh, mh.type().parameterCount(), byte[].class, Object[].class); + + for (int i = recordComponents.length-1; i >= 0; i--) { String name = recordComponents[i].getName(); - Class type= recordComponents[i].getType(); - Object o = streamFieldValue(name, type, desc, fieldValues); - args[i] = o; + Class type = recordComponents[i].getType(); + // obtain stream field extractor that extracts argument at + // position i (Ti+1) from primValues and objValues arrays + // (byte[], Object[]):Ti+1 + MethodHandle combiner = streamFieldExtractor(name, type, desc); + // fold byte[] privValues and Object[] objValues into argument at position i (Ti+1) + // (..., Ti, Ti+1, byte[], Object[]):Object -> (..., Ti, byte[], Object[]):Object + mh = MethodHandles.foldArguments(mh, i, combiner); } + // what we are left with is a MethodHandle taking just the primValues + // and objValues arrays and returning the constructed record instance + // (byte[], Object[]):Object - return MethodHandles.insertArguments(ctrMH, 0, args); + // store it into cache and return the 1st value stored + return desc.deserializationCtr = + desc.deserializationCtrs.putIfAbsentAndGet(desc.getFields(false), mh); } /** Returns the number of primitive fields for the given descriptor. */ @@ -2575,37 +2727,15 @@ private static int numberPrimValues(ObjectStreamClass desc) { return primValueCount; } - /** Returns the default value for the given type. */ - private static Object defaultValueFor(Class pType) { - if (pType == Integer.TYPE) - return 0; - else if (pType == Byte.TYPE) - return (byte)0; - else if (pType == Long.TYPE) - return 0L; - else if (pType == Float.TYPE) - return 0.0f; - else if (pType == Double.TYPE) - return 0.0d; - else if (pType == Short.TYPE) - return (short)0; - else if (pType == Character.TYPE) - return '\u0000'; - else if (pType == Boolean.TYPE) - return false; - else - return null; - } - /** - * Returns the stream field value for the given name. The default value - * for the given type is returned if the field value is absent. + * Returns extractor MethodHandle taking the primValues and objValues arrays + * and extracting the argument of canonical constructor with given name and type + * or producing default value for the given type if the field is absent. */ - private static Object streamFieldValue(String pName, - Class pType, - ObjectStreamClass desc, - ObjectInputStream.FieldValues fieldValues) { - ObjectStreamField[] fields = desc.getFields(); + private static MethodHandle streamFieldExtractor(String pName, + Class pType, + ObjectStreamClass desc) { + ObjectStreamField[] fields = desc.getFields(false); for (int i = 0; i < fields.length; i++) { ObjectStreamField f = fields[i]; @@ -2618,30 +2748,62 @@ private static Object streamFieldValue(String pName, throw new InternalError(fName + " unassignable, pType:" + pType + ", fType:" + fType); if (f.isPrimitive()) { - if (pType == Integer.TYPE) - return Bits.getInt(fieldValues.primValues, f.getOffset()); - else if (fType == Byte.TYPE) - return fieldValues.primValues[f.getOffset()]; - else if (fType == Long.TYPE) - return Bits.getLong(fieldValues.primValues, f.getOffset()); - else if (fType == Float.TYPE) - return Bits.getFloat(fieldValues.primValues, f.getOffset()); - else if (fType == Double.TYPE) - return Bits.getDouble(fieldValues.primValues, f.getOffset()); - else if (fType == Short.TYPE) - return Bits.getShort(fieldValues.primValues, f.getOffset()); - else if (fType == Character.TYPE) - return Bits.getChar(fieldValues.primValues, f.getOffset()); - else if (fType == Boolean.TYPE) - return Bits.getBoolean(fieldValues.primValues, f.getOffset()); - else + // (byte[], int):fType + MethodHandle mh = PRIM_VALUE_EXTRACTORS.get(fType); + if (mh == null) { throw new InternalError("Unexpected type: " + fType); + } + // bind offset + // (byte[], int):fType -> (byte[]):fType + mh = MethodHandles.insertArguments(mh, 1, f.getOffset()); + // drop objValues argument + // (byte[]):fType -> (byte[], Object[]):fType + mh = MethodHandles.dropArguments(mh, 1, Object[].class); + // adapt return type to pType + // (byte[], Object[]):fType -> (byte[], Object[]):pType + if (pType != fType) { + mh = mh.asType(mh.type().changeReturnType(pType)); + } + return mh; } else { // reference - return fieldValues.objValues[i - numberPrimValues(desc)]; + // (Object[], int):Object + MethodHandle mh = MethodHandles.arrayElementGetter(Object[].class); + // bind index + // (Object[], int):Object -> (Object[]):Object + mh = MethodHandles.insertArguments(mh, 1, i - numberPrimValues(desc)); + // drop primValues argument + // (Object[]):Object -> (byte[], Object[]):Object + mh = MethodHandles.dropArguments(mh, 0, byte[].class); + // adapt return type to pType + // (byte[], Object[]):Object -> (byte[], Object[]):pType + if (pType != Object.class) { + mh = mh.asType(mh.type().changeReturnType(pType)); + } + return mh; } } - return defaultValueFor(pType); + // return default value extractor if no field matches pName + return MethodHandles.empty(MethodType.methodType(pType, byte[].class, Object[].class)); + } + + private static final Map, MethodHandle> PRIM_VALUE_EXTRACTORS; + static { + var lkp = MethodHandles.lookup(); + try { + PRIM_VALUE_EXTRACTORS = Map.of( + byte.class, MethodHandles.arrayElementGetter(byte[].class), + short.class, lkp.findStatic(Bits.class, "getShort", MethodType.methodType(short.class, byte[].class, int.class)), + int.class, lkp.findStatic(Bits.class, "getInt", MethodType.methodType(int.class, byte[].class, int.class)), + long.class, lkp.findStatic(Bits.class, "getLong", MethodType.methodType(long.class, byte[].class, int.class)), + float.class, lkp.findStatic(Bits.class, "getFloat", MethodType.methodType(float.class, byte[].class, int.class)), + double.class, lkp.findStatic(Bits.class, "getDouble", MethodType.methodType(double.class, byte[].class, int.class)), + char.class, lkp.findStatic(Bits.class, "getChar", MethodType.methodType(char.class, byte[].class, int.class)), + boolean.class, lkp.findStatic(Bits.class, "getBoolean", MethodType.methodType(boolean.class, byte[].class, int.class)) + ); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new InternalError("Can't lookup Bits.getXXX", e); + } } } } diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java index 0ba39b0e64b..6f3eb264c44 100644 --- a/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/src/java.base/share/classes/java/lang/ClassLoader.java @@ -133,11 +133,12 @@ * It is the virtual machine's built-in class loader, typically represented * as {@code null}, and does not have a parent. *
  • {@linkplain #getPlatformClassLoader() Platform class loader}. - * All platform classes are visible to the platform class loader - * that can be used as the parent of a {@code ClassLoader} instance. - * Platform classes include Java SE platform APIs, their implementation - * classes and JDK-specific run-time classes that are defined by the - * platform class loader or its ancestors. + * The platform class loader is responsible for loading the + * platform classes. Platform classes include Java SE platform APIs, + * their implementation classes and JDK-specific run-time classes that are + * defined by the platform class loader or its ancestors. + * The platform class loader can be used as the parent of a {@code ClassLoader} + * instance. *

    To allow for upgrading/overriding of modules defined to the platform * class loader, and where upgraded modules read modules defined to class * loaders other than the platform class loader and its ancestors, then @@ -151,8 +152,9 @@ * from the platform class loader. * The system class loader is typically used to define classes on the * application class path, module path, and JDK-specific tools. - * The platform class loader is a parent or an ancestor of the system class - * loader that all platform classes are visible to it.

  • + * The platform class loader is the parent or an ancestor of the system class + * loader, so the system class loader can load platform classes by delegating + * to its parent. * * *

    Normally, the Java virtual machine loads classes from the local file diff --git a/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java b/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java index db20841f2a1..8f79bdc6e6f 100644 --- a/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java @@ -163,19 +163,24 @@ public static int vectorizedMismatch(Object a, long aOffset, /** * Mismatch over long lengths. */ - public static long vectorizedMismatchLarge(Object a, long aOffset, - Object b, long bOffset, - long length, - int log2ArrayIndexScale) { + public static long vectorizedMismatchLargeForBytes(Object a, long aOffset, + Object b, long bOffset, + long length) { long off = 0; long remaining = length; - int i ; - while (remaining > 7) { - int size = (int) Math.min(Integer.MAX_VALUE, remaining); + int i, size; + boolean lastSubRange = false; + while (remaining > 7 && !lastSubRange) { + if (remaining > Integer.MAX_VALUE) { + size = Integer.MAX_VALUE; + } else { + size = (int) remaining; + lastSubRange = true; + } i = vectorizedMismatch( a, aOffset + off, b, bOffset + off, - size, log2ArrayIndexScale); + size, LOG2_ARRAY_BYTE_INDEX_SCALE); if (i >= 0) return off + i; @@ -183,7 +188,7 @@ public static long vectorizedMismatchLarge(Object a, long aOffset, off += i; remaining -= i; } - return ~off; + return ~remaining; } // Booleans diff --git a/src/java.compiler/share/classes/javax/annotation/processing/Filer.java b/src/java.compiler/share/classes/javax/annotation/processing/Filer.java index 7fe41006104..e077d7b7edb 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/Filer.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/Filer.java @@ -164,7 +164,7 @@ public interface Filer { * An implementation may use information about the configuration of * the annotation processing tool as part of the inference. * - *

    Creating a source file in or for an unnamed package in a named + *

    Creating a source file in or for an unnamed package in a named * module is not supported. * * @apiNote To use a particular {@linkplain @@ -240,7 +240,7 @@ JavaFileObject createSourceFile(CharSequence name, * An implementation may use information about the configuration of * the annotation processing tool as part of the inference. * - *

    Creating a class file in or for an unnamed package in a named + *

    Creating a class file in or for an unnamed package in a named * module is not supported. * * @apiNote To avoid subsequent errors, the contents of the class diff --git a/src/java.compiler/share/classes/javax/annotation/processing/Processor.java b/src/java.compiler/share/classes/javax/annotation/processing/Processor.java index c9bd9738b20..c4ff4619c79 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/Processor.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/Processor.java @@ -234,7 +234,7 @@ public interface Processor { * in which case it may wish to report a warning. * * @return the options recognized by this processor or an - * empty collection if none + * empty set if none * @see javax.annotation.processing.SupportedOptions */ Set getSupportedOptions(); @@ -286,7 +286,8 @@ public interface Processor { * * * where TypeName and ModuleName are as defined in - * The Java™ Language Specification. + * The Java™ Language Specification + * ({@jls 6.5 Determining the Meaning of a Name}). * * @apiNote When running in an environment which supports modules, * processors are encouraged to include the module prefix when @@ -297,9 +298,9 @@ public interface Processor { * environment without modules. * * @return the names of the annotation types supported by this processor + * or an empty set if none * @see javax.annotation.processing.SupportedAnnotationTypes * @jls 3.8 Identifiers - * @jls 6.5 Determining the Meaning of a Name */ Set getSupportedAnnotationTypes(); @@ -390,14 +391,14 @@ boolean process(Set annotations, *

         * import static javax.annotation.processing.Completions.*;
         * ...
    -    * return Arrays.asList({@link Completions#of(String) of}("3"),
    -    *                      of("7"),
    -    *                      of("31"),
    -    *                      of("127"),
    -    *                      of("8191"),
    -    *                      of("131071"),
    -    *                      of("524287"),
    -    *                      of("2147483647"));
    +    * return List.of({@link Completions#of(String) of}("3"),
    +    *                of("7"),
    +    *                of("31"),
    +    *                of("127"),
    +    *                of("8191"),
    +    *                of("131071"),
    +    *                of("524287"),
    +    *                of("2147483647"));
         * 
    * * @@ -406,14 +407,14 @@ boolean process(Set annotations, * *
    *
    -    * return Arrays.asList({@link Completions#of(String, String) of}("3",          "M2"),
    -    *                      of("7",          "M3"),
    -    *                      of("31",         "M5"),
    -    *                      of("127",        "M7"),
    -    *                      of("8191",       "M13"),
    -    *                      of("131071",     "M17"),
    -    *                      of("524287",     "M19"),
    -    *                      of("2147483647", "M31"));
    +    * return List.of({@link Completions#of(String, String) of}("3",          "M2"),
    +    *                of("7",          "M3"),
    +    *                of("31",         "M5"),
    +    *                of("127",        "M7"),
    +    *                of("8191",       "M13"),
    +    *                of("131071",     "M17"),
    +    *                of("524287",     "M19"),
    +    *                of("2147483647", "M31"));
         * 
    *
    * diff --git a/src/java.compiler/share/classes/javax/lang/model/AnnotatedConstruct.java b/src/java.compiler/share/classes/javax/lang/model/AnnotatedConstruct.java index d639af0bdcf..6f9220edf7b 100644 --- a/src/java.compiler/share/classes/javax/lang/model/AnnotatedConstruct.java +++ b/src/java.compiler/share/classes/javax/lang/model/AnnotatedConstruct.java @@ -81,8 +81,8 @@ * C, then if AT is repeatable annotation type, an * annotation of type ATC is {@linkplain javax.lang.model.util.Elements#getOrigin(AnnotatedConstruct, AnnotationMirror) implicitly declared} on C. *
  • A representation of A appears in the executable output - * for C, such as the {@code RuntimeVisibleAnnotations} or - * {@code RuntimeVisibleParameterAnnotations} attributes of a class + * for C, such as the {@code RuntimeVisibleAnnotations} (JVMS {@jvms 4.7.16}) or + * {@code RuntimeVisibleParameterAnnotations} (JVMS {@jvms 4.7.17}) attributes of a class * file. * * diff --git a/src/java.compiler/share/classes/javax/lang/model/UnknownEntityException.java b/src/java.compiler/share/classes/javax/lang/model/UnknownEntityException.java index 34971fab11e..3e2cee42400 100644 --- a/src/java.compiler/share/classes/javax/lang/model/UnknownEntityException.java +++ b/src/java.compiler/share/classes/javax/lang/model/UnknownEntityException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,6 @@ * this exception may be thrown by visitors to indicate that the * visitor was created for a prior version of the language. * - * @apiNote A common superclass for exceptions specific to different - * kinds of unknown entities allows a single catch block to easily - * provide uniform handling of those related conditions. - * * @author Joseph D. Darcy * @see javax.lang.model.element.UnknownElementException * @see javax.lang.model.element.UnknownAnnotationValueException diff --git a/src/java.compiler/share/classes/javax/lang/model/element/Element.java b/src/java.compiler/share/classes/javax/lang/model/element/Element.java index 39b3d14e03f..0e1593cd2b1 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/Element.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/Element.java @@ -37,7 +37,7 @@ /** * Represents a program element such as a module, package, class, or method. - * Each element represents a static, language-level construct + * Each element represents a compile-time language-level construct * (and not, for example, a runtime construct of the virtual machine). * *

    Elements should be compared using the {@link #equals(Object)} diff --git a/src/java.compiler/share/classes/javax/lang/model/element/RecordComponentElement.java b/src/java.compiler/share/classes/javax/lang/model/element/RecordComponentElement.java index 5b7d4ce54ff..be4bd7c2680 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/RecordComponentElement.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/RecordComponentElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ public interface RecordComponentElement extends Element { * Returns the simple name of this record component. * *

    The name of each record component must be distinct from the - * names of all other record components. + * names of all other record components of the same record. * * @return the simple name of this record component * diff --git a/src/java.compiler/share/classes/javax/lang/model/element/package-info.java b/src/java.compiler/share/classes/javax/lang/model/element/package-info.java index 83f849d6230..6787ea97538 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/package-info.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ * recovered from class files and class files might not be able to * provide source position information. * - * Names of parameters may not be recoverable from class files. + * Names of {@linkplain javax.lang.model.element.ExecutableElement#getParameters() parameters} may not be recoverable from class files. * * The {@linkplain javax.lang.model.element.Modifier modifiers} on an * element created from a class file may differ in some cases from an @@ -108,6 +108,15 @@ * @author Scott Seligman * @author Peter von der Ahé * @see javax.lang.model.util.Elements + * @jls 6.1 Declarations + * @jls 7.4 Package Declarations + * @jls 7.7 Module Declarations + * @jls 8.1 Class Declarations + * @jls 8.3 Field Declarations + * @jls 8.4 Method Declarations + * @jls 8.5 Member Type Declarations + * @jls 8.8 Constructor Declarations + * @jls 9.1 Interface Declarations * @since 1.6 */ package javax.lang.model.element; diff --git a/src/java.compiler/share/classes/javax/lang/model/type/NullType.java b/src/java.compiler/share/classes/javax/lang/model/type/NullType.java index 2bb96e3c4b2..cc41a02990e 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/NullType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/NullType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,8 @@ * @author Joseph D. Darcy * @author Scott Seligman * @author Peter von der Ahé + * @jls 3.10.7 The Null Literal + * @jls 4.1 The Kinds of Types and Values * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/type/PrimitiveType.java b/src/java.compiler/share/classes/javax/lang/model/type/PrimitiveType.java index 4c8883c0223..e91f1ef2998 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/PrimitiveType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/PrimitiveType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ * @author Joseph D. Darcy * @author Scott Seligman * @author Peter von der Ahé + * @jls 4.2 Primitive Types and Values * @since 1.6 */ public interface PrimitiveType extends TypeMirror { diff --git a/src/java.compiler/share/classes/javax/lang/model/type/ReferenceType.java b/src/java.compiler/share/classes/javax/lang/model/type/ReferenceType.java index d41a72b2d5c..9ab823ee81b 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/ReferenceType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/ReferenceType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ * @author Joseph D. Darcy * @author Scott Seligman * @author Peter von der Ahé + * @jls 4.3 Reference Types and Values * @since 1.6 */ public interface ReferenceType extends TypeMirror { diff --git a/src/java.compiler/share/classes/javax/lang/model/type/TypeMirror.java b/src/java.compiler/share/classes/javax/lang/model/type/TypeMirror.java index 7d2b862ee00..f8881f7b04a 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/TypeMirror.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/TypeMirror.java @@ -55,6 +55,14 @@ * @author Peter von der Ahé * @see Element * @see Types + * @jls 4.1 The Kinds of Types and Values + * @jls 4.2 Primitive Types and Values + * @jls 4.3 Reference Types and Values + * @jls 4.4 Type Variables + * @jls 4.5 Parameterized Types + * @jls 4.8 Raw Types + * @jls 4.9 Intersection Types + * @jls 10.1 Array Types * @since 1.6 */ public interface TypeMirror extends javax.lang.model.AnnotatedConstruct { diff --git a/src/java.compiler/share/classes/javax/lang/model/type/TypeVariable.java b/src/java.compiler/share/classes/javax/lang/model/type/TypeVariable.java index dd45b59c68a..1056ad7c356 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/TypeVariable.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/TypeVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,13 +38,14 @@ * type, method, or constructor. * A type variable may also be declared implicitly, as by * the capture conversion of a wildcard type argument - * (see chapter 5 of + * (see chapter {@jls 5} of * The Java™ Language Specification). * * @author Joseph D. Darcy * @author Scott Seligman * @author Peter von der Ahé * @see TypeParameterElement + * @jls 4.4 Type Variables * @since 1.6 */ public interface TypeVariable extends ReferenceType { @@ -67,6 +68,7 @@ public interface TypeVariable extends ReferenceType { * {@linkplain IntersectionType#getBounds() bounds}. * * @return the upper bound of this type variable + * @jls 4.9 Intersection Types */ TypeMirror getUpperBound(); @@ -78,6 +80,7 @@ public interface TypeVariable extends ReferenceType { * lower bound of {@link NullType}. * * @return the lower bound of this type variable + * @jls 18.1.3. Bounds */ TypeMirror getLowerBound(); } diff --git a/src/java.compiler/share/classes/javax/lang/model/type/UnionType.java b/src/java.compiler/share/classes/javax/lang/model/type/UnionType.java index 97d7014bb6e..d33d696b384 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/UnionType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/UnionType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ * Union types can appear as the type of a multi-catch exception * parameter. * + * @jls 14.20 The try statement * @since 1.7 */ public interface UnionType extends TypeMirror { diff --git a/src/java.compiler/share/classes/javax/lang/model/type/WildcardType.java b/src/java.compiler/share/classes/javax/lang/model/type/WildcardType.java index 859cdfc6c0a..f6d091c8d00 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/WildcardType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/WildcardType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ * @author Joseph D. Darcy * @author Scott Seligman * @author Peter von der Ahé + * @jls 4.5.1 Type Arguments of Parameterized Types * @since 1.6 */ public interface WildcardType extends TypeMirror { diff --git a/src/java.compiler/share/classes/javax/lang/model/type/package-info.java b/src/java.compiler/share/classes/javax/lang/model/type/package-info.java index a33eba0f684..13ec0f638bc 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/package-info.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,14 @@ * @author Scott Seligman * @author Peter von der Ahé * @see javax.lang.model.util.Types + * @jls 4.1 The Kinds of Types and Values + * @jls 4.2 Primitive Types and Values + * @jls 4.3 Reference Types and Values + * @jls 4.4 Type Variables + * @jls 4.5 Parameterized Types + * @jls 4.8 Raw Types + * @jls 4.9 Intersection Types + * @jls 10.1 Array Types * @since 1.6 */ package javax.lang.model.type; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java index 79397ad99d9..c988c1bf863 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java @@ -171,15 +171,16 @@ private static Collection createRequestSubprotocols( static URI createRequestURI(URI uri) { String s = uri.getScheme(); assert "ws".equalsIgnoreCase(s) || "wss".equalsIgnoreCase(s); - String scheme = "ws".equalsIgnoreCase(s) ? "http" : "https"; + String newUri = uri.toString(); + if (s.equalsIgnoreCase("ws")) { + newUri = "http" + newUri.substring(2); + } + else { + newUri = "https" + newUri.substring(3); + } + try { - return new URI(scheme, - uri.getUserInfo(), - uri.getHost(), - uri.getPort(), - uri.getPath(), - uri.getQuery(), - null); // No fragment + return new URI(newUri); } catch (URISyntaxException e) { // Shouldn't happen: URI invariant throw new InternalError(e); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java index 8249f53e17b..cc5d14cae95 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java @@ -36,6 +36,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -114,6 +115,7 @@ public class Checker extends DocTreePathScanner { public enum Flag { TABLE_HAS_CAPTION, + TABLE_IS_PRESENTATION, HAS_ELEMENT, HAS_HEADING, HAS_INLINE_TAG, @@ -530,7 +532,8 @@ public Void visitEndElement(EndElementTree tree, Void ignore) { if (t == top.tag) { switch (t) { case TABLE: - if (!top.attrs.contains(HtmlTag.Attr.SUMMARY) + if (!top.flags.contains(Flag.TABLE_IS_PRESENTATION) + && !top.attrs.contains(HtmlTag.Attr.SUMMARY) && !top.flags.contains(Flag.TABLE_HAS_CAPTION)) { env.messages.error(ACCESSIBILITY, tree, "dc.no.summary.or.caption.for.table"); @@ -687,6 +690,15 @@ public Void visitAttribute(AttributeTree tree, Void ignore) { } } break; + + case ROLE: + if (currTag == HtmlTag.TABLE) { + String v = getAttrValue(tree); + if (Objects.equals(v, "presentation")) { + tagStack.peek().flags.add(Flag.TABLE_IS_PRESENTATION); + } + } + break; } } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java index aaa30e186c7..dff3340e565 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java @@ -220,6 +220,7 @@ public static Symtab instance(Context context) { public final Type elementTypeType; public final Type functionalInterfaceType; public final Type previewFeatureType; + public final Type previewFeatureInternalType; public final Type typeDescriptorType; public final Type recordType; public final Type valueBasedType; @@ -595,6 +596,7 @@ public R accept(ElementVisitor v, P p) { valueBootstrapMethods = enterClass("java.lang.invoke.ValueBootstrapMethods"); functionalInterfaceType = enterClass("java.lang.FunctionalInterface"); previewFeatureType = enterClass("jdk.internal.PreviewFeature"); + previewFeatureInternalType = enterSyntheticAnnotation("jdk.internal.PreviewFeature+Annotation"); typeDescriptorType = enterClass("java.lang.invoke.TypeDescriptor"); recordType = enterClass("java.lang.Record"); valueBasedType = enterClass("java.lang.ValueBased"); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 0fed6519bfc..96c4d48655d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1470,6 +1470,9 @@ else if (proxy.type.tsym.flatName() == syms.profileType.tsym.flatName()) { } } } + } else if (proxy.type.tsym.flatName() == syms.previewFeatureInternalType.tsym.flatName()) { + sym.flags_field |= PREVIEW_API; + setFlagIfAttributeTrue(proxy, sym, names.essentialAPI, PREVIEW_ESSENTIAL_API); } else { if (proxy.type.tsym == syms.annotationTargetType.tsym) { target = proxy; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index 2663edaf175..0a4d4ac12a1 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -3893,15 +3893,7 @@ protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) { nextToken(); implementing = typeList(); } - List permitting = List.nil(); - if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) { - checkSourceLevel(Feature.SEALED_CLASSES); - if ((mods.flags & Flags.SEALED) == 0) { - log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed("class"))); - } - nextToken(); - permitting = qualidentList(false); - } + List permitting = permitsClause(mods, "class"); List defs = classInterfaceOrRecordBody(name, false, false); JCClassDecl result = toP(F.at(pos).ClassDef( mods, name, typarams, extending, implementing, permitting, defs)); @@ -3981,15 +3973,7 @@ protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) { nextToken(); extending = typeList(); } - List permitting = List.nil(); - if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) { - checkSourceLevel(Feature.SEALED_CLASSES); - if ((mods.flags & Flags.SEALED) == 0) { - log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed("interface"))); - } - nextToken(); - permitting = typeList(); - } + List permitting = permitsClause(mods, "interface"); List defs; defs = classInterfaceOrRecordBody(name, true, false); JCClassDecl result = toP(F.at(pos).ClassDef( @@ -3998,6 +3982,18 @@ protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) { return result; } + List permitsClause(JCModifiers mods, String classOrInterface) { + if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) { + checkSourceLevel(Feature.SEALED_CLASSES); + if ((mods.flags & Flags.SEALED) == 0) { + log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed(classOrInterface))); + } + nextToken(); + return qualidentList(false); + } + return List.nil(); + } + /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody * @param mods The modifiers starting the enum declaration * @param dc The documentation comment for the enum, or null. diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/DwarfParser.cpp b/src/jdk.hotspot.agent/linux/native/libsaproc/DwarfParser.cpp index bd50a17b9af..33554463e2a 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/DwarfParser.cpp +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/DwarfParser.cpp @@ -104,7 +104,9 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_cr DwarfParser *parser = new DwarfParser(reinterpret_cast(lib)); if (!parser->is_parseable()) { jclass ex_cls = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"); - env->ThrowNew(ex_cls, "DWARF not found"); + if (!env->ExceptionOccurred()) { + env->ThrowNew(ex_cls, "DWARF not found"); + } return 0L; } @@ -146,7 +148,9 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_pro DwarfParser *parser = reinterpret_cast(get_dwarf_context(env, this_obj)); if (!parser->process_dwarf(pc)) { jclass ex_cls = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"); - env->ThrowNew(ex_cls, "Could not find PC in DWARF"); + if (!env->ExceptionOccurred()) { + env->ThrowNew(ex_cls, "Could not find PC in DWARF"); + } return; } } diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/libproc_impl.c b/src/jdk.hotspot.agent/macosx/native/libsaproc/libproc_impl.c index b84c6505997..a7e4b0b5874 100644 --- a/src/jdk.hotspot.agent/macosx/native/libsaproc/libproc_impl.c +++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/libproc_impl.c @@ -56,6 +56,8 @@ int pathmap_open(const char* name) { if (fd >= 0) { print_debug("path %s substituted for %s\n", alt_path, name); return fd; + } else { + print_debug("can't open %s\n", alt_path); } if (strrchr(name, '/')) { @@ -65,12 +67,16 @@ int pathmap_open(const char* name) { if (fd >= 0) { print_debug("path %s substituted for %s\n", alt_path, name); return fd; + } else { + print_debug("can't open %s\n", alt_path); } } } else { fd = open(name, O_RDONLY); if (fd >= 0) { return fd; + } else { + print_debug("can't open %s\n", name); } } return -1; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CompressedReadStream.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CompressedReadStream.java index 671bd4362db..49f1d2b3124 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CompressedReadStream.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CompressedReadStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,7 @@ public double readDouble() { int rl = readInt(); int h = reverseInt(rh); int l = reverseInt(rl); - return Double.longBitsToDouble((h << 32) | ((long)l & 0x00000000FFFFFFFFL)); + return Double.longBitsToDouble(((long)h << 32) | ((long)l & 0x00000000FFFFFFFFL)); } public long readLong() { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java index eead7038466..8a8ead72bf9 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java @@ -822,8 +822,8 @@ private static void initialize() { // CDS specific. Bytecodes rewritten at CDS dump time def(_nofast_getfield , "_nofast_getfield" , "bJJ" , null , BasicType.getTIllegal() , 0, true, _getfield ); def(_nofast_putfield , "_nofast_putfield" , "bJJ" , null , BasicType.getTIllegal() ,-2, true, _putfield ); - def(_nofast_aload_0 , "_nofast_aload_0" , "b" , null , BasicType.getTIllegal() , 1, true, _aload_0 ); - def(_nofast_iload , "_nofast_iload" , "bi" , null , BasicType.getTIllegal() , 1, false, _iload ); + def(_nofast_aload_0 , "_nofast_aload_0" , "b" , null , BasicType.getTObject() , 1, true, _aload_0 ); + def(_nofast_iload , "_nofast_iload" , "bi" , null , BasicType.getTInt() , 1, false, _iload ); def(_shouldnotreachhere , "_shouldnotreachhere" , "b" , null , BasicType.getTVoid() , 0, false); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java index dfd85559063..f5774d79eb7 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java @@ -52,7 +52,7 @@ * explicitly permitted types. * * @implSpec - * Implementations of this interface are immutable and thread-safe. + * Implementations of this interface are immutable, thread-safe and value-based. */ public interface MemoryAddress { /** diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java index 4c3efa16668..b9a6d145f39 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java @@ -54,6 +54,27 @@ * element layout (see {@link SequenceLayout}); a group layout denotes an aggregation of (typically) heterogeneous * member layouts (see {@link GroupLayout}). *

    + * For instance, consider the following struct declaration in C: + * + *

    {@code
    + typedef struct {
    +     char kind;
    +     int value;
    + } TaggedValues[5];
    + * }
    + * + * The above declaration can be modelled using a layout object, as follows: + * + *
    {@code
    +SequenceLayout taggedValues = MemoryLayout.ofSequence(5,
    +    MemoryLayout.ofStruct(
    +        MemoryLayout.ofValueBits(8, ByteOrder.NATIVE_ORDER).withName("kind"),
    +        MemoryLayout.ofPaddingBits(24),
    +        MemoryLayout.ofValueBits(32, ByteOrder.NATIVE_ORDER).withName("value")
    +    )
    +).withName("TaggedValues");
    + * }
    + *

    * All implementations of this interface must be value-based; * use of identity-sensitive operations (including reference equality ({@code ==}), identity hash code, or synchronization) on * instances of {@code MemoryLayout} may have unpredictable results and should be avoided. The {@code equals} method should @@ -103,53 +124,30 @@ * another layout (see {@link MemoryLayout#map(UnaryOperator, PathElement...)}). *

    * Such layout paths can be constructed programmatically using the methods in this class. - * For instance, given a layout constructed as follows: - *

    {@code
    -SequenceLayout seq = MemoryLayout.ofSequence(5,
    -    MemoryLayout.ofStruct(
    -        MemoryLayout.ofPaddingBits(32),
    -        MemoryLayout.ofValueBits(32, ByteOrder.BIG_ENDIAN).withName("value")
    -));
    - * }
    - * - * We can obtain the offset, in bits, of the member layout named value from seq, as follows: + * For instance, given the {@code taggedValues} layout instance constructed as above, we can obtain the offset, + * in bits, of the member layout named value in the first sequence element, as follows: *
    {@code
    -long valueOffset = seq.bitOffset(PathElement.sequenceElement(), PathElement.groupElement("value"));
    - * }
    - * - * Similarly, we can select the member layout named {@code value}, as follows: - *
    {@code
    -MemoryLayout value = seq.select(PathElement.sequenceElement(), PathElement.groupElement("value"));
    - * }
    - * - * And, we can also replace the layout named {@code value} with another layout, as follows: - *
    {@code
    -MemoryLayout newSeq = seq.map(l -> MemoryLayout.ofPadding(32), PathElement.sequenceElement(), PathElement.groupElement("value"));
    - * }
    - * - * That is, the above declaration is identical to the following, more verbose one: - *
    {@code
    -MemoryLayout newSeq = MemoryLayout.ofSequence(5,
    -    MemoryLayout.ofStruct(
    -        MemoryLayout.ofPaddingBits(32),
    -        MemoryLayout.ofPaddingBits(32)
    -));
    +long valueOffset = taggedValues.bitOffset(PathElement.sequenceElement(0),
    +                                          PathElement.groupElement("value")); // yields 32
      * }
    * * Similarly, we can select the member layout named {@code value}, as follows: *
    {@code
    -MemoryLayout value = seq.select(PathElement.sequenceElement(), PathElement.groupElement("value"));
    +MemoryLayout value = taggedValues.select(PathElement.sequenceElement(),
    +                                         PathElement.groupElement("value"));
      * }
    * * And, we can also replace the layout named {@code value} with another layout, as follows: *
    {@code
    -MemoryLayout newSeq = seq.map(l -> MemoryLayout.ofPadding(32), PathElement.sequenceElement(), PathElement.groupElement("value"));
    +MemoryLayout taggedValuesWithHole = taggedValues.map(l -> MemoryLayout.ofPadding(32),
    +                                            PathElement.sequenceElement(), PathElement.groupElement("value"));
      * }
    * * That is, the above declaration is identical to the following, more verbose one: *
    {@code
    -MemoryLayout newSeq = MemoryLayout.ofSequence(5,
    +MemoryLayout taggedValuesWithHole = MemoryLayout.ofSequence(5,
         MemoryLayout.ofStruct(
    +        MemoryLayout.ofValueBits(8, ByteOrder.NATIVE_ORDER).withName("kind").
             MemoryLayout.ofPaddingBits(32),
             MemoryLayout.ofPaddingBits(32)
     ));
    @@ -161,11 +159,14 @@
      * This is important when obtaining memory access var handle from layouts, as in the following code:
      *
      * 
    {@code
    -VarHandle valueHandle = seq.map(int.class, PathElement.sequenceElement(), PathElement.groupElement("value"));
    +VarHandle valueHandle = taggedValues.varHandle(int.class,
    +                                               PathElement.sequenceElement(),
    +                                               PathElement.groupElement("value"));
      * }
    * - * Since the layout path {@code seq} constructed in the above example features exactly one free dimension, - * it follows that the memory access var handle {@code valueHandle} will feature an extra {@code long} + * Since the layout path constructed in the above example features exactly one free dimension (as it doesn't specify + * which member layout named {@code value} should be selected from the enclosing sequence layout), + * it follows that the memory access var handle {@code valueHandle} will feature an additional {@code long} * access coordinate. * *

    Layout attributes

    @@ -180,7 +181,7 @@ * explicitly permitted types. * * @implSpec - * Implementations of this class are immutable and thread-safe. + * Implementations of this interface are immutable, thread-safe and value-based. */ public interface MemoryLayout extends Constable { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java index d15ade978f7..239d14b8f5e 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java @@ -44,7 +44,7 @@ /** * A memory segment models a contiguous region of memory. A memory segment is associated with both spatial * and temporal bounds. Spatial bounds ensure that memory access operations on a memory segment cannot affect a memory location - * which falls outside the boundaries of the memory segment being accessed. Temporal checks ensure that memory access + * which falls outside the boundaries of the memory segment being accessed. Temporal bounds ensure that memory access * operations on a segment cannot occur after a memory segment has been closed (see {@link MemorySegment#close()}). *

    * All implementations of this interface must be value-based; @@ -76,12 +76,22 @@ * Finally, it is also possible to obtain a memory segment backed by a memory-mapped file using the factory method * {@link MemorySegment#mapFromPath(Path, long, long, FileChannel.MapMode)}. Such memory segments are called mapped memory segments * (see {@link MappedMemorySegment}). + *

    + * Array and buffer segments are effectively views over existing memory regions which might outlive the + * lifecycle of the segments derived from them, and can even be manipulated directly (e.g. via array access, or direct use + * of the {@link ByteBuffer} API) by other clients. As a result, while sharing array or buffer segments is possible, + * it is strongly advised that clients wishing to do so take extra precautions to make sure that the underlying memory sources + * associated with such segments remain inaccessible, and that said memory sources are never aliased by more than one segment + * at a time - e.g. so as to prevent concurrent modifications of the contents of an array, or buffer segment. * *

    Closing a memory segment

    * - * Memory segments are closed explicitly (see {@link MemorySegment#close()}). In general when a segment is closed, all off-heap - * resources associated with it are released; this has different meanings depending on the kind of memory segment being - * considered: + * Memory segments are closed explicitly (see {@link MemorySegment#close()}). When a segment is closed, it is no longer + * alive (see {@link #isAlive()}, and subsequent operation on the segment (or on any {@link MemoryAddress} instance + * derived from it) will fail with {@link IllegalStateException}. + *

    + * Closing a segment might trigger the releasing of the underlying memory resources associated with said segment, depending on + * the kind of memory segment being considered: *

      *
    • closing a native memory segment results in freeing the native memory associated with it
    • *
    • closing a mapped memory segment results in the backing memory-mapped file to be unmapped
    • @@ -92,32 +102,6 @@ * objects. *
    * - *

    Thread confinement

    - * - * Memory segments support strong thread-confinement guarantees. Upon creation, they are assigned an owner thread, - * typically the thread which initiated the creation operation. After creation, only the owner thread will be allowed - * to directly manipulate the memory segment (e.g. close the memory segment) or access the underlying memory associated with - * the segment using a memory access var handle. Any attempt to perform such operations from a thread other than the - * owner thread will result in a runtime failure. - *

    - * Memory segments support serial thread confinement; that is, ownership of a memory segment can change (see - * {@link #withOwnerThread(Thread)}). This allows, for instance, for two threads {@code A} and {@code B} to share - * a segment in a controlled, cooperative and race-free fashion. - *

    - * In some cases, it might be useful for multiple threads to process the contents of the same memory segment concurrently - * (e.g. in the case of parallel processing); while memory segments provide strong confinement guarantees, it is possible - * to obtain a {@link Spliterator} from a segment, which can be used to slice the segment and allow multiple thread to - * work in parallel on disjoint segment slices (this assumes that the access mode {@link #ACQUIRE} is set). - * For instance, the following code can be used to sum all int values in a memory segment in parallel: - *

    {@code
    -MemorySegment segment = ...
    -SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.ofSequence(1024, MemoryLayouts.JAVA_INT);
    -VarHandle VH_int = SEQUENCE_LAYOUT.elementLayout().varHandle(int.class);
    -int sum = StreamSupport.stream(MemorySegment.spliterator(segment, SEQUENCE_LAYOUT), true)
    -            .mapToInt(s -> (int)VH_int.get(s.baseAddress()))
    -            .sum();
    - * }
    - * *

    Access modes

    * * Memory segments supports zero or more access modes. Supported access modes are {@link #READ}, @@ -152,12 +136,38 @@ * {@link ByteBuffer} API, but need to operate on large memory segments. Byte buffers obtained in such a way support * the same spatial and temporal access restrictions associated to the memory segment from which they originated. * + *

    Thread confinement

    + * + * Memory segments support strong thread-confinement guarantees. Upon creation, they are assigned an owner thread, + * typically the thread which initiated the creation operation. After creation, only the owner thread will be allowed + * to directly manipulate the memory segment (e.g. close the memory segment) or access the underlying memory associated with + * the segment using a memory access var handle. Any attempt to perform such operations from a thread other than the + * owner thread will result in a runtime failure. + *

    + * Memory segments support serial thread confinement; that is, ownership of a memory segment can change (see + * {@link #withOwnerThread(Thread)}). This allows, for instance, for two threads {@code A} and {@code B} to share + * a segment in a controlled, cooperative and race-free fashion. + *

    + * In some cases, it might be useful for multiple threads to process the contents of the same memory segment concurrently + * (e.g. in the case of parallel processing); while memory segments provide strong confinement guarantees, it is possible + * to obtain a {@link Spliterator} from a segment, which can be used to slice the segment and allow multiple thread to + * work in parallel on disjoint segment slices (this assumes that the access mode {@link #ACQUIRE} is set). + * For instance, the following code can be used to sum all int values in a memory segment in parallel: + *

    {@code
    +MemorySegment segment = ...
    +SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.ofSequence(1024, MemoryLayouts.JAVA_INT);
    +VarHandle VH_int = SEQUENCE_LAYOUT.elementLayout().varHandle(int.class);
    +int sum = StreamSupport.stream(MemorySegment.spliterator(segment, SEQUENCE_LAYOUT), true)
    +                       .mapToInt(s -> (int)VH_int.get(s.baseAddress()))
    +                       .sum();
    + * }
    + * * @apiNote In the future, if the Java language permits, {@link MemorySegment} * may become a {@code sealed} interface, which would prohibit subclassing except by * {@link MappedMemorySegment} and other explicitly permitted subtypes. * * @implSpec - * Implementations of this interface are immutable and thread-safe. + * Implementations of this interface are immutable, thread-safe and value-based. */ public interface MemorySegment extends AutoCloseable { @@ -276,8 +286,8 @@ static Spliterator spliterator(S segment, SequenceL /** * Closes this memory segment. Once a memory segment has been closed, any attempt to use the memory segment, - * or to access the memory associated with the segment will fail with {@link IllegalStateException}. Depending on - * the kind of memory segment being closed, calling this method further trigger deallocation of all the resources + * or to access any {@link MemoryAddress} instance associated with it will fail with {@link IllegalStateException}. + * Depending on the kind of memory segment being closed, calling this method further triggers deallocation of all the resources * associated with the memory segment. * @throws IllegalStateException if this segment is not alive, or if access occurs from a thread other than the * thread owning this segment, or if the segment cannot be closed because it is being operated upon by a different @@ -610,8 +620,8 @@ static MemorySegment allocateNative(long bytesSize, long alignmentBytes) { * (often as a plain {@code long} value). The segment will feature all access modes * (see {@link #ALL_ACCESS}). *

    - * This method is restricted. Restricted method are unsafe, and, if used incorrectly, their use might crash - * the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * This method is restricted. Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on * restricted methods, and use safe and supported functionalities, where possible. * * @param addr the desired base address diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java index 33990e517b0..1d8408db2e5 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java @@ -25,21 +25,34 @@ */ /** - *

    Classes to support low-level, safe and efficient memory access. For example: + *

    Classes to support low-level, safe and efficient memory access. + *

    + * The key abstractions introduced by this package are {@link jdk.incubator.foreign.MemorySegment} and {@link jdk.incubator.foreign.MemoryAddress}. + * The first models a contiguous memory region, which can reside either inside or outside the Java heap; the latter models an address - which can + * sometimes be expressed as an offset into a given segment. A memory address represents the main access coordinate of a memory access var handle, which can be obtained + * using the combinator methods defined in the {@link jdk.incubator.foreign.MemoryHandles} class. Finally, the {@link jdk.incubator.foreign.MemoryLayout} class + * hierarchy enables description of memory layouts and basic operations such as computing the size in bytes of a given + * layout, obtain its alignment requirements, and so on. Memory layouts also provide an alternate, more abstract way, to produce + * memory access var handles, e.g. using layout paths. + * + * For example, to allocate an off-heap memory region big enough to hold 10 values of the primitive type {@code int}, and fill it with values + * ranging from {@code 0} to {@code 9}, we can use the following code: * *

    {@code
    -static final VarHandle intHandle = MemoryHandles.varHandle(int.class, ByteOrder.BIG_ENDIAN);
    +static final VarHandle intHandle = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder());
     
     try (MemorySegment segment = MemorySegment.allocateNative(10 * 4)) {
    -   MemoryAddress base = segment.baseAddress();
    -   for (long i = 0 ; i < 10 ; i++) {
    -     intHandle.set(base.addOffset(i * 4), (int)i);
    -   }
    - }
    +    MemoryAddress base = segment.baseAddress();
    +    for (long i = 0 ; i < 10 ; i++) {
    +       intHandle.set(base.addOffset(i * 4), (int)i);
    +    }
    +}
      * }
    * * Here we create a var handle, namely {@code intHandle}, to manipulate values of the primitive type {@code int}, at - * a given memory location. We then create a native memory segment, that is, a memory segment backed by + * a given memory location. Also, {@code intHandle} is stored in a {@code static} and {@code final} field, to achieve + * better performance and allow for inlining of the memory access operation through the {@link java.lang.invoke.VarHandle} + * instance. We then create a native memory segment, that is, a memory segment backed by * off-heap memory; the size of the segment is 40 bytes, enough to store 10 values of the primitive type {@code int}. * The segment is created inside a try-with-resources construct: this idiom ensures that all the memory resources * associated with the segment will be released at the end of the block, according to the semantics described in @@ -48,15 +61,6 @@ * {@code s[i]}, where {@code 0 <= i < 10}, where the size of each slot is exactly 4 bytes, the initialization logic above will set each slot * so that {@code s[i] = i}, again where {@code 0 <= i < 10}. * - *

    - * The key abstractions introduced by this package are {@link jdk.incubator.foreign.MemorySegment} and {@link jdk.incubator.foreign.MemoryAddress}. - * The first models a contiguous memory region, which can reside either inside or outside the Java heap; the latter models an address - which can - * sometimes be expressed as an offset into a given segment. A memory address represents the main access coordinate of a memory access var handle, which can be obtained - * using the combinator methods defined in the {@link jdk.incubator.foreign.MemoryHandles} class. Finally, the {@link jdk.incubator.foreign.MemoryLayout} class - * hierarchy enables description of memory layouts and basic operations such as computing the size in bytes of a given - * layout, obtain its alignment requirements, and so on. Memory layouts also provide an alternate, more abstract way, to produce - * memory access var handles, e.g. using layout paths. - * *

    Deterministic deallocation

    * * When writing code that manipulates memory segments, especially if backed by memory which resides outside the Java heap, it is diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index 2bfe7926e8d..9c45b02e5c2 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -149,14 +149,19 @@ public long mismatch(MemorySegment other) { long i = 0; if (length > 7) { - i = ArraysSupport.vectorizedMismatchLarge( + if ((byte) BYTE_HANDLE.get(this.baseAddress(), 0) != (byte) BYTE_HANDLE.get(that.baseAddress(), 0)) { + return 0; + } + i = ArraysSupport.vectorizedMismatchLargeForBytes( this.base(), this.min(), that.base(), that.min(), - length, ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE); + length); if (i >= 0) { return i; } - i = length - ~i; + long remaining = ~i; + assert remaining < 8 : "remaining greater than 7: " + remaining; + i = length - remaining; } MemoryAddress thisAddress = this.baseAddress(); MemoryAddress thatAddress = that.baseAddress(); diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java index 4430eb53920..feed358562d 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryAddressImpl.java @@ -54,17 +54,6 @@ public MemoryAddressImpl(AbstractMemorySegmentImpl segment, long offset) { this.offset = offset; } - public static void copy(MemoryAddressImpl src, MemoryAddressImpl dst, long size) { - src.checkAccess(0, size, true); - dst.checkAccess(0, size, false); - //check disjoint - long offsetSrc = src.unsafeGetOffset(); - long offsetDst = dst.unsafeGetOffset(); - Object baseSrc = src.unsafeGetBase(); - Object baseDst = dst.unsafeGetBase(); - UNSAFE.copyMemory(baseSrc, offsetSrc, baseDst, offsetDst, size); - } - // MemoryAddress methods @Override diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/LauncherData.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/LauncherData.java index 9667e406bb2..752509444a9 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/LauncherData.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/LauncherData.java @@ -26,7 +26,9 @@ import java.io.File; import java.io.IOException; +import java.io.Reader; import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleReference; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; @@ -34,7 +36,9 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.Properties; import java.util.Set; import java.util.function.Supplier; import java.util.jar.Attributes; @@ -42,13 +46,14 @@ import java.util.jar.Manifest; import java.util.stream.Collectors; import java.util.stream.Stream; +import static jdk.incubator.jpackage.internal.StandardBundlerParam.PREDEFINED_RUNTIME_IMAGE; /** * Extracts data needed to run application from parameters. */ final class LauncherData { boolean isModular() { - return moduleDescriptor != null; + return moduleInfo != null; } String qualifiedClassName() { @@ -65,7 +70,7 @@ String packageName() { String moduleName() { verifyIsModular(true); - return moduleDescriptor.name(); + return moduleInfo.name; } List modulePath() { @@ -84,11 +89,7 @@ List classPath() { String getAppVersion() { if (isModular()) { - ModuleDescriptor.Version ver = moduleDescriptor.version().orElse(null); - if (ver != null) { - return ver.toString(); - } - return moduleDescriptor.rawVersion().orElse(null); + return moduleInfo.version; } return null; @@ -98,7 +99,7 @@ private LauncherData() { } private void verifyIsModular(boolean isModular) { - if ((moduleDescriptor != null) != isModular) { + if ((moduleInfo != null) != isModular) { throw new IllegalStateException(); } } @@ -107,9 +108,19 @@ static LauncherData create(Map params) throws ConfigException, IOException { final String mainModule = getMainModule(params); + final LauncherData result; if (mainModule == null) { - return createNonModular(params); + result = createNonModular(params); + } else { + result = createModular(mainModule, params); } + result.initClasspath(params); + return result; + } + + private static LauncherData createModular(String mainModule, + Map params) throws ConfigException, + IOException { LauncherData launcherData = new LauncherData(); @@ -123,18 +134,34 @@ static LauncherData create(Map params) throws } launcherData.modulePath = getModulePath(params); - launcherData.moduleDescriptor = JLinkBundlerHelper.createModuleFinder( - launcherData.modulePath).find(moduleName).orElseThrow( - () -> new ConfigException(MessageFormat.format(I18N.getString( - "error.no-module-in-path"), moduleName), null)).descriptor(); + // Try to find module in the specified module path list. + ModuleReference moduleRef = JLinkBundlerHelper.createModuleFinder( + launcherData.modulePath).find(moduleName).orElse(null); + + if (moduleRef != null) { + launcherData.moduleInfo = ModuleInfo.fromModuleDescriptor( + moduleRef.descriptor()); + } else if (params.containsKey(PREDEFINED_RUNTIME_IMAGE.getID())) { + // Failed to find module in the specified module path list and + // there is external runtime given to jpackage. + // Lookup module in this runtime. + Path cookedRuntime = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params).toPath(); + launcherData.moduleInfo = ModuleInfo.fromCookedRuntime(moduleName, + cookedRuntime); + } + + if (launcherData.moduleInfo == null) { + throw new ConfigException(MessageFormat.format(I18N.getString( + "error.no-module-in-path"), moduleName), null); + } if (launcherData.qualifiedClassName == null) { - launcherData.qualifiedClassName = launcherData.moduleDescriptor.mainClass().orElseThrow( - () -> new ConfigException(I18N.getString("ERR_NoMainClass"), - null)); + launcherData.qualifiedClassName = launcherData.moduleInfo.mainClass; + if (launcherData.qualifiedClassName == null) { + throw new ConfigException(I18N.getString("ERR_NoMainClass"), null); + } } - launcherData.initClasspath(params); return launcherData; } @@ -195,7 +222,6 @@ private static LauncherData createNonModular( launcherData.mainJarName)); } - launcherData.initClasspath(params); return launcherData; } @@ -263,8 +289,17 @@ private static Path getPathParam(Map params, private static List getModulePath(Map params) throws ConfigException { - return getPathListParameter(Arguments.CLIOptions.MODULE_PATH.getId(), - params); + List modulePath = getPathListParameter(Arguments.CLIOptions.MODULE_PATH.getId(), params); + + if (params.containsKey(PREDEFINED_RUNTIME_IMAGE.getID())) { + Path runtimePath = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params).toPath(); + runtimePath = runtimePath.resolve("lib"); + modulePath = Stream.of(modulePath, List.of(runtimePath)) + .flatMap(List::stream) + .collect(Collectors.toUnmodifiableList()); + } + + return modulePath; } private static List getPathListParameter(String paramName, @@ -281,5 +316,77 @@ private static List getPathListParameter(String paramName, private Path mainJarName; private List classPath; private List modulePath; - private ModuleDescriptor moduleDescriptor; + private ModuleInfo moduleInfo; + + private static final class ModuleInfo { + String name; + String version; + String mainClass; + + static ModuleInfo fromModuleDescriptor(ModuleDescriptor md) { + ModuleInfo result = new ModuleInfo(); + result.name = md.name(); + result.mainClass = md.mainClass().orElse(null); + + ModuleDescriptor.Version ver = md.version().orElse(null); + if (ver != null) { + result.version = ver.toString(); + } else { + result.version = md.rawVersion().orElse(null); + } + + return result; + } + + static ModuleInfo fromCookedRuntime(String moduleName, + Path cookedRuntime) { + Objects.requireNonNull(moduleName); + + // We can't extract info about version and main class of a module + // linked in external runtime without running ModuleFinder in that + // runtime. But this is too much work as the runtime might have been + // coocked without native launchers. So just make sure the module + // is linked in the runtime by simply analysing the data + // of `release` file. + + final Path releaseFile; + if (!Platform.isMac()) { + releaseFile = cookedRuntime.resolve("release"); + } else { + // On Mac `cookedRuntime` can be runtime root or runtime home. + Path runtimeHome = cookedRuntime.resolve("Contents/Home"); + if (!Files.isDirectory(runtimeHome)) { + runtimeHome = cookedRuntime; + } + releaseFile = runtimeHome.resolve("release"); + } + + try (Reader reader = Files.newBufferedReader(releaseFile)) { + Properties props = new Properties(); + props.load(reader); + String moduleList = props.getProperty("MODULES"); + if (moduleList == null) { + return null; + } + + if ((moduleList.startsWith("\"") && moduleList.endsWith("\"")) + || (moduleList.startsWith("\'") && moduleList.endsWith( + "\'"))) { + moduleList = moduleList.substring(1, moduleList.length() - 1); + } + + if (!List.of(moduleList.split("\\s+")).contains(moduleName)) { + return null; + } + } catch (IOException|IllegalArgumentException ex) { + Log.verbose(ex); + return null; + } + + ModuleInfo result = new ModuleInfo(); + result.name = moduleName; + + return result; + } + } } diff --git a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java index 7d9f8bd8f38..7a1791d7209 100644 --- a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java +++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java @@ -305,13 +305,16 @@ private void prepareProto(Map params) // Ignore custom icon if any as we don't want to copy anything in // Java Runtime image. installerIcon = ApplicationLayout.javaRuntime() + .resolveAt(appDir.toPath()) .runtimeDirectory() .resolve(Path.of("bin", "java.exe")); } else { installerIcon = ApplicationLayout.windowsAppImage() + .resolveAt(appDir.toPath()) .launchersDirectory() .resolve(APP_NAME.fetchFrom(params) + ".exe"); } + installerIcon = installerIcon.toAbsolutePath(); params.put(WIN_APP_IMAGE.getID(), appDir); @@ -459,6 +462,8 @@ private File buildMSI(Map params, boolean enableLicenseUI = (LICENSE_FILE.fetchFrom(params) != null); boolean enableInstalldirUI = INSTALLDIR_CHOOSER.fetchFrom(params); + wixPipeline.addLightOptions("-sice:ICE27"); + if (!MSI_SYSTEM_WIDE.fetchFrom(params)) { wixPipeline.addLightOptions("-sice:ICE91"); } diff --git a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/main.wxs b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/main.wxs index 63e32d47030..b7b65d7b61b 100644 --- a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/main.wxs +++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/main.wxs @@ -12,6 +12,17 @@ + + + + + + + + + + + - - - - - + + + + - - - - - - - - + - - - - - + @@ -87,8 +80,10 @@ + - + + @@ -140,9 +135,14 @@ Not Installed - - Not Installed + + JP_UPGRADABLE_FOUND + + JP_DOWNGRADABLE_FOUND + + + diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java index 3c9166408b2..609204ebcd6 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java @@ -772,6 +772,11 @@ HotSpotResolvedObjectTypeImpl getResolvedJavaType(long displacement, boolean com */ native void ensureInitialized(HotSpotResolvedObjectTypeImpl type); + /** + * Forces linking of {@code type}. + */ + native void ensureLinked(HotSpotResolvedObjectTypeImpl type); + /** * Checks if {@code object} is a String and is an interned string value. */ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java index ae8dcbc259a..99fd3016f98 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java @@ -146,6 +146,18 @@ private boolean checkArgs(Object... args) { return true; } + /** + * {@inheritDoc} + * + * It's possible for the HotSpot runtime to sweep nmethods at any point in time. As a result, + * there is no guarantee that calling this method will execute the wrapped nmethod. Instead, it + * may end up executing the bytecode of the associated {@link #getMethod() Java method}. Only if + * {@link #isValid()} is {@code true} after returning can the caller be sure that the nmethod + * was executed. If {@link #isValid()} is {@code false}, then the only way to determine if the + * nmethod was executed is to test for some side-effect specific to the nmethod (e.g., update to + * a field) that is not performed by the bytecode of the associated {@link #getMethod() Java + * method}. + */ @Override public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { if (IS_IN_NATIVE_IMAGE) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java index b1139f9e42f..4c6c647f264 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java @@ -65,25 +65,21 @@ public HotSpotResolvedObjectType getType() { @Override public abstract int getIdentityHashCode(); - static class Fields { - // Initializing these too early causes a hang, so do it here in a subclass - static final HotSpotResolvedJavaField callSiteTargetField = HotSpotMethodHandleAccessProvider.Internals.instance().callSiteTargetField; - static final HotSpotResolvedJavaField constantCallSiteFrozenField = HotSpotMethodHandleAccessProvider.Internals.instance().constantCallSiteFrozenField; - } - private boolean isFullyInitializedConstantCallSite() { if (!runtime().getConstantCallSite().isInstance(this)) { return false; } // read ConstantCallSite.isFrozen as a volatile field - boolean isFrozen = readFieldValue(Fields.constantCallSiteFrozenField, true /* volatile */).asBoolean(); + HotSpotResolvedJavaField field = HotSpotMethodHandleAccessProvider.Internals.instance().constantCallSiteFrozenField; + boolean isFrozen = readFieldValue(field, true /* volatile */).asBoolean(); // isFrozen true implies fully-initialized return isFrozen; } private HotSpotObjectConstantImpl readTarget() { // read CallSite.target as a volatile field - return (HotSpotObjectConstantImpl) readFieldValue(Fields.callSiteTargetField, true /* volatile */); + HotSpotResolvedJavaField field = HotSpotMethodHandleAccessProvider.Internals.instance().callSiteTargetField; + return (HotSpotObjectConstantImpl) readFieldValue(field, true /* volatile */); } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 3a9f9daabc7..aa7cd43aa6a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -373,6 +373,27 @@ public boolean isLinked() { return isArray() ? true : getInitState() >= config().instanceKlassStateLinked; } + @Override + public void link() { + if (!isLinked()) { + runtime().compilerToVm.ensureLinked(this); + } + } + + @Override + public boolean hasDefaultMethods() { + HotSpotVMConfig config = config(); + int miscFlags = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassMiscFlagsOffset); + return (miscFlags & config.jvmMiscFlagsHasDefaultMethods) != 0; + } + + @Override + public boolean declaresDefaultMethods() { + HotSpotVMConfig config = config(); + int miscFlags = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassMiscFlagsOffset); + return (miscFlags & config.jvmMiscFlagsDeclaresDefaultMethods) != 0; + } + /** * Returns the value of the state field {@code InstanceKlass::_init_state} of the metaspace * klass. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java index af3dfdace5b..c71aa16a940 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java @@ -250,6 +250,20 @@ public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { public void initialize() { } + @Override + public void link() { + } + + @Override + public boolean hasDefaultMethods() { + return false; + } + + @Override + public boolean declaresDefaultMethods() { + return false; + } + @Override public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedType) { return null; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index dba5e3331c1..0aff9e740a3 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -137,6 +137,9 @@ String getHostArchitectureName() { final int jvmAccEnum = getConstant("JVM_ACC_ENUM", Integer.class); final int jvmAccInterface = getConstant("JVM_ACC_INTERFACE", Integer.class); + final int jvmMiscFlagsHasDefaultMethods = getConstant("InstanceKlass::_misc_has_nonstatic_concrete_methods", Integer.class); + final int jvmMiscFlagsDeclaresDefaultMethods = getConstant("InstanceKlass::_misc_declares_nonstatic_concrete_methods", Integer.class); + // This is only valid on AMD64. final int runtimeCallStackSize = getConstant("frame::arg_reg_save_area_bytes", Integer.class, osArch.equals("amd64") ? null : 0); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java index f4b30368937..772e4da7699 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java @@ -105,6 +105,30 @@ default boolean isLeaf() { */ boolean isLinked(); + /** + * Links this type. If this method returns normally, then future calls of {@link #isLinked} will + * return true and future calls of {@link #link} are no-ops. If the method throws an exception, + * then future calls of {@link #isLinked} will return false and future calls of {@link #link} + * will reattempt the linking step which might succeed or throw an exception. + */ + default void link() { + throw new UnsupportedOperationException("link is unsupported"); + } + + /** + * Checks whether this type or any of its supertypes or superinterfaces has default methods. + */ + default boolean hasDefaultMethods() { + throw new UnsupportedOperationException("hasDefaultMethods is unsupported"); + } + + /** + * Checks whether this type declares defaults methods. + */ + default boolean declaresDefaultMethods() { + throw new UnsupportedOperationException("declaresDefaultMethods is unsupported"); + } + /** * Determines if this type is either the same as, or is a superclass or superinterface of, the * type represented by the specified parameter. This method is identical to @@ -308,13 +332,15 @@ default ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, Reso /** * Returns an array reflecting all the constructors declared by this type. This method is - * similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors. + * similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors. Calling + * this method forces this type to be {@link #link linked}. */ ResolvedJavaMethod[] getDeclaredConstructors(); /** * Returns an array reflecting all the methods declared by this type. This method is similar to - * {@link Class#getDeclaredMethods()} in terms of returned methods. + * {@link Class#getDeclaredMethods()} in terms of returned methods. Calling this method forces + * this type to be {@link #link linked}. */ ResolvedJavaMethod[] getDeclaredMethods(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LateMembarInsertionTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LateMembarInsertionTest.java index 591de0a36cf..c1d361b2395 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LateMembarInsertionTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LateMembarInsertionTest.java @@ -195,45 +195,6 @@ public void test08() { verifyMembars("volatileFieldStore", membarsExpected()); } - // Unused field load should be optimized out and leave no barrier behind - @SuppressWarnings("unused") - public static void volatileFieldStoreUnusedVolatileFieldLoadVolatileFieldStore(int v2) { - VolatileAccess2.field = v2; - int v1 = VolatileAccess.field; - VolatileAccess2.field = v2; - } - - @Test - public void test09() { - StructuredGraph graph = getFinalGraph(getResolvedJavaMethod("volatileFieldStoreUnusedVolatileFieldLoadVolatileFieldStore")); - List accesses = getAccesses(graph); - - Assert.assertEquals(accesses.size(), 2); - Assert.assertEquals(accesses.get(0).getType(), volatileAccess2Type); - Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type); - Assert.assertTrue(accesses.get(0).isWrite()); - Assert.assertTrue(accesses.get(1).isWrite()); - Assert.assertEquals(membarsExpected() ? 4 : 0, getMembars(graph).size()); - } - - // Unused field load should be optimized out and leave no barrier behind - @SuppressWarnings("unused") - public static void unusedVolatileFieldLoadVolatileFieldStore(int v2) { - int v1 = VolatileAccess.field; - VolatileAccess2.field = v2; - } - - @Test - public void test10() { - StructuredGraph graph = getFinalGraph(getResolvedJavaMethod("unusedVolatileFieldLoadVolatileFieldStore")); - List accesses = getAccesses(graph); - - Assert.assertEquals(accesses.size(), 1); - Assert.assertEquals(accesses.get(0).getType(), volatileAccess2Type); - Assert.assertTrue(accesses.get(0).isWrite()); - Assert.assertEquals(membarsExpected() ? 2 : 0, getMembars(graph).size()); - } - public static int unsafeVolatileFieldLoad(Object o, long offset) { return UNSAFE.getIntVolatile(o, offset); } @@ -346,11 +307,4 @@ private ResolvedJavaType classForAccess(FixedAccessNode n) { return javaType; } - private static List getMembars(StructuredGraph graph) { - StructuredGraph.ScheduleResult schedule = graph.getLastSchedule(); - ControlFlowGraph cfg = schedule.getCFG(); - Block[] blocks = cfg.getBlocks(); - - return Arrays.stream(blocks).flatMap(b -> schedule.nodesFor(b).stream()).filter(n -> n instanceof MembarNode).collect(Collectors.toList()); - } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VolatileReadEliminateWrongMemoryStateTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VolatileReadEliminateWrongMemoryStateTest.java new file mode 100644 index 00000000000..6e9ed0edb28 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VolatileReadEliminateWrongMemoryStateTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.core.test; + +import org.junit.Test; + +// See https://bugs.openjdk.java.net/browse/JDK-8247832 +public class VolatileReadEliminateWrongMemoryStateTest extends GraalCompilerTest { + + private static volatile int volatileField; + private static int field; + + @SuppressWarnings("unused") + public static int testMethod() { + field = 0; + int v = volatileField; + field += 1; + v = volatileField; + field += 1; + return field; + } + + @Test + public void test1() { + test("testMethod"); + } + + public static void testMethod2(Object obj) { + synchronized (obj) { + volatileField++; + } + } + + @Test + public void test2() { + test("testMethod2", new Object()); + } +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/VolatileReadNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/VolatileReadNode.java index e42e59f7e1e..8e520804a86 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/VolatileReadNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/VolatileReadNode.java @@ -33,8 +33,6 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.spi.Simplifiable; -import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.memory.address.AddressNode; @@ -43,20 +41,11 @@ import jdk.internal.vm.compiler.word.LocationIdentity; @NodeInfo(nameTemplate = "VolatileRead#{p#location/s}", allowedUsageTypes = Memory, cycles = CYCLES_2, size = SIZE_1) -public class VolatileReadNode extends ReadNode implements SingleMemoryKill, Lowerable, Simplifiable { +public class VolatileReadNode extends ReadNode implements SingleMemoryKill, Lowerable { public static final NodeClass TYPE = NodeClass.create(VolatileReadNode.class); - public VolatileReadNode(AddressNode address, LocationIdentity location, Stamp stamp, BarrierType barrierType) { - super(TYPE, address, location, stamp, null, barrierType, false, null); - } - - @Override - public void simplify(SimplifierTool tool) { - if (lastLocationAccess != null && hasOnlyUsagesOfType(Memory)) { - replaceAtUsages(lastLocationAccess.asNode(), Memory); - assert hasNoUsages(); - graph().removeFixed(this); - } + public VolatileReadNode(AddressNode address, Stamp stamp, BarrierType barrierType) { + super(TYPE, address, LocationIdentity.any(), stamp, null, barrierType, false, null); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java index b4c784ca4d2..c2b56e0fc07 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java @@ -475,7 +475,7 @@ protected void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) { ReadNode memoryRead = null; BarrierType barrierType = barrierSet.fieldLoadBarrierType(field, getStorageKind(field)); if (loadField.isVolatile()) { - memoryRead = graph.add(new VolatileReadNode(address, fieldLocationIdentity(field), loadStamp, barrierType)); + memoryRead = graph.add(new VolatileReadNode(address, loadStamp, barrierType)); } else { memoryRead = graph.add(new ReadNode(address, fieldLocationIdentity(field), loadStamp, barrierType)); } @@ -767,7 +767,7 @@ protected ReadNode createUnsafeRead(StructuredGraph graph, RawLoadNode load, Gua AddressNode address = createUnsafeAddress(graph, load.object(), load.offset()); ReadNode memoryRead = null; if (load.isVolatile()) { - memoryRead = new VolatileReadNode(address, load.getLocationIdentity(), loadStamp, barrierSet.readBarrierType(load)); + memoryRead = new VolatileReadNode(address, loadStamp, barrierSet.readBarrierType(load)); } else { memoryRead = new ReadNode(address, load.getLocationIdentity(), loadStamp, barrierSet.readBarrierType(load)); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/Versions.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/Versions.java index 9d08ee670f6..a44a22931f1 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/Versions.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/Versions.java @@ -26,6 +26,7 @@ package jdk.javadoc.internal; import java.util.ResourceBundle; +import java.util.stream.Collectors; import static java.util.ResourceBundle.getBundle; @@ -77,15 +78,18 @@ public static Runtime.Version javadocVersion() throws RuntimeException { /** * Returns a short string representation of the provided version. * - *

    Examples of strings returned from this method are: "15" and - * "15-internal". + *

    The string contains the dotted representation of the version number, + * followed by the prerelease info, if any. + * For example, "15", "15.1", "15.0.1", "15-internal". * * @return a short string representation of the provided version * * @throws NullPointerException if {@code v == null} */ public static String shortVersionStringOf(Runtime.Version v) { - String svstr = String.valueOf(v.feature()); + String svstr = v.version().stream() + .map(Object::toString) + .collect(Collectors.joining(".")); if (v.pre().isPresent()) { svstr += "-" + v.pre().get(); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java index a055d21daa8..743c72b1826 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java @@ -159,11 +159,6 @@ public Runtime.Version getDocletVersion() { return docletVersion; } - @Override - public String getDocletVersionString() { - return Versions.shortVersionStringOf(docletVersion); - } - @Override public Resources getDocResources() { return docResources; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 26999451093..453341e6e76 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -431,7 +431,7 @@ public void printHtmlDocument(List metakeywords, Content htmlComment = contents.newPage; List additionalStylesheets = configuration.getAdditionalStylesheets(); additionalStylesheets.addAll(localStylesheets); - Head head = new Head(path, configuration.getDocletVersionString(), configuration.startTime) + Head head = new Head(path, configuration.getDocletVersion(), configuration.startTime) .setTimestamp(!options.noTimestamp()) .setDescription(description) .setGenerator(getGenerator(getClass())) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java index e9ace055240..99db81bcc59 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java @@ -75,7 +75,7 @@ private IndexRedirectWriter(HtmlConfiguration configuration, DocPath filename, D */ private void generateIndexFile() throws DocFileIOException { Content htmlComment = contents.newPage; - Head head = new Head(path, configuration.getDocletVersionString(), configuration.startTime) + Head head = new Head(path, configuration.getDocletVersion(), configuration.startTime) .setTimestamp(!options.noTimestamp()) .setDescription("index redirect") .setGenerator(getGenerator(getClass())) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java index f1c58b93957..f0a13436221 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java @@ -235,7 +235,7 @@ public void convertClass(TypeElement te, DocPath outputdir) * @param path the path for the file. */ private void writeToFile(Content body, DocPath path, TypeElement te) throws DocFileIOException { - Head head = new Head(path, configuration.getDocletVersionString(), configuration.startTime) + Head head = new Head(path, configuration.getDocletVersion(), configuration.startTime) // .setTimestamp(!options.notimestamp) // temporary: compatibility! .setTitle(resources.getText("doclet.Window_Source_title")) // .setCharset(options.charset) // temporary: compatibility! diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java index d4a9f616b23..858de157ccf 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java @@ -49,7 +49,7 @@ * deletion without notice. */ public class Head extends Content { - private final String docletVersion; + private final Runtime.Version docletVersion; private final Date generatedDate; private final DocPath pathToRoot; private String title; @@ -74,9 +74,9 @@ public class Head extends Content { * recording the time the file was created. * The doclet version should also be provided for recording in the file. * @param path the path for the file that will include this HEAD element - * @param docletVersion a string identifying the doclet version + * @param docletVersion the doclet version */ - public Head(DocPath path, String docletVersion, Date generatedDate) { + public Head(DocPath path, Runtime.Version docletVersion, Date generatedDate) { this.docletVersion = docletVersion; this.generatedDate = generatedDate; pathToRoot = path.parent().invert(); @@ -294,9 +294,8 @@ private Content toContent() { private Comment getGeneratedBy(boolean timestamp, Date now) { String text = "Generated by javadoc"; // marker string, deliberately not localized - text += " (" + docletVersion + ")"; if (timestamp) { - text += " on " + now; + text += " ("+ docletVersion.feature() + ") on " + now; } return new Comment(text); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java index 2f537fc6bc7..f11a03ae871 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java @@ -157,14 +157,6 @@ public abstract class BaseConfiguration { */ public abstract Runtime.Version getDocletVersion(); - /** - * Returns a short string representation of the version returned by - * {@linkplain #getDocletVersion()}. - * - * @return a short string representation of the version - */ - public abstract String getDocletVersionString(); - /** * This method should be defined in all those doclets (configurations), * which want to derive themselves from this BaseConfiguration. This method diff --git a/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options b/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options index 90032747e2b..7fe7487e11a 100644 --- a/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options +++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,95 +131,95 @@ option gc { header "^S0C^" /* Survivor 0 Space Capacity - Current */ data sun.gc.generation.0.space.1.capacity scale K - align center - width 6 + align right + width 11 format "0.0" } column { header "^S1C^" /* Survivor 1 Space Capacity - Current */ data sun.gc.generation.0.space.2.capacity scale K - align center - width 6 + align right + width 11 format "0.0" } column { header "^S0U^" /* Survivor 0 Space Used */ data sun.gc.generation.0.space.1.used scale K - align center - width 6 + align right + width 11 format "0.0" } column { header "^S1U^" /* Survivor 1 Space Used */ data sun.gc.generation.0.space.2.used scale K - align center - width 6 + align right + width 11 format "0.0" } column { header "^EC^" /* Eden Space Capacity - Current */ data sun.gc.generation.0.space.0.capacity - align center + align right scale K - width 8 + width 12 format "0.0" } column { header "^EU^" /* Eden Space Used */ data sun.gc.generation.0.space.0.used - align center + align right scale K - width 8 + width 12 format "0.0" } column { header "^OC^" /* Old Space Capacity - Current */ data sun.gc.generation.1.space.0.capacity - align center + align right scale K - width 10 + width 12 format "0.0" } column { header "^OU^" /* Old Space Used */ data sun.gc.generation.1.space.0.used - align center - width 10 + align right + width 12 scale K format "0.0" } column { header "^MC^" /* Metaspace Capacity - Current */ data sun.gc.metaspace.capacity - align center - width 6 + align right + width 10 scale K format "0.0" } column { - header "^MU^" /* Metaspae Used */ + header "^MU^" /* Metaspace Used */ data sun.gc.metaspace.used - align center - width 6 + align right + width 10 scale K format "0.0" } column { header "^CCSC^" /* Compressed Class Space Capacity - Current */ data sun.gc.compressedclassspace.capacity - align center - width 6 + align right + width 9 scale K format "0.0" } column { header "^CCSU^" /* Compressed Class Space Used */ data sun.gc.compressedclassspace.used - align center - width 6 + align right + width 9 scale K format "0.0" } @@ -231,42 +231,42 @@ option gc { format "0" } column { - header "^YGCT^" /* Young Generation Garbage Collection Time */ + header "^YGCT^" /* Young Generation Collection Time */ data sun.gc.collector.0.time/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" } column { header "^FGC^" /* Full Collections */ data sun.gc.collector.1.invocations - align center + align right width 5 scale raw format "0" } column { - header "^FGCT^" /* Full Garbage Collection Time */ + header "^FGCT^" /* Full Collection Time */ data sun.gc.collector.1.time/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" } column { header "^CGC^" /* Concurrent Collections (STW phase) */ data sun.gc.collector.2.invocations - align center + align right width 5 scale raw format "0" } column { - header "^CGCT^" /* Concurrent Garbage Collection Time (STW phase) */ + header "^CGCT^" /* Concurrent Collection Time (STW phase) */ data sun.gc.collector.2.time/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" } @@ -274,7 +274,7 @@ option gc { header "^GCT^" /* Total Garbage Collection Time */ data (sun.gc.collector.0.time + sun.gc.collector.1.time + sun.gc.collector.2.time)/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" required true @@ -287,7 +287,7 @@ option gccapacity { data sun.gc.generation.0.minCapacity scale K align right - width 8 + width 12 format "0.0" } column { @@ -295,7 +295,7 @@ option gccapacity { data sun.gc.generation.0.maxCapacity scale K align right - width 8 + width 12 format "0.0" } column { @@ -303,7 +303,7 @@ option gccapacity { data sun.gc.generation.0.capacity scale K align right - width 8 + width 12 format "0.0" } column { @@ -311,7 +311,7 @@ option gccapacity { data sun.gc.generation.0.space.1.capacity scale K align right - width 6 + width 11 format "0.0" } column { @@ -319,7 +319,7 @@ option gccapacity { data sun.gc.generation.0.space.2.capacity scale K align right - width 6 + width 11 format "0.0" } column { @@ -327,7 +327,7 @@ option gccapacity { data sun.gc.generation.0.space.0.capacity scale K align right - width 8 + width 12 format "0.0" } column { @@ -335,7 +335,7 @@ option gccapacity { data sun.gc.generation.1.minCapacity scale K align right - width 10 + width 12 format "0.0" } column { @@ -343,7 +343,7 @@ option gccapacity { data sun.gc.generation.1.maxCapacity scale K align right - width 10 + width 12 format "0.0" } column { @@ -351,7 +351,7 @@ option gccapacity { data sun.gc.generation.1.capacity scale K align right - width 10 + width 12 format "0.0" } column { @@ -359,7 +359,7 @@ option gccapacity { data sun.gc.generation.1.space.0.capacity scale K align right - width 10 + width 12 format "0.0" } column { @@ -367,7 +367,7 @@ option gccapacity { data sun.gc.metaspace.minCapacity scale K align right - width 8 + width 10 format "0.0" } column { @@ -375,7 +375,7 @@ option gccapacity { data sun.gc.metaspace.maxCapacity scale K align right - width 8 + width 10 format "0.0" } column { @@ -383,7 +383,7 @@ option gccapacity { data sun.gc.metaspace.capacity scale K align right - width 8 + width 10 format "0.0" } column { @@ -391,7 +391,7 @@ option gccapacity { data sun.gc.compressedclassspace.minCapacity scale K align right - width 8 + width 9 format "0.0" } column { @@ -399,7 +399,7 @@ option gccapacity { data sun.gc.compressedclassspace.maxCapacity scale K align right - width 8 + width 9 format "0.0" } column { @@ -407,7 +407,7 @@ option gccapacity { data sun.gc.compressedclassspace.capacity scale K align right - width 8 + width 9 format "0.0" } column { @@ -496,7 +496,7 @@ option gccause { data sun.gc.collector.0.time/sun.os.hrt.frequency align right scale sec - width 8 + width 9 format "0.000" } column { @@ -512,7 +512,7 @@ option gccause { data sun.gc.collector.1.time/sun.os.hrt.frequency align right scale sec - width 8 + width 9 format "0.000" } column { @@ -524,10 +524,10 @@ option gccause { format "0" } column { - header "^CGCT^" /* Concurrent Garbage Collection Time (STW phase) */ + header "^CGCT^" /* Concurrent Collection Time (STW phase) */ data sun.gc.collector.2.time/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" } @@ -535,7 +535,7 @@ option gccause { header "^GCT^" /* Total Garbage Collection Time */ data (sun.gc.collector.0.time + sun.gc.collector.1.time + sun.gc.collector.2.time)/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" required true @@ -562,7 +562,7 @@ option gcnew { data sun.gc.generation.0.space.1.capacity scale K align right - width 6 + width 11 format "0.0" } column { @@ -570,7 +570,7 @@ option gcnew { data sun.gc.generation.0.space.2.capacity scale K align right - width 6 + width 11 format "0.0" } column { @@ -578,7 +578,7 @@ option gcnew { data sun.gc.generation.0.space.1.used scale K align right - width 6 + width 11 format "0.0" } column { @@ -586,7 +586,7 @@ option gcnew { data sun.gc.generation.0.space.2.used scale K align right - width 6 + width 11 format "0.0" } column { @@ -607,7 +607,7 @@ option gcnew { header "^DSS^" /* Desired Survivor Size */ data sun.gc.policy.desiredSurvivorSize scale K - width 6 + width 11 align right format "0.0" } @@ -615,7 +615,7 @@ option gcnew { header "^EC^" /* Eden Space Capacity - Current */ data sun.gc.generation.0.space.0.capacity scale K - width 8 + width 12 align right format "0.0" } @@ -623,7 +623,7 @@ option gcnew { header "^EU^" /* Eden Space Used */ data sun.gc.generation.0.space.0.used scale K - width 8 + width 12 align right format "0.0" } @@ -639,7 +639,7 @@ option gcnew { data sun.gc.collector.0.time/sun.os.hrt.frequency align right scale sec - width 8 + width 9 format "0.000" } } @@ -650,7 +650,7 @@ option gcnewcapacity { data sun.gc.generation.0.minCapacity scale K align right - width 10 + width 12 format "0.0" } column { @@ -658,7 +658,7 @@ option gcnewcapacity { data sun.gc.generation.0.maxCapacity scale K align right - width 10 + width 12 format "0.0" } column { @@ -666,7 +666,7 @@ option gcnewcapacity { data sun.gc.generation.0.capacity scale K align right - width 10 + width 12 format "0.0" } column { @@ -674,7 +674,7 @@ option gcnewcapacity { data sun.gc.generation.0.space.1.maxCapacity scale K align right - width 8 + width 11 format "0.0" } column { @@ -682,7 +682,7 @@ option gcnewcapacity { data sun.gc.generation.0.space.1.capacity scale K align right - width 8 + width 11 format "0.0" } column { @@ -690,7 +690,7 @@ option gcnewcapacity { data sun.gc.generation.0.space.2.maxCapacity scale K align right - width 8 + width 11 format "0.0" } column { @@ -698,7 +698,7 @@ option gcnewcapacity { data sun.gc.generation.0.space.2.capacity scale K align right - width 8 + width 11 format "0.0" } column { @@ -706,7 +706,7 @@ option gcnewcapacity { data sun.gc.generation.0.space.0.maxCapacity scale K align right - width 10 + width 12 format "0.0" } column { @@ -714,14 +714,14 @@ option gcnewcapacity { data sun.gc.generation.0.space.0.capacity scale K align right - width 10 + width 12 format "0.0" } column { header "^YGC^" /* Young Generation Collections */ data sun.gc.collector.0.invocations align right - width 5 + width 6 format "0" } column { @@ -746,7 +746,7 @@ option gcold { column { header "^MC^" /* Metaspace Capacity - Current */ data sun.gc.metaspace.capacity - width 8 + width 10 align right scale K format "0.0" @@ -754,7 +754,7 @@ option gcold { column { header "^MU^" /* Metaspace Space Used */ data sun.gc.metaspace.used - width 8 + width 10 align right scale K format "0.0" @@ -762,7 +762,7 @@ option gcold { column { header "^CCSC^" /* Compressed Class Space Capacity - Current */ data sun.gc.compressedclassspace.capacity - width 8 + width 9 align right scale K format "0.0" @@ -770,7 +770,7 @@ option gcold { column { header "^CCSU^" /* Compressed Class Space Used */ data sun.gc.compressedclassspace.used - width 8 + width 9 align right scale K format "0.0" @@ -778,7 +778,7 @@ option gcold { column { header "^OC^" /* Old Space Capacity - Current */ data sun.gc.generation.1.space.0.capacity - width 11 + width 12 align right scale K format "0.0" @@ -786,7 +786,7 @@ option gcold { column { header "^OU^" /* Old Space Used */ data sun.gc.generation.1.space.0.used - width 11 + width 12 align right scale K format "0.0" @@ -811,7 +811,7 @@ option gcold { data sun.gc.collector.1.time/sun.os.hrt.frequency align right scale sec - width 8 + width 9 format "0.000" } column { @@ -823,10 +823,10 @@ option gcold { format "0" } column { - header "^CGCT^" /* Concurrent Garbage Collection Time (STW phase) */ + header "^CGCT^" /* Concurrent Collection Time (STW phase) */ data sun.gc.collector.2.time/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" } @@ -834,7 +834,7 @@ option gcold { header "^GCT^" /* Total Garbage Collection Time */ data (sun.gc.collector.0.time + sun.gc.collector.1.time + sun.gc.collector.2.time)/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" required true @@ -847,7 +847,7 @@ option gcoldcapacity { data sun.gc.generation.1.minCapacity scale K align right - width 11 + width 12 format "0.0" } column { @@ -855,7 +855,7 @@ option gcoldcapacity { data sun.gc.generation.1.maxCapacity scale K align right - width 11 + width 12 format "0.0" } column { @@ -863,7 +863,7 @@ option gcoldcapacity { data sun.gc.generation.1.capacity scale K align right - width 11 + width 12 format "0.0" } column { @@ -871,14 +871,14 @@ option gcoldcapacity { data sun.gc.generation.1.space.0.capacity scale K align right - width 11 + width 12 format "0.0" } column { header "^YGC^" /* Young Generation Collections */ data sun.gc.collector.0.invocations align right - width 5 + width 6 format "0" } column { @@ -894,7 +894,7 @@ option gcoldcapacity { data sun.gc.collector.1.time/sun.os.hrt.frequency align right scale sec - width 8 + width 9 format "0.000" } column { @@ -906,10 +906,10 @@ option gcoldcapacity { format "0" } column { - header "^CGCT^" /* Concurrent Garbage Collection Time (STW phase) */ + header "^CGCT^" /* Concurrent Collection Time (STW phase) */ data sun.gc.collector.2.time/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" } @@ -917,7 +917,7 @@ option gcoldcapacity { header "^GCT^" /* Total Garbage Collection Time */ data (sun.gc.collector.0.time + sun.gc.collector.1.time + sun.gc.collector.2.time)/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" required true @@ -954,7 +954,7 @@ option gcmetacapacity { data sun.gc.compressedclassspace.minCapacity scale K align right - width 10 + width 9 format "0.0" } column { @@ -962,7 +962,7 @@ option gcmetacapacity { data sun.gc.compressedclassspace.maxCapacity scale K align right - width 10 + width 9 format "0.0" } column { @@ -970,14 +970,14 @@ option gcmetacapacity { data sun.gc.compressedclassspace.capacity scale K align right - width 10 + width 9 format "0.0" } column { header "^YGC^" /* Young Generation Collections */ data sun.gc.collector.0.invocations align right - width 5 + width 6 format "0" } column { @@ -993,7 +993,7 @@ option gcmetacapacity { data sun.gc.collector.1.time/sun.os.hrt.frequency align right scale sec - width 8 + width 9 format "0.000" } column { @@ -1005,10 +1005,10 @@ option gcmetacapacity { format "0" } column { - header "^CGCT^" /* Concurrent Garbage Collection Time (STW phase) */ + header "^CGCT^" /* Concurrent Collection Time (STW phase) */ data sun.gc.collector.2.time/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" } @@ -1016,7 +1016,7 @@ option gcmetacapacity { header "^GCT^" /* Total Garbage Collection Time */ data (sun.gc.collector.0.time + sun.gc.collector.1.time + sun.gc.collector.2.time)/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" required true @@ -1084,7 +1084,7 @@ option gcutil { data sun.gc.collector.0.time/sun.os.hrt.frequency align right scale sec - width 8 + width 9 format "0.000" } column { @@ -1100,7 +1100,7 @@ option gcutil { data sun.gc.collector.1.time/sun.os.hrt.frequency align right scale sec - width 8 + width 9 format "0.000" } column { @@ -1112,10 +1112,10 @@ option gcutil { format "0" } column { - header "^CGCT^" /* Concurrent Garbage Collection Time (STW phase) */ + header "^CGCT^" /* Concurrent Collection Time (STW phase) */ data sun.gc.collector.2.time/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" } @@ -1123,7 +1123,7 @@ option gcutil { header "^GCT^" /* Total Garbage Collection Time */ data (sun.gc.collector.0.time + sun.gc.collector.1.time + sun.gc.collector.2.time)/sun.os.hrt.frequency align right - width 8 + width 9 scale sec format "0.000" required true diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/FailOverExecutionControlProvider.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/FailOverExecutionControlProvider.java index 890306c2fcc..6d3e5cc03f0 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/FailOverExecutionControlProvider.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/FailOverExecutionControlProvider.java @@ -96,6 +96,8 @@ public Map defaultParameters() { public ExecutionControl generate(ExecutionEnv env, Map parameters) throws Throwable { Throwable thrown = null; + StringWriter dumpsw = new StringWriter(); + PrintWriter dump = new PrintWriter(dumpsw); for (int i = 0; i <= 9; ++i) { String param = parameters.get("" + i); if (param != null && !param.isEmpty()) { @@ -115,10 +117,17 @@ public ExecutionControl generate(ExecutionEnv env, Map parameter ex.printStackTrace(log); log.flush(); logger().fine(writer.toString()); - // only care about the first, and only if they all fail - if (thrown == null) { - thrown = ex; + // if they all fail, use the last as cause and include info about prior in message + dump.printf("FailOverExecutionControlProvider: FAILED: %d:%s --%n", i, param); + dump.printf(" Exception: %s%n", ex); + var st = ex.getStackTrace(); + for (int k = 0; k < 5 && k < st.length; ++k) { + dump.printf(" %s%n", st[k]); } + if (ex.getCause() != null) { + dump.printf(" cause: %s%n", ex.getCause()); + } + thrown = ex; } } @@ -127,7 +136,7 @@ public ExecutionControl generate(ExecutionEnv env, Map parameter if (thrown == null) { throw new IllegalArgumentException("All least one parameter must be set to a provider."); } - throw thrown; + throw new RuntimeException(dumpsw.toString(), thrown); } private Logger logger() { diff --git a/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java b/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java index c79d511b471..b87cd0eebd8 100644 --- a/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java +++ b/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java @@ -25,6 +25,7 @@ package com.sun.management; +import java.io.IOException; import java.lang.management.PlatformManagedObject; /** @@ -72,7 +73,7 @@ public interface HotSpotDiagnosticMXBean extends PlatformManagedObject { * method denies write access to the named file * or the caller does not have ManagmentPermission("control"). */ - public void dumpHeap(String outputFile, boolean live) throws java.io.IOException; + public void dumpHeap(String outputFile, boolean live) throws IOException; /** * Returns a list of {@code VMOption} objects for all diagnostic options. diff --git a/test/hotspot/gtest/gc/shared/test_oopStorage.cpp b/test/hotspot/gtest/gc/shared/test_oopStorage.cpp index 3758cd65d6e..5fdea55980b 100644 --- a/test/hotspot/gtest/gc/shared/test_oopStorage.cpp +++ b/test/hotspot/gtest/gc/shared/test_oopStorage.cpp @@ -183,27 +183,14 @@ class OopStorageTest : public ::testing::Test { OopStorageTest(); ~OopStorageTest(); - Mutex _allocation_mutex; - Mutex _active_mutex; OopStorage _storage; - static const int _active_rank = Mutex::leaf - 1; - static const int _allocate_rank = Mutex::leaf; - class CountingIterateClosure; template class VM_CountAtSafepoint; }; OopStorageTest::OopStorageTest() : - _allocation_mutex(_allocate_rank, - "test_OopStorage_allocation", - false, - Mutex::_safepoint_check_never), - _active_mutex(_active_rank, - "test_OopStorage_active", - false, - Mutex::_safepoint_check_never), - _storage("Test Storage", &_allocation_mutex, &_active_mutex) + _storage("Test Storage") { } OopStorageTest::~OopStorageTest() { diff --git a/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp b/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp index d4e24ac415c..dea8fe7903a 100644 --- a/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp +++ b/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp @@ -67,11 +67,6 @@ class OopStorageParIterPerf : public ::testing::Test { static WorkGang* _workers; - static const int _active_rank = Mutex::leaf - 1; - static const int _allocate_rank = Mutex::leaf; - - Mutex _allocate_mutex; - Mutex _active_mutex; OopStorage _storage; oop* _entries[_storage_entries]; }; @@ -92,15 +87,7 @@ WorkGang* OopStorageParIterPerf::workers() const { } OopStorageParIterPerf::OopStorageParIterPerf() : - _allocate_mutex(_allocate_rank, - "test_OopStorage_parperf_allocate", - false, - Mutex::_safepoint_check_never), - _active_mutex(_active_rank, - "test_OopStorage_parperf_active", - false, - Mutex::_safepoint_check_never), - _storage("Test Storage", &_allocate_mutex, &_active_mutex) + _storage("Test Storage") { for (size_t i = 0; i < _storage_entries; ++i) { _entries[i] = _storage.allocate(); diff --git a/test/hotspot/gtest/gc/shared/test_workerDataArray.cpp b/test/hotspot/gtest/gc/shared/test_workerDataArray.cpp index 7a17392e2ee..b08d9ae83c4 100644 --- a/test/hotspot/gtest/gc/shared/test_workerDataArray.cpp +++ b/test/hotspot/gtest/gc/shared/test_workerDataArray.cpp @@ -34,7 +34,7 @@ class WorkerDataArrayTest : public ::testing::Test { protected: WorkerDataArrayTest() : title("Test array"), - array(title, 3), + array(NULL, title, 3), sub_item_title("Sub item array") { array.create_thread_work_items(sub_item_title); diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 0d039cbe951..22dfac35769 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -201,6 +201,7 @@ serviceability/sa/TestRevPtrsForInvokeDynamic.java 8241235 generic-all serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatIntervalTest.java 8214032 generic-all serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatArrayCorrectnessTest.java 8224150 generic-all +serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java 8225354 windows-all # Valhalla TODO: serviceability/sa/ClhsdbCDSCore.java 8190936 generic-all diff --git a/test/hotspot/jtreg/compiler/c2/TestBit.java b/test/hotspot/jtreg/compiler/c2/TestBit.java new file mode 100644 index 00000000000..2e3d5248363 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestBit.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/* + * @test + * @bug 8247408 + * @summary C2 should convert ((var&16) == 16) to ((var&16) != 0) for power-of-two constants + * @library /test/lib / + * + * @run main/othervm compiler.c2.TestBit + * + * @requires os.arch=="aarch64" | os.arch=="amd64" | os.arch == "ppc64le" + * @requires vm.debug == true & vm.flavor == "server" & !vm.graal.enabled + */ +public class TestBit { + + static void runTest(String testName) throws Exception { + String className = "compiler.c2.TestBit"; + String[] procArgs = { + "-XX:+PrintOptoAssembly", + "-XX:CompileCommand=compileonly," + className + "::tst*", + className, testName}; + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + String expectedTestBitInstruction = + "ppc64le".equals(System.getProperty("os.arch")) ? "ANDI" : + "aarch64".equals(System.getProperty("os.arch")) ? "tb" : + "amd64".equals(System.getProperty("os.arch")) ? "test" : null; + + if (expectedTestBitInstruction != null) { + output.shouldContain(expectedTestBitInstruction); + } else { + System.err.println("unexpected os.arch"); + } + } + + static final int ITER = 100000; // ~ Tier4CompileThreshold + compilation time + + // dummy volatile variable + public static volatile long c = 0; + + // C2 is expected to generate test bit instruction on the test + static void tstBitLong(long value) { + if (1L == (1L & value)) { + c++; + } else { + c--; + } + } + + // C2 is expected to generate test bit instruction on the test + static void tstBitInt(int value) { + if (1 == (1 & value)) { + c++; + } else { + c--; + } + } + + public static void main(String[] args) throws Exception { + if (args.length == 0) { + // Fork VMs to check their debug compiler output + runTest("tstBitLong"); + runTest("tstBitInt"); + } + if (args.length > 0) { + // We are in a forked VM to execute the named test + String testName = args[0]; + switch (testName) { + case "tstBitLong": + for (int i = 0; i < ITER; i++) { + tstBitLong(i % 2); + } + break; + case "tstBitInt": + for (int i = 0; i < ITER; i++) { + tstBitInt(i % 2); + } + break; + default: + throw new RuntimeException("unexpected test name " + testName); + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/c2/TestLiveNodeLimit.java b/test/hotspot/jtreg/compiler/c2/TestLiveNodeLimit.java new file mode 100644 index 00000000000..7adf1eed68e --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestLiveNodeLimit.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8244724 + * @summary Test which exceeds the live node limit in Compile::Code_Gen(). The previouslz failing assert is now only checked during parsing and during Compile::Optimize(). + * + * @compile -XDstringConcat=inline TestLiveNodeLimit.java + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.c2.TestLiveNodeLimit::test* compiler.c2.TestLiveNodeLimit + */ +package compiler.c2; + +import java.util.ArrayList; + +public class TestLiveNodeLimit { + + public static ArrayList arrList = new ArrayList(); + + public static void main(String[] args) { + for (int i = 0; i < 10000; i++) { + testNodeLimitInBuildCfg(); + testNodeLimitInGlobalCodeMotion(); + } + } + + // Hits live node limit in PhaseCFG::build_cfg(). There are around 70000 nodes right before build_cfg() + // which creates another 15000 nodes which exceeds the default max node limit of 80000. + public static int testNodeLimitInBuildCfg() { + // Just some string operations that create a lot of nodes when compiled with javac with -XDstringConcat=inline + // which generate a lot of StringBuilder objects and calls + String someString = "as@df#as@df" + "fdsa"; + String[] split = someString.split("#"); + String[] tmp1 = split[0].split("@"); + String[] tmp2 = split[0].split("@"); + String concat1 = tmp1[0] + tmp2[0] + split[0]; + String concat2 = tmp1[0] + tmp2[0] + split[0]; + String concat3 = tmp1[0] + tmp2[0]; + String concat4 = tmp1[0] + tmp2[0]; + String string1 = "string1"; + String[] stringArr1 = arrList.toArray(new String[4]); + String[] stringArr2 = new String[3]; + String[] stringArr3 = new String[3]; + if (stringArr1.length > 1) { + stringArr2 = new String[3 * stringArr1.length]; + stringArr3 = new String[3 * stringArr1.length]; + for (int i = 0; i < stringArr1.length; i++) { + stringArr2[3 * i ] = string1 + concat1 + concat3 + stringArr1[i]; + stringArr2[3 * i + 1] = string1 + concat1 + concat3 + stringArr1[i]; + stringArr2[3 * i + 2] = string1 + concat1 + concat3 + stringArr1[i]; + stringArr3[3 * i ] = string1 + concat2 + concat3 + concat4 + stringArr1[i]; + stringArr3[3 * i + 1] = string1 + concat2 + concat3 + concat4 + stringArr1[i]; + stringArr3[3 * i + 2] = string1 + concat2 + concat3 + concat4 + stringArr1[i]; + } + } + return stringArr1.length + stringArr2.length + stringArr3.length; + } + + // Hits live node limit in PhaseCFG::global_code_motion(). There are around 79000 nodes right before global_code_motion() + // which creates another 2000 nodes which exceeds the default max node limit of 80000. + public static int testNodeLimitInGlobalCodeMotion() { + // Just some string operations that create a lot of nodes when compiled with javac with -XDstringConcat=inline + // which generate a lot of StringBuilder objects and calls + String someString = "as@df#as@df" + "fdsa"; + String[] split = someString.split("#"); + String[] tmp1 = split[0].split("@"); + String[] tmp2 = split[0].split("@"); + String concat1 = tmp1[0] + tmp2[0] + split[0]; + String concat2 = tmp1[0] + tmp2[0] + split[0]; + String concat3 = tmp1[0] + tmp2[0] + split[0]; + String concat4 = tmp1[0] + tmp2[0] + split[0]; + String string1 = "string1"; + String[] stringArr1 = arrList.toArray(new String[4]); + String[] stringArr2 = new String[3]; + String[] stringArr3 = new String[3]; + if (stringArr1.length > 1) { + stringArr2 = new String[3 * stringArr1.length]; + stringArr3 = new String[3 * stringArr1.length]; + for (int i = 0; i < stringArr1.length; i++) { + stringArr2[3 * i ] = string1 + concat1 + concat3 + stringArr1[i]; + stringArr2[3 * i + 1] = string1 + concat1 + concat3 + stringArr1[i]; + stringArr2[3 * i + 2] = string1 + concat1 + concat3 + stringArr1[i]; + stringArr3[3 * i ] = string1 + concat2 + concat4 + stringArr1[i]; + stringArr3[3 * i + 1] = string1 + concat2 + concat4 + stringArr1[i]; + stringArr3[3 * i + 2] = string1 + concat2 + stringArr1[i]; + } + } + return stringArr1.length + stringArr2.length + stringArr3.length; + } +} + diff --git a/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java b/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java index 818ab4ee5d3..7d39496831a 100644 --- a/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java +++ b/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java @@ -70,9 +70,12 @@ public abstract class CiReplayBase { private static final String[] REPLAY_OPTIONS = new String[]{DISABLE_COREDUMP_ON_CRASH, "-XX:+ReplayCompiles", REPLAY_FILE_OPTION}; protected final Optional runServer; + private static int dummy; - public static class EmptyMain { + public static class TestMain { public static void main(String[] args) { + // Do something because empty methods might not be called/compiled. + dummy = 42; } } @@ -140,7 +143,7 @@ public boolean generateReplay(boolean needCoreDump, String... vmopts) { options.addAll(Arrays.asList(REPLAY_GENERATION_OPTIONS)); options.addAll(Arrays.asList(vmopts)); options.add(needCoreDump ? ENABLE_COREDUMP_ON_CRASH : DISABLE_COREDUMP_ON_CRASH); - options.add(EmptyMain.class.getName()); + options.add(TestMain.class.getName()); if (needCoreDump) { crashOut = ProcessTools.executeProcess(getTestJvmCommandlineWithPrefix( RUN_SHELL_NO_LIMIT, options.toArray(new String[0]))); diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 708db56bd64..4a73e2b2aa2 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -49,6 +49,9 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.AccessibleObject; @@ -64,6 +67,7 @@ import java.util.Map; import java.util.Set; +import org.junit.Assert; import org.junit.Test; import jdk.internal.org.objectweb.asm.*; @@ -337,6 +341,111 @@ public void findLeastCommonAncestorTest() { } } + @Test + public void linkTest() { + for (Class c : classes) { + ResolvedJavaType type = metaAccess.lookupJavaType(c); + type.link(); + } + } + + private class HidingClassLoader extends ClassLoader { + @Override + protected Class findClass(final String name) throws ClassNotFoundException { + if (name.endsWith("MissingInterface")) { + throw new ClassNotFoundException("missing"); + } + byte[] classData = null; + try { + InputStream is = HidingClassLoader.class.getResourceAsStream("/" + name.replace('.', '/') + ".class"); + classData = new byte[is.available()]; + new DataInputStream(is).readFully(classData); + } catch (IOException e) { + Assert.fail("can't access class: " + name); + } + + return defineClass(null, classData, 0, classData.length); + } + + ResolvedJavaType lookupJavaType(String name) throws ClassNotFoundException { + return metaAccess.lookupJavaType(loadClass(name)); + } + + HidingClassLoader() { + super(null); + } + + } + + interface MissingInterface { + } + + static class MissingInterfaceImpl implements MissingInterface { + } + + interface SomeInterface { + default MissingInterface someMethod() { + return new MissingInterfaceImpl(); + } + } + + static class Wrapper implements SomeInterface { + } + + @Test + public void linkExceptionTest() throws ClassNotFoundException { + HidingClassLoader cl = new HidingClassLoader(); + ResolvedJavaType inner = cl.lookupJavaType(Wrapper.class.getName()); + assertTrue("expected default methods", inner.hasDefaultMethods()); + try { + inner.link(); + assertFalse("link should throw an exception", true); + } catch (NoClassDefFoundError e) { + } + } + + @Test + public void hasDefaultMethodsTest() { + for (Class c : classes) { + ResolvedJavaType type = metaAccess.lookupJavaType(c); + assertEquals(hasDefaultMethods(type), type.hasDefaultMethods()); + } + } + + @Test + public void declaresDefaultMethodsTest() { + for (Class c : classes) { + ResolvedJavaType type = metaAccess.lookupJavaType(c); + assertEquals(declaresDefaultMethods(type), type.declaresDefaultMethods()); + } + } + + private static boolean hasDefaultMethods(ResolvedJavaType type) { + if (!type.isInterface() && type.getSuperclass() != null && hasDefaultMethods(type.getSuperclass())) { + return true; + } + for (ResolvedJavaType iface : type.getInterfaces()) { + if (hasDefaultMethods(iface)) { + return true; + } + } + return declaresDefaultMethods(type); + } + + static boolean declaresDefaultMethods(ResolvedJavaType type) { + if (!type.isInterface()) { + /* Only interfaces can declare default methods. */ + return false; + } + for (ResolvedJavaMethod method : type.getDeclaredMethods()) { + if (method.isDefault()) { + assert !Modifier.isStatic(method.getModifiers()) : "Default method that is static?"; + return true; + } + } + return false; + } + private static class Base { } diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/AbortProvoker.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/AbortProvoker.java index 2d9411e94d0..1c6cecca08c 100644 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/AbortProvoker.java +++ b/test/hotspot/jtreg/compiler/testlibrary/rtm/AbortProvoker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,7 +98,9 @@ public static Object inflateMonitor(Object monitor) throws Exception { public static void verifyMonitorState(Object monitor, boolean shouldBeInflated) { if (!shouldBeInflated && WHITE_BOX.isMonitorInflated(monitor)) { - WHITE_BOX.forceSafepoint(); + boolean did_deflation = WHITE_BOX.deflateIdleMonitors(); + Asserts.assertEQ(did_deflation, true, + "deflateIdleMonitors() should have worked."); } Asserts.assertEQ(WHITE_BOX.isMonitorInflated(monitor), shouldBeInflated, "Monitor in a wrong state."); diff --git a/test/hotspot/jtreg/compiler/unsafe/TestUnsafeUnalignedSwap.java b/test/hotspot/jtreg/compiler/unsafe/TestUnsafeUnalignedSwap.java new file mode 100644 index 00000000000..1b345894e7c --- /dev/null +++ b/test/hotspot/jtreg/compiler/unsafe/TestUnsafeUnalignedSwap.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Alibaba designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* @test + * @library / /test/lib + * @bug 8246051 + * @summary A test for SIGBUS in aarch64 by unalgined unsafe access + * @requires os.arch=="aarch64" + * @run main/othervm/timeout=200 -XX:-Inline TestUnsafeUnalignedSwap + */ + +import sun.misc.Unsafe; +import java.lang.reflect.Field; +import java.util.*; +import jdk.test.lib.Asserts; + +public class TestUnsafeUnalignedSwap { + private final static Unsafe U; + private static long sum = 4; + static volatile long[] arrayLong = new long[1001]; + static volatile int[] arrayInt = new int[1001]; + static { + try { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + U = (Unsafe) f.get(null); + } catch (ReflectiveOperationException e) { + throw new InternalError(e); + } + } + // Bug 8246051 : Unsafe.compareAndSwapLong should not crash + public static void testCompareAndSwapLong() { + try { + if (U.compareAndSwapLong(arrayLong, Unsafe.ARRAY_LONG_BASE_OFFSET + 1, 3243, 2334)) { + sum++; + } else { + sum--; + } + } catch (InternalError e) { + System.out.println(e.getMessage()); + } + } + public static void testCompareAndSwapInt() { + try { + if (U.compareAndSwapInt(arrayInt, Unsafe.ARRAY_INT_BASE_OFFSET + 1, 3243, 2334)) { + sum++; + } else { + sum--; + } + } catch (InternalError e) { + System.out.println(e.getMessage()); + } + } + public static void test() { + testCompareAndSwapLong(); + testCompareAndSwapInt(); + } + public static void main(String[] args) { + test(); + } +} diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java index 8e84a3bc7a5..34b5f77d05f 100644 --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java @@ -122,13 +122,13 @@ public boolean isAvailable() { // Ext Root Scan new LogMessageWithLevel("Thread Roots", Level.TRACE), new LogMessageWithLevel("Universe Roots", Level.TRACE), - new LogMessageWithLevel("JNI Handles Roots", Level.TRACE), new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE), new LogMessageWithLevel("Management Roots", Level.TRACE), - new LogMessageWithLevel("VM Global Roots", Level.TRACE), new LogMessageWithLevel("CLDG Roots", Level.TRACE), new LogMessageWithLevel("JVMTI Roots", Level.TRACE), new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE), + new LogMessageWithLevel("JNI Global Roots", Level.TRACE), + new LogMessageWithLevel("VM Global Roots", Level.TRACE), // Redirty Cards new LogMessageWithLevel("Redirty Cards", Level.DEBUG), new LogMessageWithLevel("Parallel Redirty", Level.TRACE), @@ -164,10 +164,10 @@ public boolean isAvailable() { new LogMessageWithLevel("Reference Processing", Level.DEBUG), // VM internal reference processing new LogMessageWithLevel("Weak Processing", Level.DEBUG), - new LogMessageWithLevel("JNI weak", Level.DEBUG), - new LogMessageWithLevel("StringTable weak", Level.DEBUG), - new LogMessageWithLevel("ResolvedMethodTable weak", Level.DEBUG), - new LogMessageWithLevel("VM weak", Level.DEBUG), + new LogMessageWithLevel("JNI Weak", Level.DEBUG), + new LogMessageWithLevel("StringTable Weak", Level.DEBUG), + new LogMessageWithLevel("ResolvedMethodTable Weak", Level.DEBUG), + new LogMessageWithLevel("VM Weak", Level.DEBUG), new LogMessageWithLevelC2OrJVMCIOnly("DerivedPointerTable Update", Level.DEBUG), new LogMessageWithLevel("Start New Collection Set", Level.DEBUG), diff --git a/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java b/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java index 76160e426b8..e2a494110e4 100644 --- a/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java +++ b/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java @@ -203,6 +203,10 @@ public static void main(String[] args) throws ClassNotFoundException, Instantiat gc.provoke(); + boolean did_deflation = WB.deflateIdleMonitors(); + Asserts.assertEQ(did_deflation, true, + "deflateIdleMonitors() should have worked."); + // Test checks Asserts.assertEquals(WB.isClassAlive(HUMONGOUS_CLASSLOADER_NAME), false, String.format("Classloader class %s is loaded after we forget all references to it", diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestShenandoahLRBInOuterStripMinedLoop.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestShenandoahLRBInOuterStripMinedLoop.java new file mode 100644 index 00000000000..774d3cd3e6f --- /dev/null +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestShenandoahLRBInOuterStripMinedLoop.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8247824 + * @summary CTW: C2 (Shenandoah) compilation fails with SEGV in SBC2Support::pin_and_expand + * @requires vm.flavor == "server" + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * + * @run main/othervm -XX:-BackgroundCompilation -XX:+UseShenandoahGC -XX:LoopMaxUnroll=0 TestShenandoahLRBInOuterStripMinedLoop + * + */ + +import java.util.Arrays; + +public class TestShenandoahLRBInOuterStripMinedLoop { + public static void main(String[] args) { + A[] array = new A[4000]; + Arrays.fill(array, new A()); + for (int i = 0; i < 20_0000; i++) { + test(array); + } + } + + private static int test(A[] array) { + A a = null; + int v = 1; + A b = null; + for (int i = 0; i < 2000; i++) { + a = array[i]; + b = array[2*i]; + v *= 2; + } + return a.f + b.f + v; + } + + private static class A { + public int f; + } +} diff --git a/test/hotspot/jtreg/gc/whitebox/TestWBGC.java b/test/hotspot/jtreg/gc/whitebox/TestWBGC.java index 2d1cdbf26c4..0b08d40f88d 100644 --- a/test/hotspot/jtreg/gc/whitebox/TestWBGC.java +++ b/test/hotspot/jtreg/gc/whitebox/TestWBGC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,9 @@ package gc.whitebox; /* - * @test TestWBGC + * @test * @bug 8055098 - * @summary Test verify that WB methods isObjectInOldGen and youngGC works correctly. + * @summary Test to verify that WB methods isObjectInOldGen and youngGC work correctly. * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/gtest/GTestWrapper.java b/test/hotspot/jtreg/gtest/GTestWrapper.java index 2c000b18372..4772ad87774 100644 --- a/test/hotspot/jtreg/gtest/GTestWrapper.java +++ b/test/hotspot/jtreg/gtest/GTestWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ public static void main(String[] args) throws Throwable { .resolve(jvmVariantDir); } if (!path.toFile().exists()) { - throw new Error("TESTBUG: the library has not been found in " + nativePath); + throw new Error("TESTBUG: the library has not been found in " + nativePath + ". Did you forget to use --with-gtest to configure?"); } Path execPath = path.resolve("gtestLauncher" + (Platform.isWindows() ? ".exe" : "")); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/BootClassPathMismatch.java b/test/hotspot/jtreg/runtime/cds/appcds/BootClassPathMismatch.java index 68f938046a6..7016558be9f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/BootClassPathMismatch.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/BootClassPathMismatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ * @requires vm.cds * @library /test/lib * @compile test-classes/Hello.java + * @compile test-classes/C2.java * @run driver BootClassPathMismatch */ @@ -61,6 +62,7 @@ public static void main(String[] args) throws Exception { test.testBootClassPathMatchWithAppend(); } test.testBootClassPathMatch(); + test.testBootClassPathMismatchTwoJars(); } /* Archive contains boot classes only, with Hello class on -Xbootclasspath/a path. @@ -215,6 +217,25 @@ public void testBootClassPathMismatchWithAppClass() throws Exception { .assertAbnormalExit(mismatchMessage); } + /* Archive contains app classes, with 2 jars in bootclasspath at dump time. + * + * Error should be detected if: + * dump time: -Xbootclasspath/a:hello.jar:jar2.jar + * run-time : -Xbootclasspath/a:hello.jar:jar2.jarx + * Note: the second jar (jar2.jarx) specified for run-time doesn't exist. + */ + public void testBootClassPathMismatchTwoJars() throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + String jar2 = ClassFileInstaller.writeJar("jar2.jar", "pkg/C2"); + String jars = appJar + File.pathSeparator + jar2; + String appClasses[] = {"Hello", "pkg/C2"}; + TestCommon.dump( + appJar, appClasses, "-Xbootclasspath/a:" + jars); + TestCommon.run( + "-cp", appJar, "-Xbootclasspath/a:" + jars + "x", "Hello") + .assertAbnormalExit(mismatchMessage); + } + private static void copyHelloToNewDir() throws Exception { String classDir = System.getProperty("test.classes"); String dstDir = classDir + File.separator + "newdir"; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/WrongClasspath.java b/test/hotspot/jtreg/runtime/cds/appcds/WrongClasspath.java index 2a5f5677f05..3d2d4fa7fab 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/WrongClasspath.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/WrongClasspath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,9 +28,11 @@ * @requires vm.cds * @library /test/lib * @compile test-classes/Hello.java + * @compile test-classes/C2.java * @run driver WrongClasspath */ +import java.io.File; import jdk.test.lib.process.OutputAnalyzer; public class WrongClasspath { @@ -48,5 +50,16 @@ public static void main(String[] args) throws Exception { "Hello") .assertAbnormalExit("Unable to use shared archive", "shared class paths mismatch"); + + // Dump CDS archive with 2 jars: -cp hello.jar:jar2.jar + // Run with 2 jars but the second jar doesn't exist: -cp hello.jarjar2.jarx + // Shared class paths mismatch should be detected. + String jar2 = ClassFileInstaller.writeJar("jar2.jar", "pkg/C2"); + String jars = appJar + File.pathSeparator + jar2; + TestCommon.testDump(jars, TestCommon.list("Hello", "pkg/C2")); + TestCommon.run( + "-cp", jars + "x", "Hello") + .assertAbnormalExit("Unable to use shared archive", + "shared class paths mismatch"); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/PatchModule/Simple.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/PatchModule/Simple.java index 15cfa2cc3c1..7edb1937d6b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/PatchModule/Simple.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/PatchModule/Simple.java @@ -33,6 +33,7 @@ * @run driver Simple */ +import jdk.test.lib.cds.CDSTestUtils; import jdk.test.lib.compiler.InMemoryJavaCompiler; import jdk.test.lib.process.OutputAnalyzer; @@ -78,18 +79,20 @@ public static void main(String args[]) throws Throwable { .assertSilentlyDisabledCDS(0, "I pass!"); // ======================================== - System.out.println("Dump again without --patch-module"); - output = - TestCommon.dump(null, - TestCommon.list("javax/naming/spi/NamingManager")); - output.shouldHaveExitValue(0); + if (!CDSTestUtils.DYNAMIC_DUMP) { + System.out.println("Dump again without --patch-module"); + output = + TestCommon.dump(null, + TestCommon.list("javax/naming/spi/NamingManager")); + output.shouldHaveExitValue(0); - TestCommon.run( - "-XX:+UnlockDiagnosticVMOptions", - "--patch-module=java.naming=" + moduleJar, - "-Xlog:class+load", - "-Xlog:class+path=info", - "PatchMain", "javax.naming.spi.NamingManager") - .assertSilentlyDisabledCDS(0, "I pass!"); + TestCommon.run( + "-XX:+UnlockDiagnosticVMOptions", + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "-Xlog:class+path=info", + "PatchMain", "javax.naming.spi.NamingManager") + .assertSilentlyDisabledCDS(0, "I pass!"); + } } } diff --git a/test/hotspot/jtreg/runtime/modules/SealedInterfaceModuleTest.java b/test/hotspot/jtreg/runtime/modules/SealedInterfaceModuleTest.java new file mode 100644 index 00000000000..403a5852f3f --- /dev/null +++ b/test/hotspot/jtreg/runtime/modules/SealedInterfaceModuleTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8225056 8246337 + * @modules java.base/jdk.internal.misc + * @library /test/lib .. + * @compile sealedP1/SuperInterface.jcod + * @compile --enable-preview --source ${jdk.version} sealedP1/C1.java sealedP2/C2.java sealedP3/C3.java + * @build sun.hotspot.WhiteBox + * @compile/module=java.base java/lang/ModuleHelper.java + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. --enable-preview -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SealedInterfaceModuleTest + */ + +public class SealedInterfaceModuleTest { + + // Test sub-classing a sealed super interface in a named module. In this test, + // sealed interface sealedP1/SuperInterface permits sealedP1.C1, sealedP2.C2, and + // sealedP3.C3. All three of those classes implement sealedP1/SuperInterface. + + public static void main(String args[]) throws Throwable { + Object m1x, m2x; + + // Get the class loader for SealedInterfaceModuleTest and assume it's also used + // to load the other classes. + ClassLoader this_cldr = AccessCheckRead.class.getClassLoader(); + + // Define a module for packages sealedP1 and sealedP2. + m1x = ModuleHelper.ModuleObject("module_one", this_cldr, + new String[] { "sealedP1", "sealedP2" }); + ModuleHelper.DefineModule(m1x, false, "9.0", "m1x/here", + new String[] { "sealedP1", "sealedP2" }); + + // Define a module for package sealedP3 with the same class loader. + m2x = ModuleHelper.ModuleObject("module_two", this_cldr, new String[] { "sealedP3" }); + ModuleHelper.DefineModule(m2x, false, "9.0", "m2x/there", new String[] { "sealedP3" }); + + // Make package sealedP1 in m1x visible to everyone because it contains + // the sealed super interface for C1, C2, and C3. + ModuleHelper.AddModuleExportsToAll(m1x, "sealedP1"); + ModuleHelper.AddReadsModule(m2x, m1x); + + // Test subtype in the same named package and named module as its super + // interface. This should succeed. + // Class sealedP1.C1 implements interface sealedP1.SuperInterface. + Class p1_C1_class = Class.forName("sealedP1.C1"); + + // Test non-public class in same module but different package than its + // super interface. This should throw ICCE. + // Class sealedP2.C2 implements interface class sealedP1.SuperInterface. + try { + Class p2_C2_class = Class.forName("sealedP2.C2"); + throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown"); + } catch (IncompatibleClassChangeError e) { + if (!e.getMessage().contains("cannot implement sealed interface")) { + throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage()); + } + } + + // Test subtype in a different module than its super type. This should + // fail even though they have the same class loader. + // Class sealedP3.C3 implements interface sealedP1.SuperInterface. + try { + Class p3_C3_class = Class.forName("sealedP3.C3"); + throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown"); + } catch (IncompatibleClassChangeError e) { + if (!e.getMessage().contains("cannot implement sealed interface")) { + throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage()); + } + } + + } +} diff --git a/test/hotspot/jtreg/runtime/modules/sealedP1/C1.java b/test/hotspot/jtreg/runtime/modules/sealedP1/C1.java index a253eb7dd98..30e53a0fb94 100644 --- a/test/hotspot/jtreg/runtime/modules/sealedP1/C1.java +++ b/test/hotspot/jtreg/runtime/modules/sealedP1/C1.java @@ -24,7 +24,7 @@ // Small class used by SealedModuleTest package sealedP1; -public final class C1 extends sealedP1.SuperClass { +public final class C1 extends sealedP1.SuperClass implements sealedP1.SuperInterface { public C1() { } } diff --git a/test/hotspot/jtreg/runtime/modules/sealedP1/SuperClass.jcod b/test/hotspot/jtreg/runtime/modules/sealedP1/SuperClass.jcod index f598f49b33d..e0cb6297480 100644 --- a/test/hotspot/jtreg/runtime/modules/sealedP1/SuperClass.jcod +++ b/test/hotspot/jtreg/runtime/modules/sealedP1/SuperClass.jcod @@ -103,3 +103,46 @@ class sealedP1/SuperClass { } // end PermittedSubclasses } // Attributes } // end class sealedP1/SuperClass + + +// This is an empty interface that is needed because the subtypes used by test +// SealedModuleTest are also used by test SealedInterfaceModuleTest, which +// tests a sealed interface with this same name. +// +// package sealedP1; +// public interface SuperInterface { } +// +class sealedP1/SuperInterface { + 0xCAFEBABE; + 0; // minor version + 60; // version + [7] { // Constant Pool + ; // first element is empty + class #2; // #1 at 0x0A + Utf8 "sealedP1/SuperInterface"; // #2 at 0x0D + class #4; // #3 at 0x27 + Utf8 "java/lang/Object"; // #4 at 0x2A + Utf8 "SourceFile"; // #5 at 0x3D + Utf8 "SuperInterface.java"; // #6 at 0x4A + } // Constant Pool + + 0x0601; // access [ ACC_PUBLIC ACC_INTERFACE ] + #1;// this_cpx + #3;// super_cpx + + [0] { // Interfaces + } // Interfaces + + [0] { // fields + } // fields + + [0] { // methods + } // methods + + [1] { // Attributes + Attr(#5, 2) { // SourceFile at 0x6E + #6; + } // end SourceFile + } // Attributes +} // end class sealedP1/SuperInterface + diff --git a/test/hotspot/jtreg/runtime/modules/sealedP1/SuperInterface.jcod b/test/hotspot/jtreg/runtime/modules/sealedP1/SuperInterface.jcod new file mode 100644 index 00000000000..1672b03876a --- /dev/null +++ b/test/hotspot/jtreg/runtime/modules/sealedP1/SuperInterface.jcod @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// This sealed class cannot be a java file because its permits clause names +// a class in another package causing javac to issue a compilation error. +// +// Sealed super interface used by SealedInterfaceModuleTest. +// +// package sealedP1; +// +// public sealed interface SuperInterface permits sealedP1.C1, sealedP2.C2, sealedP3.C3 { } +// +class sealedP1/SuperInterface { + 0xCAFEBABE; + 65535; // minor version + 60; // version + [14] { // Constant Pool + ; // first element is empty + class #2; // #1 at 0x0A + Utf8 "sealedP1/SuperInterface"; // #2 at 0x0D + class #4; // #3 at 0x27 + Utf8 "java/lang/Object"; // #4 at 0x2A + Utf8 "SourceFile"; // #5 at 0x3D + Utf8 "SuperInterface.java"; // #6 at 0x4A + Utf8 "PermittedSubclasses"; // #7 at 0x60 + class #9; // #8 at 0x76 + Utf8 "sealedP1/C1"; // #9 at 0x79 + class #11; // #10 at 0x87 + Utf8 "sealedP2/C2"; // #11 at 0x8A + class #13; // #12 at 0x98 + Utf8 "sealedP3/C3"; // #13 at 0x9B + } // Constant Pool + + 0x0601; // access [ ACC_PUBLIC ACC_INTERFACE ] + #1;// this_cpx + #3;// super_cpx + + [0] { // Interfaces + } // Interfaces + + [0] { // fields + } // fields + + [0] { // methods + } // methods + + [2] { // Attributes + Attr(#5, 2) { // SourceFile at 0xB7 + #6; + } // end SourceFile + ; + Attr(#7, 8) { // PermittedSubclasses at 0xBF + 0x00030008000A000C; + } // end PermittedSubclasses + } // Attributes +} // end class sealedP1/SuperInterface + + +// This is an empty class that is needed because the subtypes used by test +// SealedInterfaceModuleTest are also used by test SealedoduleTest, which +// tests a sealed class with this same name. +// +// package sealedP1; +// +// public class SuperClass { } +// +class sealedP1/SuperClass { + 0xCAFEBABE; + 0; // minor version + 60; // version + [13] { // Constant Pool + ; // first element is empty + Method #2 #3; // #1 at 0x0A + class #4; // #2 at 0x0F + NameAndType #5 #6; // #3 at 0x12 + Utf8 "java/lang/Object"; // #4 at 0x17 + Utf8 ""; // #5 at 0x2A + Utf8 "()V"; // #6 at 0x33 + class #8; // #7 at 0x39 + Utf8 "sealedP1/SuperClass"; // #8 at 0x3C + Utf8 "Code"; // #9 at 0x52 + Utf8 "LineNumberTable"; // #10 at 0x59 + Utf8 "SourceFile"; // #11 at 0x6B + Utf8 "SuperClass.java"; // #12 at 0x78 + } // Constant Pool + + 0x0021; // access [ ACC_PUBLIC ACC_SUPER ] + #7;// this_cpx + #2;// super_cpx + + [0] { // Interfaces + } // Interfaces + + [0] { // fields + } // fields + + [1] { // methods + { // Member at 0x96 + 0x0001; // access + #5; // name_cpx + #6; // sig_cpx + [1] { // Attributes + Attr(#9, 29) { // Code at 0x9E + 1; // max_stack + 1; // max_locals + Bytes[5]{ + 0x2AB70001B1; + } + [0] { // Traps + } // end Traps + [1] { // Attributes + Attr(#10, 6) { // LineNumberTable at 0xB5 + [1] { // LineNumberTable + 0 3; // at 0xC1 + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [1] { // Attributes + Attr(#11, 2) { // SourceFile at 0xC3 + #12; + } // end SourceFile + } // Attributes +} // end class sealedP1/SuperClass diff --git a/test/hotspot/jtreg/runtime/modules/sealedP2/C2.java b/test/hotspot/jtreg/runtime/modules/sealedP2/C2.java index 12e62e55810..7874ee110ee 100644 --- a/test/hotspot/jtreg/runtime/modules/sealedP2/C2.java +++ b/test/hotspot/jtreg/runtime/modules/sealedP2/C2.java @@ -24,6 +24,6 @@ // Small class used by SealedModuleTest package sealedP2; -final class C2 extends sealedP1.SuperClass { +final class C2 extends sealedP1.SuperClass implements sealedP1.SuperInterface { public void method2() { } } diff --git a/test/hotspot/jtreg/runtime/modules/sealedP3/C3.java b/test/hotspot/jtreg/runtime/modules/sealedP3/C3.java index d2720795e71..07adc122c86 100644 --- a/test/hotspot/jtreg/runtime/modules/sealedP3/C3.java +++ b/test/hotspot/jtreg/runtime/modules/sealedP3/C3.java @@ -24,6 +24,6 @@ // Small class used by SealedModuleTest package sealedP3; -public final class C3 extends sealedP1.SuperClass { +public final class C3 extends sealedP1.SuperClass implements sealedP1.SuperInterface { public void method3() { } } diff --git a/test/hotspot/jtreg/runtime/sealedClasses/Pkg/SealedInterface.jcod b/test/hotspot/jtreg/runtime/sealedClasses/Pkg/SealedInterface.jcod index c16a344b24c..16c8480fce8 100644 --- a/test/hotspot/jtreg/runtime/sealedClasses/Pkg/SealedInterface.jcod +++ b/test/hotspot/jtreg/runtime/sealedClasses/Pkg/SealedInterface.jcod @@ -26,13 +26,13 @@ // // package Pkg; // -// sealed public interface SealedInterface permits Permitted, otherPkg.WrongPackage { } +// sealed public interface SealedInterface permits Permitted, otherPkg.WrongPackage, otherPkg.WrongPackageNotPublic { } class Pkg/SealedInterface { 0xCAFEBABE; 65535; // minor version 60; // version - [12] { // Constant Pool + [14] { // Constant Pool ; // first element is empty class #2; // #1 at 0x0A Utf8 "Pkg/SealedInterface"; // #2 at 0x0D @@ -45,6 +45,8 @@ class Pkg/SealedInterface { Utf8 "Pkg/Permitted"; // #9 at 0x74 class #11; // #10 at 0x84 Utf8 "otherPkg/WrongPackage"; // #11 at 0x87 + class #13; // #12 + Utf8 "otherPkg/WrongPackageNotPublic"; // #13 } // Constant Pool 0x0601; // access [ ACC_PUBLIC ACC_INTERFACE ] @@ -65,8 +67,8 @@ class Pkg/SealedInterface { #6; } // end SourceFile ; - Attr(#7, 6) { // PermittedSubtclasses at 0xB5 - 0x00020008000A; + Attr(#7, 8) { // PermittedSubtclasses at 0xB5 + 0x00030008000A000C; } // end PermittedSubclasses } // Attributes } // end class Pkg/SealedInterface diff --git a/test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleIntfTest.java b/test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleIntfTest.java index 63f2055021c..f5757894b95 100644 --- a/test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleIntfTest.java +++ b/test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleIntfTest.java @@ -25,7 +25,7 @@ * @test * @bug 8225056 * @compile Pkg/SealedInterface.jcod Pkg/NotPermitted.jcod - * @compile --enable-preview -source ${jdk.version} Pkg/Permitted.java otherPkg/WrongPackage.java + * @compile --enable-preview -source ${jdk.version} Pkg/Permitted.java otherPkg/WrongPackage.java otherPkg/WrongPackageNotPublic.java * @run main/othervm --enable-preview SealedUnnamedModuleIntfTest */ @@ -33,14 +33,18 @@ public class SealedUnnamedModuleIntfTest { public static void main(String args[]) throws Throwable { - // Classes Permitted, NotPermitted, and WrongPackage all try to implement + // Classes Permitted, NotPermitted, WrongPackage and WrongPackageNotPublic all try to implement // sealed interface SealedInterface. - // Interface SealedInterface permits classes Permitted and WrongPackage. + // Interface SealedInterface permits classes Permitted, WrongPackage, and WrongPackageNotPublic; // Test non-public permitted subclass and superclass in unnamed module and // same package. This should succeed. Class permitted = Class.forName("Pkg.Permitted"); + // Test public permitted subclass and superclass in same unnamed module but in + // different packages. This should not throw an exception. + Class wrongPkg = Class.forName("otherPkg.WrongPackage"); + // Test unpermitted subclass and superclass in unnamed module and same package. // This should throw an exception. try { @@ -52,8 +56,15 @@ public static void main(String args[]) throws Throwable { } } - // Test public permitted subclass and superclass in same unnamed module but in - // different packages. This should not throw an exception. - Class wrongPkg = Class.forName("otherPkg.WrongPackage"); + // Test non-public permitted subclass and superclass in same unnamed module but + // in different packages. This should throw an exception. + try { + Class notPermitted = Class.forName("otherPkg.WrongPackageNotPublic"); + throw new RuntimeException("Expected IncompatibleClassChangeError exception not thrown"); + } catch (IncompatibleClassChangeError e) { + if (!e.getMessage().contains("cannot implement sealed interface")) { + throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage()); + } + } } } diff --git a/test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleTest.java b/test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleTest.java index d8a7b8a8bf8..f74b4713dfa 100644 --- a/test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleTest.java +++ b/test/hotspot/jtreg/runtime/sealedClasses/SealedUnnamedModuleTest.java @@ -25,7 +25,7 @@ * @test * @bug 8225056 * @compile planets/OuterPlanets.jcod planets/Mars.jcod - * @compile --enable-preview -source ${jdk.version} planets/Neptune.java asteroids/Pluto.java + * @compile --enable-preview -source ${jdk.version} planets/Neptune.java asteroids/Pluto.java asteroids/Charon.java * @run main/othervm --enable-preview SealedUnnamedModuleTest */ @@ -33,8 +33,8 @@ public class SealedUnnamedModuleTest { public static void main(String args[]) throws Throwable { - // Classes Neptune, Mars, and Pluto all try to extend sealed class OuterPlanets. - // Class OuterPlanets permits Nepturn and Pluto. + // Classes Neptune, Mars, Pluto, and Charon all try to extend sealed class OuterPlanets. + // Class OuterPlanets permits Nepturn, Pluto, and Charon. // Test permitted subclass and superclass in unnamed module and same package. // This should succeed. @@ -61,5 +61,9 @@ public static void main(String args[]) throws Throwable { throw new RuntimeException("Wrong IncompatibleClassChangeError exception thrown: " + e.getMessage()); } } + + // Test public permitted subclass and superclass in same unnamed module but + // in different packages. This should succeed. + Class charon = Class.forName("asteroids.Charon"); } } diff --git a/src/hotspot/share/runtime/extendedPC.hpp b/test/hotspot/jtreg/runtime/sealedClasses/asteroids/Charon.java similarity index 65% rename from src/hotspot/share/runtime/extendedPC.hpp rename to test/hotspot/jtreg/runtime/sealedClasses/asteroids/Charon.java index fb3288a1a27..6b5f3f442c9 100644 --- a/src/hotspot/share/runtime/extendedPC.hpp +++ b/test/hotspot/jtreg/runtime/sealedClasses/asteroids/Charon.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -19,25 +19,9 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. - * */ -#ifndef SHARE_RUNTIME_EXTENDEDPC_HPP -#define SHARE_RUNTIME_EXTENDEDPC_HPP - -#include "utilities/globalDefinitions.hpp" - -// An ExtendedPC contains the _pc from a signal handler in a platform -// independent way. - -class ExtendedPC { - private: - address _pc; +package asteroids; - public: - address pc() const { return _pc; } - ExtendedPC(address pc) { _pc = pc; } - ExtendedPC() { _pc = NULL; } -}; +public final class Charon extends planets.OuterPlanets { } -#endif // SHARE_RUNTIME_EXTENDEDPC_HPP diff --git a/test/hotspot/jtreg/runtime/sealedClasses/otherPkg/WrongPackageNotPublic.java b/test/hotspot/jtreg/runtime/sealedClasses/otherPkg/WrongPackageNotPublic.java new file mode 100644 index 00000000000..294ee8776cc --- /dev/null +++ b/test/hotspot/jtreg/runtime/sealedClasses/otherPkg/WrongPackageNotPublic.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package otherPkg; + +final class WrongPackageNotPublic implements Pkg.SealedInterface { } diff --git a/test/hotspot/jtreg/runtime/sealedClasses/planets/OuterPlanets.jcod b/test/hotspot/jtreg/runtime/sealedClasses/planets/OuterPlanets.jcod index f354a939d1f..615a5c885f6 100644 --- a/test/hotspot/jtreg/runtime/sealedClasses/planets/OuterPlanets.jcod +++ b/test/hotspot/jtreg/runtime/sealedClasses/planets/OuterPlanets.jcod @@ -23,13 +23,13 @@ // package planets; // -// sealed public class OuterPlanets permits Neptune, asteroids.Pluto { } +// sealed public class OuterPlanets permits Neptune, asteroids.Pluto, asteroids.Charon { } class planets/OuterPlanets { 0xCAFEBABE; 65535; // minor version 60; // version - [18] { // Constant Pool + [20] { // Constant Pool ; // first element is empty Method #2 #3; // #1 at 0x0A class #4; // #2 at 0x0F @@ -48,6 +48,8 @@ class planets/OuterPlanets { Utf8 "planets/Neptune"; // #15 at 0xA4 class #17; // #16 at 0xB6 Utf8 "asteroids/Pluto"; // #17 at 0xB9 + class #19; // #18 at 0xB6 + Utf8 "asteroids/Charon"; // #19 } // Constant Pool 0x0021; // access [ ACC_PUBLIC ACC_SUPER ] @@ -91,8 +93,8 @@ class planets/OuterPlanets { #12; } // end SourceFile ; - Attr(#13, 6) { // PermittedSubclasses at 0x010C - 0x0002000E0010; + Attr(#13, 8) { // PermittedSubclasses at 0x010C + 0x0003000E00100012; } // end PermittedSubclasses } // Attributes } // end class planets/OuterPlanets diff --git a/test/hotspot/jtreg/runtime/whitebox/TestWBDeflateIdleMonitors.java b/test/hotspot/jtreg/runtime/whitebox/TestWBDeflateIdleMonitors.java new file mode 100644 index 00000000000..ae8f02196c9 --- /dev/null +++ b/test/hotspot/jtreg/runtime/whitebox/TestWBDeflateIdleMonitors.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package runtime.whitebox; + +/* + * @test + * @bug 8246477 + * @summary Test to verify that WB method deflateIdleMonitors works correctly. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run driver runtime.whitebox.TestWBDeflateIdleMonitors + */ +import jdk.test.lib.Asserts; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.WhiteBox; + +public class TestWBDeflateIdleMonitors { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createTestJvm( + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-Xlog:monitorinflation=info", + InflateMonitorsTest.class.getName()); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + System.out.println(output.getStdout()); + output.shouldHaveExitValue(0); + output.shouldContain("WhiteBox initiated DeflateIdleMonitors"); + } + + public static class InflateMonitorsTest { + static WhiteBox wb = WhiteBox.getWhiteBox(); + public static Object obj; + + public static void main(String args[]) { + obj = new Object(); + synchronized (obj) { + // HotSpot implementation detail: asking for the hash code + // when the object is locked causes monitor inflation. + if (obj.hashCode() == 0xBAD) System.out.println("!"); + Asserts.assertEQ(wb.isMonitorInflated(obj), true, + "Monitor should be inflated."); + } + boolean did_deflation = wb.deflateIdleMonitors(); + Asserts.assertEQ(did_deflation, true, + "deflateIdleMonitors() should have worked."); + Asserts.assertEQ(wb.isMonitorInflated(obj), false, + "Monitor should be deflated."); + } + } +} diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java index 8f81be763be..cee7bebbd50 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,9 @@ * Results of running the JstatGcTool ("jstat -gccapacity ") * * Output example: - * NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC YGC FGC - * 41984.0 671744.0 41984.0 5248.0 5248.0 31488.0 83968.0 1343488.0 83968.0 83968.0 512.0 110592.0 4480.0 0 0 - + * NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC CGC + * 0.0 4194304.0 6144.0 0.0 2048.0 4096.0 0.0 4194304.0 2048.0 2048.0 0.0 1056768.0 7680.0 0.0 1048576.0 768.0 4 0 0 + * * Output description: * NGCMN Minimum new generation capacity (KB). * NGCMX Maximum new generation capacity (KB). diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java index 62610fe27fd..b40f6629391 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java @@ -25,9 +25,9 @@ * Results of running the JstatGcTool ("jstat -gccause ") * * Output example: - * S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT LGCC GCC - * 0.00 6.25 46.19 0.34 57.98 54.63 15305 1270.551 0 0.000 0 0.00 1270.551 Allocation Failure No GC - + * S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT LGCC GCC + * 0.00 0.00 0.00 53.70 97.40 92.67 4 0.286 19 17.890 2 0.086 18.263 System.gc() No GC + * * Output description: * S0 Survivor space 0 utilization as a percentage of the space's current capacity. * S1 Survivor space 1 utilization as a percentage of the space's current capacity. diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewResults.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewResults.java index 109b4d210e5..b10cb345775 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewResults.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcNewResults.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,9 @@ * Results of running the JstatGcTool ("jstat -gcnew ") * * Output example: - * S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT - * 0.0 7168.0 0.0 7168.0 15 15 3584.0 62464.0 5120.0 27 0.340 - + * S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT + * 0.0 2048.0 0.0 1113.5 15 15 1024.0 4096.0 0.0 4 0.228 + * * Output description: * S0C Current survivor space 0 capacity (KB). * S1C Current survivor space 1 capacity (KB). diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcResults.java b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcResults.java index e2d039e19a1..9b2bd24d6c2 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcResults.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcResults.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ * Results of running the JstatGcTool ("jstat -gc ") * * Output example: - * S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT - * 512.0 512.0 32.0 0.0 288768.0 168160.6 83968.0 288.1 4864.0 2820.3 512.0 279.7 18510 1559.208 0 0.000 0 0.0 1559.208 + * S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT + * 0.0 2048.0 0.0 1079.5 4096.0 0.0 2048.0 0.0 7680.0 7378.6 768.0 664.7 4 0.140 0 0.000 0 0.000 0.140 * * Output description: * S0C Current survivor space 0 capacity (KB). diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/TestDescription.java index c77f621ac01..7f081c52fce 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,11 @@ * * @library /vmTestbase * /test/lib + * @comment some of the tests from forceEarlyReturn001.tests need WhiteBox + * @modules java.base/jdk.internal.misc:+open + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * * @run driver jdk.test.lib.FileInstaller . . * * @comment build classes required for tests from forceEarlyReturn001.tests @@ -64,7 +69,8 @@ * -waittime=5 * -debugee.vmkind=java * -transport.address=dynamic - * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * "-debugee.vmkeys=-Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI ${test.vm.opts} ${test.java.opts}" * -testClassPath ${test.class.path} * -configFile ./forceEarlyReturn001.tests */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/TestDescription.java index c5ec223c7ca..87612557076 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/TestDescription.java @@ -39,6 +39,11 @@ * * @library /vmTestbase * /test/lib + * @comment some of the tests from forceEarlyReturn002.tests need WhiteBox + * @modules java.base/jdk.internal.misc:+open + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * * @run driver jdk.test.lib.FileInstaller . . * * @comment build classes required for tests from forceEarlyReturn002.tests @@ -66,7 +71,8 @@ * -waittime=5 * -debugee.vmkind=java * -transport.address=dynamic - * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * "-debugee.vmkeys=-Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI ${test.vm.opts} ${test.java.opts}" * -testClassPath ${test.class.path} * -configFile ./forceEarlyReturn002.tests * -testWorkDir . diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java index 95bf37ae580..8514a16bf50 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,11 @@ * * @library /vmTestbase * /test/lib + * @comment some of the tests from heapwalking001.tests need WhiteBox + * @modules java.base/jdk.internal.misc:+open + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * * @run driver jdk.test.lib.FileInstaller . . * * @comment build classes required for tests from heapwalking001.tests @@ -58,7 +63,8 @@ * -waittime=5 * -debugee.vmkind=java * -transport.address=dynamic - * "-debugee.vmkeys=-Xmx256M ${test.vm.opts} ${test.java.opts}" + * "-debugee.vmkeys=-Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -Xmx256M ${test.vm.opts} ${test.java.opts}" * -testClassPath ${test.class.path} * -configFile ./heapwalking001.tests */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/TestDescription.java index 13ad382b49b..3b32e597b61 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking002/TestDescription.java @@ -39,6 +39,11 @@ * * @library /vmTestbase * /test/lib + * @comment some of the tests from heapwalking002.tests need WhiteBox + * @modules java.base/jdk.internal.misc:+open + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * * @run driver jdk.test.lib.FileInstaller . . * * @comment build classes required for tests from heapwalking002.tests @@ -60,7 +65,8 @@ * -waittime=5 * -debugee.vmkind=java * -transport.address=dynamic - * "-debugee.vmkeys=-Xmx256M ${test.vm.opts} ${test.java.opts}" + * "-debugee.vmkeys=-Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -Xmx256M ${test.vm.opts} ${test.java.opts}" * -testClassPath ${test.class.path} * -configFile ./heapwalking002.tests * -testWorkDir . diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/TestDescription.java index 5c8f0d16ac0..b47bd71aeb9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,11 @@ * * @library /vmTestbase * /test/lib + * @comment some of the tests from mixed001.tests need WhiteBox + * @modules java.base/jdk.internal.misc:+open + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * * @run driver jdk.test.lib.FileInstaller . . * * @comment build classes required for tests from mixed001.tests @@ -68,7 +73,8 @@ * -waittime=5 * -debugee.vmkind=java * -transport.address=dynamic - * "-debugee.vmkeys=-Xmx256M ${test.vm.opts} ${test.java.opts}" + * "-debugee.vmkeys=-Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -Xmx256M ${test.vm.opts} ${test.java.opts}" * -testClassPath ${test.class.path} * -configFile ./mixed001.tests */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java index 4afd5458a65..87859a1d7e2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java @@ -40,6 +40,11 @@ * * @library /vmTestbase * /test/lib + * @comment some of the tests from mixed002.tests need WhiteBox + * @modules java.base/jdk.internal.misc:+open + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * * @run driver jdk.test.lib.FileInstaller . . * * @comment build classes required for tests from mixed002.tests @@ -66,7 +71,8 @@ * -waittime=5 * -debugee.vmkind=java * -transport.address=dynamic - * "-debugee.vmkeys=-Xmx256M ${test.vm.opts} ${test.java.opts}" + * "-debugee.vmkeys=-Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -Xmx256M ${test.vm.opts} ${test.java.opts}" * -testClassPath ${test.class.path} * -configFile ./mixed002.tests * -testWorkDir . diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/TestDescription.java index f43557b5df4..95c2ca7b44c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,11 @@ * * @library /vmTestbase * /test/lib + * @comment some of the tests from monitorEvents001.tests need WhiteBox + * @modules java.base/jdk.internal.misc:+open + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * * @run driver jdk.test.lib.FileInstaller . . * * @comment build classes required for tests from monitorEvents001.tests @@ -53,7 +58,8 @@ * -waittime=5 * -debugee.vmkind=java * -transport.address=dynamic - * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * "-debugee.vmkeys=-Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI ${test.vm.opts} ${test.java.opts}" * -testClassPath ${test.class.path} * -configFile ./monitorEvents001.tests */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/TestDescription.java index 2285aef0c9c..2b2a2bc403f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/monitorEvents002/TestDescription.java @@ -40,6 +40,11 @@ * * @library /vmTestbase * /test/lib + * @comment some of the tests from monitorEvents002.tests need WhiteBox + * @modules java.base/jdk.internal.misc:+open + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * * @run driver jdk.test.lib.FileInstaller . . * * @comment build classes required for tests from monitorEvents002.tests @@ -55,7 +60,8 @@ * -waittime=5 * -debugee.vmkind=java * -transport.address=dynamic - * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * "-debugee.vmkeys=-Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI ${test.vm.opts} ${test.java.opts}" * -testClassPath ${test.class.path} * -configFile ./monitorEvents002.tests * -testWorkDir . diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/TestDescription.java index a3667ec89bb..dc25f24ec3d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,11 @@ * * @library /vmTestbase * /test/lib + * @comment some of the tests from ownedMonitorsAndFrames001.tests need WhiteBox + * @modules java.base/jdk.internal.misc:+open + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * * @run driver jdk.test.lib.FileInstaller . . * * @comment build classes required for tests from ownedMonitorsAndFrames001.tests @@ -57,7 +62,8 @@ * -waittime=5 * -debugee.vmkind=java * -transport.address=dynamic - * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * "-debugee.vmkeys=-Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI ${test.vm.opts} ${test.java.opts}" * -testClassPath ${test.class.path} * -configFile ./ownedMonitorsAndFrames001.tests */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java index 4ec8baac002..fdb61c7195a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java @@ -39,6 +39,11 @@ * * @library /vmTestbase * /test/lib + * @comment some of the tests from ownedMonitorsAndFrames002.tests need WhiteBox + * @modules java.base/jdk.internal.misc:+open + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * * @run driver jdk.test.lib.FileInstaller . . * * @comment build classes required for tests from ownedMonitorsAndFrames002.tests @@ -61,7 +66,8 @@ * -waittime=5 * -debugee.vmkind=java * -transport.address=dynamic - * "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}" + * "-debugee.vmkeys=-Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI ${test.vm.opts} ${test.java.opts}" * -testClassPath ${test.class.path} * -configFile ./ownedMonitorsAndFrames002.tests * -testWorkDir . diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/SerialExecutionDebuggee.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/SerialExecutionDebuggee.java index 32603119704..6bd3d5f7339 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/SerialExecutionDebuggee.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/SerialExecutionDebuggee.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ import java.io.StreamTokenizer; import java.io.StringReader; import nsk.share.Consts; +import sun.hotspot.WhiteBox; /* * This class is intended for execution several JDI tests in single VM and used together with nsk.share.jdi.SerialExecutionDebugger @@ -41,6 +42,8 @@ * For more detailed description of serial test execution see SerialExecutionDebugger */ public class SerialExecutionDebuggee extends AbstractJDIDebuggee { + private final WhiteBox WB = WhiteBox.getWhiteBox(); + public static void main(String args[]) { new SerialExecutionDebuggee().doTest(args); } @@ -129,6 +132,15 @@ public boolean parseCommand(String command) { } else if (command.equals(COMMAND_CLEAR_DEBUGGEE)) { currentDebuggee = null; + // The debuggee can intentionally create inflated monitors. + // With async deflation, this can pin a StateTestThread object + // until the next deflation cycle. This can confuse tests run + // by nsk/jdi/stress/serial/mixed002/TestDescription.java that + // expect only one StateTestThread object to exist in each + // of the debugger tests that mixed002 runs serially in the + // same VM. + WB.deflateIdleMonitors(); + return true; } diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index ac1cf8fe3f2..d1dc3124aaa 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -593,6 +593,8 @@ java/io/pathNames/GeneralWin32.java 8180264 windows- com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java 8030957 aix-all com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java 8030957 aix-all +java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java 8247426 generic-all + sun/management/jdp/JdpDefaultsTest.java 8241865 macosx-all sun/management/jdp/JdpJmxRemoteDynamicPortTest.java 8241865 macosx-all sun/management/jdp/JdpSpecificAddressTest.java 8241865 macosx-all @@ -628,6 +630,8 @@ java/nio/channels/AsynchronousSocketChannel/StressLoopback.java 8211851 aix-ppc6 java/nio/channels/Selector/Wakeup.java 6963118 windows-all +sun/nio/ch/TestMaxCachedBufferSize.java 8212812 macosx-all + ############################################################################ # jdk_rmi @@ -699,10 +703,6 @@ javax/security/auth/kerberos/KerberosTixDateTest.java 8039280 generic- sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.java 8039280 generic-all sun/security/provider/PolicyParser/ExtDirsChange.java 8039280 generic-all sun/security/provider/PolicyParser/PrincipalExpansionError.java 8039280 generic-all -sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java 8247359 linux-aarch64 -sun/security/provider/SecureRandom/SHA1PRNGReseed.java 8247359 linux-aarch64 -sun/security/provider/SecureRandom/StrongSecureRandom.java 8247359 linux-aarch64 -sun/security/provider/SeedGenerator/SeedGeneratorChoice.java 8247359 linux-aarch64 ############################################################################ @@ -914,9 +914,21 @@ javax/script/Test7.java 8239361 generic- jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990,8229370 generic-all jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic-all +jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all ############################################################################ # jdk_internal ############################################################################ + +# jdk_jpackage + +tools/jpackage/share/EmptyFolderPackageTest.java 8248059 macosx-all +tools/jpackage/share/IconTest.java 8248059 macosx-all +tools/jpackage/share/AppImagePackageTest.java 8248059 macosx-all +tools/jpackage/share/SimplePackageTest.java 8248059 macosx-all +tools/jpackage/share/jdk/jpackage/tests/BasicTest.java 8248059 macosx-all +tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java#id0 8248418 generic-all + +############################################################################ diff --git a/test/jdk/java/foreign/TestMismatch.java b/test/jdk/java/foreign/TestMismatch.java index e57de6ca73a..5c361a82fe9 100644 --- a/test/jdk/java/foreign/TestMismatch.java +++ b/test/jdk/java/foreign/TestMismatch.java @@ -117,12 +117,28 @@ public void testLarge() { assertEquals(s1.mismatch(s2), -1); assertEquals(s2.mismatch(s1), -1); - for (long i = s2.byteSize() -1 ; i >= Integer.MAX_VALUE - 10L; i--) { - BYTE_HANDLE.set(s2.baseAddress().addOffset(i), (byte) 0xFF); - long expectedMismatchOffset = i; - assertEquals(s1.mismatch(s2), expectedMismatchOffset); - assertEquals(s2.mismatch(s1), expectedMismatchOffset); - } + testLargeAcrossMaxBoundary(s1, s2); + + testLargeMismatchAcrossMaxBoundary(s1, s2); + } + } + + private void testLargeAcrossMaxBoundary(MemorySegment s1, MemorySegment s2) { + for (long i = s2.byteSize() -1 ; i >= Integer.MAX_VALUE - 10L; i--) { + var s3 = s1.asSlice(0, i); + var s4 = s2.asSlice(0, i); + assertEquals(s3.mismatch(s3), -1); + assertEquals(s3.mismatch(s4), -1); + assertEquals(s4.mismatch(s3), -1); + } + } + + private void testLargeMismatchAcrossMaxBoundary(MemorySegment s1, MemorySegment s2) { + for (long i = s2.byteSize() -1 ; i >= Integer.MAX_VALUE - 10L; i--) { + BYTE_HANDLE.set(s2.baseAddress().addOffset(i), (byte) 0xFF); + long expectedMismatchOffset = i; + assertEquals(s1.mismatch(s2), expectedMismatchOffset); + assertEquals(s2.mismatch(s1), expectedMismatchOffset); } } diff --git a/test/jdk/java/io/Serializable/records/BasicRecordSer.java b/test/jdk/java/io/Serializable/records/BasicRecordSer.java index 0054faa6c49..4454c804c4b 100644 --- a/test/jdk/java/io/Serializable/records/BasicRecordSer.java +++ b/test/jdk/java/io/Serializable/records/BasicRecordSer.java @@ -132,6 +132,20 @@ public void testSerializable(Object objToSerialize) throws Exception { assertEquals(objDeserialized, objToSerialize); } + /** Tests serializing and deserializing of local records. */ + @Test + public void testLocalRecord() throws Exception { + out.println("\n---"); + record Point(int x, int y) implements Serializable { } + record Rectangle(Point bottomLeft, Point topRight) implements Serializable { } + var objToSerialize = new Rectangle(new Point(0, 1), new Point (5, 6)); + out.println("serializing : " + objToSerialize); + var objDeserialized = serializeDeserialize(objToSerialize); + out.println("deserialized: " + objDeserialized); + assertEquals(objToSerialize, objDeserialized); + assertEquals(objDeserialized, objToSerialize); + } + /** Tests back references of Serializable record objects in the stream. */ @Test public void testSerializableBackRefs() throws Exception { diff --git a/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java b/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java new file mode 100644 index 00000000000..82cb31d86c2 --- /dev/null +++ b/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java @@ -0,0 +1,563 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Checks that the appropriate value is given to the canonical ctr + * @compile --enable-preview -source ${jdk.version} DifferentStreamFieldsTest.java + * @run testng/othervm --enable-preview DifferentStreamFieldsTest + * @run testng/othervm/java.security.policy=empty_security.policy --enable-preview DifferentStreamFieldsTest + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static java.io.ObjectStreamConstants.SC_SERIALIZABLE; +import static java.io.ObjectStreamConstants.STREAM_MAGIC; +import static java.io.ObjectStreamConstants.STREAM_VERSION; +import static java.io.ObjectStreamConstants.TC_CLASSDESC; +import static java.io.ObjectStreamConstants.TC_ENDBLOCKDATA; +import static java.io.ObjectStreamConstants.TC_NULL; +import static java.io.ObjectStreamConstants.TC_OBJECT; +import static java.io.ObjectStreamConstants.TC_STRING; +import static java.lang.System.out; +import static org.testng.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InvalidClassException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.io.UncheckedIOException; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Checks that the appropriate value is given to the canonical ctr. + */ +public class DifferentStreamFieldsTest { + + record R01(boolean x) implements Serializable {} + + record R02(byte x) implements Serializable {} + + record R03(short x) implements Serializable {} + + record R04(char x) implements Serializable {} + + record R05(int x) implements Serializable {} + + record R06(long x) implements Serializable {} + + record R07(float x) implements Serializable {} + + record R08(double x) implements Serializable {} + + record R09(Object x) implements Serializable {} + + record R10(String x) implements Serializable {} + + record R11(int[]x) implements Serializable {} + + record R12(Object[]x) implements Serializable {} + + record R13(R12 x) implements Serializable {} + + record R14(R13[]x) implements Serializable {} + + @DataProvider(name = "recordTypeAndExpectedValue") + public Object[][] recordTypeAndExpectedValue() { + return new Object[][]{ + new Object[]{R01.class, false}, + new Object[]{R02.class, (byte) 0}, + new Object[]{R03.class, (short) 0}, + new Object[]{R04.class, '\u0000'}, + new Object[]{R05.class, 0}, + new Object[]{R06.class, 0L}, + new Object[]{R07.class, 0.0f}, + new Object[]{R08.class, 0.0d}, + new Object[]{R09.class, null}, + new Object[]{R10.class, null}, + new Object[]{R11.class, null}, + new Object[]{R12.class, null}, + new Object[]{R13.class, null}, + new Object[]{R14.class, null} + }; + } + + @Test(dataProvider = "recordTypeAndExpectedValue") + public void testWithDifferentTypes(Class clazz, Object expectedXValue) + throws Exception { + out.println("\n---"); + assert clazz.isRecord(); + byte[] bytes = SerialByteStreamBuilder + .newBuilder(clazz.getName()) + .build(); + + Object obj = deserialize(bytes); + out.println("deserialized: " + obj); + Object actualXValue = clazz.getDeclaredMethod("x").invoke(obj); + assertEquals(actualXValue, expectedXValue); + + bytes = SerialByteStreamBuilder + .newBuilder(clazz.getName()) + .addPrimitiveField("y", int.class, 5) // stream junk + .build(); + + obj = deserialize(bytes); + out.println("deserialized: " + obj); + actualXValue = clazz.getDeclaredMethod("x").invoke(obj); + assertEquals(actualXValue, expectedXValue); + } + + // --- all together + + @Test + public void testWithAllTogether() throws Exception { + out.println("\n---"); + record R15(boolean a, byte b, short c, char d, int e, long f, float g, + double h, Object i, String j, long[]k, Object[]l) + implements Serializable {} + + byte[] bytes = SerialByteStreamBuilder + .newBuilder(R15.class.getName()) + .addPrimitiveField("x", int.class, 5) // stream junk + .build(); + + R15 obj = deserialize(bytes); + out.println("deserialized: " + obj); + assertEquals(obj.a, false); + assertEquals(obj.b, 0); + assertEquals(obj.c, 0); + assertEquals(obj.d, '\u0000'); + assertEquals(obj.e, 0); + assertEquals(obj.f, 0l); + assertEquals(obj.g, 0f); + assertEquals(obj.h, 0d); + assertEquals(obj.i, null); + assertEquals(obj.j, null); + assertEquals(obj.k, null); + assertEquals(obj.l, null); + } + + @Test + public void testInt() throws Exception { + out.println("\n---"); + { + record R(int x) implements Serializable {} + + var r = new R(5); + byte[] OOSBytes = serialize(r); + + byte[] builderBytes = SerialByteStreamBuilder + .newBuilder(R.class.getName()) + .addPrimitiveField("x", int.class, 5) + .build(); + + var deser1 = deserialize(OOSBytes); + assertEquals(deser1, r); + var deser2 = deserialize(builderBytes); + assertEquals(deser2, deser1); + } + { + record R(int x, int y) implements Serializable {} + + var r = new R(7, 8); + byte[] OOSBytes = serialize(r); + var deser1 = deserialize(OOSBytes); + assertEquals(deser1, r); + + byte[] builderBytes = SerialByteStreamBuilder + .newBuilder(R.class.getName()) + .addPrimitiveField("x", int.class, 7) + .addPrimitiveField("y", int.class, 8) + .build(); + + var deser2 = deserialize(builderBytes); + assertEquals(deser2, deser1); + + builderBytes = SerialByteStreamBuilder + .newBuilder(R.class.getName()) + .addPrimitiveField("y", int.class, 8) // reverse order + .addPrimitiveField("x", int.class, 7) + .build(); + deser2 = deserialize(builderBytes); + assertEquals(deser2, deser1); + + builderBytes = SerialByteStreamBuilder + .newBuilder(R.class.getName()) + .addPrimitiveField("w", int.class, 6) // additional fields + .addPrimitiveField("x", int.class, 7) + .addPrimitiveField("y", int.class, 8) + .addPrimitiveField("z", int.class, 9) // additional fields + .build(); + deser2 = deserialize(builderBytes); + assertEquals(deser2, deser1); + + r = new R(0, 0); + OOSBytes = serialize(r); + deser1 = deserialize(OOSBytes); + assertEquals(deser1, r); + + builderBytes = SerialByteStreamBuilder + .newBuilder(R.class.getName()) + .addPrimitiveField("y", int.class, 0) + .addPrimitiveField("x", int.class, 0) + .build(); + deser2 = deserialize(builderBytes); + assertEquals(deser2, deser1); + + builderBytes = SerialByteStreamBuilder + .newBuilder(R.class.getName()) // no field values + .build(); + deser2 = deserialize(builderBytes); + assertEquals(deser2, deser1); + } + } + + @Test + public void testString() throws Exception { + out.println("\n---"); + + record Str(String part1, String part2) implements Serializable {} + + var r = new Str("Hello", "World!"); + var deser1 = deserialize(serialize(r)); + assertEquals(deser1, r); + + byte[] builderBytes = SerialByteStreamBuilder + .newBuilder(Str.class.getName()) + .addField("part1", String.class, "Hello") + .addField("part2", String.class, "World!") + .build(); + + var deser2 = deserialize(builderBytes); + assertEquals(deser2, deser1); + + builderBytes = SerialByteStreamBuilder + .newBuilder(Str.class.getName()) + .addField("cruft", String.class, "gg") + .addField("part1", String.class, "Hello") + .addField("part2", String.class, "World!") + .addPrimitiveField("x", int.class, 13) + .build(); + + var deser3 = deserialize(builderBytes); + assertEquals(deser3, deser1); + } + + @Test + public void testArrays() throws Exception { + out.println("\n---"); + { + record IntArray(int[]ints, long[]longs) implements Serializable {} + IntArray r = new IntArray(new int[]{5, 4, 3, 2, 1}, new long[]{9L}); + IntArray deser1 = deserialize(serialize(r)); + assertEquals(deser1.ints(), r.ints()); + assertEquals(deser1.longs(), r.longs()); + + byte[] builderBytes = SerialByteStreamBuilder + .newBuilder(IntArray.class.getName()) + .addField("ints", int[].class, new int[]{5, 4, 3, 2, 1}) + .addField("longs", long[].class, new long[]{9L}) + .build(); + + IntArray deser2 = deserialize(builderBytes); + assertEquals(deser2.ints(), deser1.ints()); + assertEquals(deser2.longs(), deser1.longs()); + } + { + record StrArray(String[]stringArray) implements Serializable {} + StrArray r = new StrArray(new String[]{"foo", "bar"}); + StrArray deser1 = deserialize(serialize(r)); + assertEquals(deser1.stringArray(), r.stringArray()); + + byte[] builderBytes = SerialByteStreamBuilder + .newBuilder(StrArray.class.getName()) + .addField("stringArray", String[].class, new String[]{"foo", "bar"}) + .build(); + + StrArray deser2 = deserialize(builderBytes); + assertEquals(deser2.stringArray(), deser1.stringArray()); + } + } + + @Test + public void testCompatibleFieldTypeChange() throws Exception { + out.println("\n---"); + + { + record NumberHolder(Number n) implements Serializable {} + + var r = new NumberHolder(123); + var deser1 = deserialize(serialize(r)); + assertEquals(deser1, r); + + byte[] builderBytes = SerialByteStreamBuilder + .newBuilder(NumberHolder.class.getName()) + .addField("n", Integer.class, 123) + .build(); + + var deser2 = deserialize(builderBytes); + assertEquals(deser2, deser1); + } + + { + record IntegerHolder(Integer i) implements Serializable {} + + var r = new IntegerHolder(123); + var deser1 = deserialize(serialize(r)); + assertEquals(deser1, r); + + byte[] builderBytes = SerialByteStreamBuilder + .newBuilder(IntegerHolder.class.getName()) + .addField("i", Number.class, 123) + .build(); + + var deser2 = deserialize(builderBytes); + assertEquals(deser2, deser1); + } + } + + @Test + public void testIncompatibleRefFieldTypeChange() throws Exception { + out.println("\n---"); + + record StringHolder(String s) implements Serializable {} + + var r = new StringHolder("123"); + var deser1 = deserialize(serialize(r)); + assertEquals(deser1, r); + + byte[] builderBytes = SerialByteStreamBuilder + .newBuilder(StringHolder.class.getName()) + .addField("s", Integer.class, 123) + .build(); + + try { + var deser2 = deserialize(builderBytes); + throw new AssertionError( + "Unexpected success of deserialization. Deserialized value: " + deser2); + } catch (InvalidObjectException e) { + // expected + } + } + + @Test + public void testIncompatiblePrimitiveFieldTypeChange() throws Exception { + out.println("\n---"); + + record IntHolder(int i) implements Serializable {} + + var r = new IntHolder(123); + var deser1 = deserialize(serialize(r)); + assertEquals(deser1, r); + + byte[] builderBytes = SerialByteStreamBuilder + .newBuilder(IntHolder.class.getName()) + .addPrimitiveField("i", long.class, 123L) + .build(); + + try { + var deser2 = deserialize(builderBytes); + throw new AssertionError( + "Unexpected success of deserialization. Deserialized value: " + deser2); + } catch (InvalidClassException e) { + // expected + } + } + + byte[] serialize(T obj) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(obj); + oos.close(); + return baos.toByteArray(); + } + + @SuppressWarnings("unchecked") + static T deserialize(byte[] streamBytes) + throws IOException, ClassNotFoundException { + ByteArrayInputStream bais = new ByteArrayInputStream(streamBytes); + ObjectInputStream ois = new ObjectInputStream(bais); + return (T) ois.readObject(); + } + + static class SerialByteStreamBuilder { + + private final ObjectOutputStream objectOutputStream; + private final ByteArrayOutputStream byteArrayOutputStream; + + record NameAndType(String name, Classtype) {} + + private String className; + private final LinkedHashMap, Object> primFields = new LinkedHashMap<>(); + private final LinkedHashMap, Object> objectFields = new LinkedHashMap<>(); + + private SerialByteStreamBuilder() { + try { + byteArrayOutputStream = new ByteArrayOutputStream(); + objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static SerialByteStreamBuilder newBuilder(String className) { + return (new SerialByteStreamBuilder()).className(className); + } + + private SerialByteStreamBuilder className(String className) { + this.className = className; + return this; + } + + public SerialByteStreamBuilder addPrimitiveField(String name, Class type, T value) { + if (!type.isPrimitive()) + throw new IllegalArgumentException("Unexpected non-primitive field: " + type); + primFields.put(new NameAndType<>(name, type), value); + return this; + } + + public SerialByteStreamBuilder addField(String name, Class type, T value) { + if (type.isPrimitive()) + throw new IllegalArgumentException("Unexpected primitive field: " + type); + objectFields.put(new NameAndType<>(name, type), value); + return this; + } + + private static int getPrimitiveSignature(Class cl) { + if (cl == Integer.TYPE) return 'I'; + else if (cl == Byte.TYPE) return 'B'; + else if (cl == Long.TYPE) return 'J'; + else if (cl == Float.TYPE) return 'F'; + else if (cl == Double.TYPE) return 'D'; + else if (cl == Short.TYPE) return 'S'; + else if (cl == Character.TYPE) return 'C'; + else if (cl == Boolean.TYPE) return 'Z'; + else throw new InternalError(); + } + + private static void writeUTF(DataOutputStream out, String str) throws IOException { + int utflen = str.length(); // assume ASCII + assert utflen <= 0xFFFF; + out.writeShort(utflen); + out.writeBytes(str); + } + + private void writePrimFieldsDesc(DataOutputStream out) throws IOException { + for (Map.Entry, Object> entry : primFields.entrySet()) { + assert entry.getKey().type() != void.class; + out.writeByte(getPrimitiveSignature(entry.getKey().type())); // prim_typecode + out.writeUTF(entry.getKey().name()); // fieldName + } + } + + private void writePrimFieldsValues(DataOutputStream out) throws IOException { + for (Map.Entry, Object> entry : primFields.entrySet()) { + Class cl = entry.getKey().type(); + Object value = entry.getValue(); + if (cl == Integer.TYPE) out.writeInt((int) value); + else if (cl == Byte.TYPE) out.writeByte((byte) value); + else if (cl == Long.TYPE) out.writeLong((long) value); + else if (cl == Float.TYPE) out.writeFloat((float) value); + else if (cl == Double.TYPE) out.writeDouble((double) value); + else if (cl == Short.TYPE) out.writeShort((short) value); + else if (cl == Character.TYPE) out.writeChar((char) value); + else if (cl == Boolean.TYPE) out.writeBoolean((boolean) value); + else throw new InternalError(); + } + } + + private void writeObjectFieldDesc(DataOutputStream out) throws IOException { + for (Map.Entry, Object> entry : objectFields.entrySet()) { + Class cl = entry.getKey().type(); + assert !cl.isPrimitive(); + // obj_typecode + if (cl.isArray()) { + out.writeByte('['); + } else { + out.writeByte('L'); + } + writeUTF(out, entry.getKey().name()); + out.writeByte(TC_STRING); + writeUTF(out, + (cl.isArray() ? cl.getName() : "L" + cl.getName() + ";") + .replace('.', '/')); + } + } + + private void writeObject(DataOutputStream out, Object value) throws IOException { + objectOutputStream.reset(); + byteArrayOutputStream.reset(); + objectOutputStream.writeUnshared(value); + out.write(byteArrayOutputStream.toByteArray()); + } + + private void writeObjectFieldValues(DataOutputStream out) throws IOException { + for (Map.Entry, Object> entry : objectFields.entrySet()) { + Class cl = entry.getKey().type(); + assert !cl.isPrimitive(); + if (cl == String.class) { + out.writeByte(TC_STRING); + writeUTF(out, (String) entry.getValue()); + } else { + writeObject(out, entry.getValue()); + } + } + } + + private int numFields() { + return primFields.size() + objectFields.size(); + } + + public byte[] build() { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + dos.writeShort(STREAM_MAGIC); + dos.writeShort(STREAM_VERSION); + dos.writeByte(TC_OBJECT); + dos.writeByte(TC_CLASSDESC); + dos.writeUTF(className); + dos.writeLong(0L); + dos.writeByte(SC_SERIALIZABLE); + dos.writeShort(numFields()); // number of fields + writePrimFieldsDesc(dos); + writeObjectFieldDesc(dos); + dos.writeByte(TC_ENDBLOCKDATA); // no annotations + dos.writeByte(TC_NULL); // no superclasses + writePrimFieldsValues(dos); + writeObjectFieldValues(dos); + dos.close(); + return baos.toByteArray(); + } catch (IOException unexpected) { + throw new AssertionError(unexpected); + } + } + } +} diff --git a/test/jdk/java/net/MulticastSocket/Promiscuous.java b/test/jdk/java/net/MulticastSocket/Promiscuous.java index ed99408c754..5f6126ae425 100644 --- a/test/jdk/java/net/MulticastSocket/Promiscuous.java +++ b/test/jdk/java/net/MulticastSocket/Promiscuous.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,7 +119,7 @@ static void test(InetAddress group1, InetAddress group2) // join groups on all network interfaces NetworkConfiguration.probe() - .multicastInterfaces(false) + .ip4MulticastInterfaces(false) .forEach((nic) -> { try { mc1.joinGroup(toSocketAddress(group1), nic); @@ -155,7 +155,7 @@ static void test(InetAddress group1, InetAddress group2) // leave groups on all network interfaces NetworkConfiguration.probe() - .multicastInterfaces(false) + .ip4MulticastInterfaces(false) .forEach((nic) -> { try { mc1.leaveGroup(toSocketAddress(group1), nic); diff --git a/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java b/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java new file mode 100644 index 00000000000..e83381c17e3 --- /dev/null +++ b/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8245245 + * @summary Test for Websocket URI encoding during HandShake + * @library /test/lib + * @build jdk.test.lib.net.SimpleSSLContext + * @modules java.net.http + * jdk.httpserver + * @run testng/othervm -Djdk.internal.httpclient.debug=true HandshakeUrlEncodingTest + */ + +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import com.sun.net.httpserver.HttpExchange; +import jdk.test.lib.net.SimpleSSLContext; +import jdk.test.lib.net.URIBuilder; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.WebSocket; +import java.net.http.WebSocketHandshakeException; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static java.net.http.HttpClient.Builder.NO_PROXY; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.fail; +import static java.lang.System.out; + +public class HandshakeUrlEncodingTest { + + SSLContext sslContext; + HttpServer httpTestServer; + HttpsServer httpsTestServer; + String httpURI; + String httpsURI; + + static String queryPart; + + static final int ITERATION_COUNT = 10; + // a shared executor helps reduce the amount of threads created by the test + static final ExecutorService executor = Executors.newCachedThreadPool(); + + @DataProvider(name = "variants") + public Object[][] variants() { + return new Object[][]{ + { httpURI, false }, + { httpsURI, false }, + { httpURI, true }, + { httpsURI, true } + }; + } + + HttpClient newHttpClient() { + return HttpClient.newBuilder() + .proxy(NO_PROXY) + .executor(executor) + .sslContext(sslContext) + .build(); + } + + @Test(dataProvider = "variants") + public void test(String uri, boolean sameClient) { + HttpClient client = null; + out.println("The url is " + uri); + for (int i = 0; i < ITERATION_COUNT; i++) { + System.out.printf("iteration %s%n", i); + if (!sameClient || client == null) + client = newHttpClient(); + + try { + client.newWebSocketBuilder() + .buildAsync(URI.create(uri), new WebSocket.Listener() { }) + .join(); + fail("Expected to throw"); + } catch (CompletionException ce) { + Throwable t = getCompletionCause(ce); + if (!(t instanceof WebSocketHandshakeException)) { + throw new AssertionError("Unexpected exception", t); + } + WebSocketHandshakeException wse = (WebSocketHandshakeException) t; + assertNotNull(wse.getResponse()); + assertNotNull(wse.getResponse().body()); + assertEquals(wse.getResponse().body().getClass(), String.class); + String body = (String)wse.getResponse().body(); + String expectedBody = "/?&raw=abc+def/ghi=xyz&encoded=abc%2Bdef%2Fghi%3Dxyz"; + assertEquals(body, expectedBody); + out.println("Status code is " + wse.getResponse().statusCode()); + out.println("Response is " + body); + assertNotNull(wse.getResponse().statusCode()); + out.println("Status code is " + wse.getResponse().statusCode()); + assertEquals(wse.getResponse().statusCode(), 400); + } + } + } + + @BeforeTest + public void setup() throws Exception { + sslContext = new SimpleSSLContext().get(); + if (sslContext == null) + throw new AssertionError("Unexpected null sslContext"); + + + InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); + queryPart = "?&raw=abc+def/ghi=xyz&encoded=abc%2Bdef%2Fghi%3Dxyz"; + httpTestServer = HttpServer.create(sa, 10); + httpURI = URIBuilder.newBuilder() + .scheme("ws") + .host("localhost") + .port(httpTestServer.getAddress().getPort()) + .path("/") + .build() + .toString() + queryPart; + + httpTestServer.createContext("/", new UrlHandler()); + + httpsTestServer = HttpsServer.create(sa, 10); + httpsTestServer.setHttpsConfigurator(new HttpsConfigurator(sslContext)); + httpsURI = URIBuilder.newBuilder() + .scheme("wss") + .host("localhost") + .port(httpsTestServer.getAddress().getPort()) + .path("/") + .build() + .toString() + queryPart; + + httpsTestServer.createContext("/", new UrlHandler()); + + httpTestServer.start(); + httpsTestServer.start(); + } + + @AfterTest + public void teardown() { + httpTestServer.stop(0); + httpsTestServer.stop(0); + executor.shutdownNow(); + } + + private static Throwable getCompletionCause(Throwable x) { + if (!(x instanceof CompletionException) + && !(x instanceof ExecutionException)) return x; + final Throwable cause = x.getCause(); + if (cause == null) { + throw new InternalError("Unexpected null cause", x); + } + return cause; + } + + static class UrlHandler implements HttpHandler { + + @Override + public void handle(HttpExchange e) throws IOException { + try(InputStream is = e.getRequestBody(); + OutputStream os = e.getResponseBody()) { + String testUri = "/?&raw=abc+def/ghi=xyz&encoded=abc%2Bdef%2Fghi%3Dxyz"; + URI uri = e.getRequestURI(); + byte[] bytes = is.readAllBytes(); + if (uri.toString().equals(testUri)) { + bytes = testUri.getBytes(); + } + e.sendResponseHeaders(400, bytes.length); + os.write(bytes); + + } + } + } +} + diff --git a/test/jdk/java/sql/testng/test/sql/DriverManagerPermissionsTests.java b/test/jdk/java/sql/testng/test/sql/othervm/DriverManagerPermissionsTests.java similarity index 97% rename from test/jdk/java/sql/testng/test/sql/DriverManagerPermissionsTests.java rename to test/jdk/java/sql/testng/test/sql/othervm/DriverManagerPermissionsTests.java index 73a8923d82f..0465e9ae3d2 100644 --- a/test/jdk/java/sql/testng/test/sql/DriverManagerPermissionsTests.java +++ b/test/jdk/java/sql/testng/test/sql/othervm/DriverManagerPermissionsTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package test.sql; +package test.sql.othervm; import java.security.AccessControlException; import java.security.Policy; diff --git a/test/jdk/javax/crypto/SecretKeyFactory/security.properties b/test/jdk/javax/crypto/SecretKeyFactory/security.properties index f855f12b990..c71970526bd 100644 --- a/test/jdk/javax/crypto/SecretKeyFactory/security.properties +++ b/test/jdk/javax/crypto/SecretKeyFactory/security.properties @@ -1,6 +1,3 @@ -# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. -# ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - jdk.security.provider.preferred= jdk.jar.disabledAlgorithms= diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java b/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java index 50e2c75b6c5..2bd7abbdc08 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java @@ -92,10 +92,10 @@ public static void main(String[] args) throws IOException { "ExtRootScan", "ThreadRoots", "UniverseRoots", - "JNIRoots", "ObjectSynchronizerRoots", "ManagementRoots", - "VMGlobalRoots", + "VM Global", + "JNI Global", "CLDGRoots", "JVMTIRoots", "CMRefRoots", diff --git a/test/jdk/jdk/jfr/event/oldobject/TestG1.java b/test/jdk/jdk/jfr/event/oldobject/TestG1.java index 6cfd985b1ce..2d3f142404f 100644 --- a/test/jdk/jdk/jfr/event/oldobject/TestG1.java +++ b/test/jdk/jdk/jfr/event/oldobject/TestG1.java @@ -54,17 +54,21 @@ static private class FindMe { public static void main(String[] args) throws Exception { WhiteBox.setWriteAllObjectSamples(true); - try (Recording r = new Recording()) { - r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); - r.start(); - allocateFindMe(); - System.gc(); - r.stop(); - List events = Events.fromRecording(r); - System.out.println(events); - if (OldObjects.countMatchingEvents(events, FindMe[].class, null, null, -1, "allocateFindMe") == 0) { - throw new Exception("Could not find leak with " + FindMe[].class); + while (true) { + try (Recording r = new Recording()) { + r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); + r.start(); + allocateFindMe(); + System.gc(); + r.stop(); + List events = Events.fromRecording(r); + System.out.println(events); + if (OldObjects.countMatchingEvents(events, FindMe[].class, null, null, -1, "allocateFindMe") > 0) { + return; + } + System.out.println("Could not find leaking object, retrying..."); } + list.clear(); } } diff --git a/test/jdk/jdk/jfr/event/oldobject/TestParallel.java b/test/jdk/jdk/jfr/event/oldobject/TestParallel.java index 71bfb486b83..ba0b6ea4b03 100644 --- a/test/jdk/jdk/jfr/event/oldobject/TestParallel.java +++ b/test/jdk/jdk/jfr/event/oldobject/TestParallel.java @@ -54,17 +54,21 @@ static private class FindMe { public static void main(String[] args) throws Exception { WhiteBox.setWriteAllObjectSamples(true); - try (Recording r = new Recording()) { - r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); - r.start(); - allocateFindMe(); - System.gc(); - r.stop(); - List events = Events.fromRecording(r); - System.out.println(events); - if (OldObjects.countMatchingEvents(events, FindMe[].class, null, null, -1, "allocateFindMe") == 0) { - throw new Exception("Could not find leak with " + FindMe[].class); + while (true) { + try (Recording r = new Recording()) { + r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); + r.start(); + allocateFindMe(); + System.gc(); + r.stop(); + List events = Events.fromRecording(r); + System.out.println(events); + if (OldObjects.countMatchingEvents(events, FindMe[].class, null, null, -1, "allocateFindMe") > 0) { + return; + } + System.out.println("Could not find leaking object, retrying..."); } + list.clear(); } } diff --git a/test/jdk/jdk/jfr/event/oldobject/TestSerial.java b/test/jdk/jdk/jfr/event/oldobject/TestSerial.java index ad18a6c84f2..905b187fc14 100644 --- a/test/jdk/jdk/jfr/event/oldobject/TestSerial.java +++ b/test/jdk/jdk/jfr/event/oldobject/TestSerial.java @@ -54,17 +54,21 @@ static private class FindMe { public static void main(String[] args) throws Exception { WhiteBox.setWriteAllObjectSamples(true); - try (Recording r = new Recording()) { - r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); - r.start(); - allocateFindMe(); - System.gc(); - r.stop(); - List events = Events.fromRecording(r); - System.out.println(events); - if (OldObjects.countMatchingEvents(events, FindMe[].class, null, null, -1, "allocateFindMe") == 0) { - throw new Exception("Could not find leak with " + FindMe[].class); + while (true) { + try (Recording r = new Recording()) { + r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); + r.start(); + allocateFindMe(); + System.gc(); + r.stop(); + List events = Events.fromRecording(r); + System.out.println(events); + if (OldObjects.countMatchingEvents(events, FindMe[].class, null, null, -1, "allocateFindMe") > 0) { + return; + } + System.out.println("Could not find leaking object, retrying..."); } + list.clear(); } } diff --git a/test/jdk/jdk/jfr/event/oldobject/TestZ.java b/test/jdk/jdk/jfr/event/oldobject/TestZ.java new file mode 100644 index 00000000000..ae5044f3801 --- /dev/null +++ b/test/jdk/jdk/jfr/event/oldobject/TestZ.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.event.oldobject; + +import java.util.ArrayList; +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.internal.test.WhiteBox; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; + +/** + * @test + * @key jfr + * @requires vm.hasJFR & vm.gc.Z + * @requires vm.gc == "null" + * @summary Test leak profiler with ZGC + * @library /test/lib /test/jdk + * @modules jdk.jfr/jdk.jfr.internal.test + * @run main/othervm -XX:TLABSize=2k -XX:+UseZGC jdk.jfr.event.oldobject.TestZ + */ +public class TestZ { + + static private class FindMe { + } + + public static List list = new ArrayList<>(OldObjects.MIN_SIZE); + + public static void main(String[] args) throws Exception { + WhiteBox.setWriteAllObjectSamples(true); + + while (true) { + try (Recording r = new Recording()) { + r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); + r.start(); + allocateFindMe(); + System.gc(); + r.stop(); + List events = Events.fromRecording(r); + System.out.println(events); + if (OldObjects.countMatchingEvents(events, FindMe[].class, null, null, -1, "allocateFindMe") > 0) { + return; + } + System.out.println("Could not find leaking object, retrying..."); + } + list.clear(); + } + } + + public static void allocateFindMe() { + for (int i = 0; i < OldObjects.MIN_SIZE; i++) { + // Allocate array to trigger sampling code path for interpreter / c1 + list.add(new FindMe[0]); + } + } + +} diff --git a/test/jdk/sun/tools/jstat/fileURITest1.awk b/test/jdk/sun/tools/jstat/fileURITest1.awk index 8b56e89ca31..e8833bd7eb1 100644 --- a/test/jdk/sun/tools/jstat/fileURITest1.awk +++ b/test/jdk/sun/tools/jstat/fileURITest1.awk @@ -3,18 +3,20 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O P YGC YGCT FGC FGCT GCT -# 0.00 100.00 68.87 1.24 27.75 1 0.044 0 0.000 0.044 +# -gcutil +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 0.00 0.00 47.17 97.15 92.31 20 0.335 696 334.382 2 0.069 334.786 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0 S1 E O P YGC YGCT FGC FGCT GCT $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/test/jdk/sun/tools/jstat/gcCapacityOutput1.awk b/test/jdk/sun/tools/jstat/gcCapacityOutput1.awk index 351ec772f49..2998b3706c0 100644 --- a/test/jdk/sun/tools/jstat/gcCapacityOutput1.awk +++ b/test/jdk/sun/tools/jstat/gcCapacityOutput1.awk @@ -3,15 +3,21 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC CGC -# 4096.0 657408.0 8192.0 512.0 512.0 3072.0 6144.0 1312768.0 6144.0 6144.0 512.0 132096.0 5120.0 512.0 131072.0 512.0 1 0 0 - +# -gccapacity 0 +# +# NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC CGC +# 0.0 4194304.0 6144.0 0.0 2048.0 4096.0 0.0 4194304.0 2048.0 2048.0 0.0 1056768.0 7680.0 0.0 1048576.0 768.0 4 0 0 +# +# -J-XX:+UseParallelGC -gccapacity 0 +# +# NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC CGC +# 1536.0 1397760.0 8192.0 1024.0 512.0 3072.0 512.0 2796544.0 5632.0 5632.0 0.0 1056768.0 8320.0 0.0 1048576.0 896.0 5 0 - BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC CGC $/ { +/^ NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC CGC $/ { headerlines++; } diff --git a/test/jdk/sun/tools/jstat/gcCauseOutput1.awk b/test/jdk/sun/tools/jstat/gcCauseOutput1.awk index 440843a26aa..16a4f4f3cb1 100644 --- a/test/jdk/sun/tools/jstat/gcCauseOutput1.awk +++ b/test/jdk/sun/tools/jstat/gcCauseOutput1.awk @@ -3,16 +3,21 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT LGCC GCC -# 0.00 0.00 0.00 9.97 90.94 87.70 2 0.013 0 0.000 0 0.000 0.013 Allocation Failure No GC -# 0.00 0.00 82.15 0.00 - - 0 0.000 0 0.000 - - 0.000 No GC No GC - +# -gccause 0 +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT LGCC GCC +# 0.00 54.68 0.00 0.00 94.02 84.11 4 0.269 0 0.000 0 0.000 0.269 G1 Evacuation Pause No GC +# +# -J-XX:+UseSerialGC -gccause 0 +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT LGCC GCC +# 78.14 0.00 68.23 15.57 94.69 88.17 4 0.204 0 0.000 - - 0.204 Allocation Failure No GC BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT LGCC GCC $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT LGCC GCC $/ { headerlines++; } diff --git a/test/jdk/sun/tools/jstat/gcMetaCapacityOutput1.awk b/test/jdk/sun/tools/jstat/gcMetaCapacityOutput1.awk index 54d31bebda5..93f0be85b18 100644 --- a/test/jdk/sun/tools/jstat/gcMetaCapacityOutput1.awk +++ b/test/jdk/sun/tools/jstat/gcMetaCapacityOutput1.awk @@ -3,14 +3,21 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT CGC CGCT GCT -# 512.0 132096.0 5120.0 512.0 131072.0 512.0 1 0 0.000 0 0.000 0.004 +# -gcmetacapacity 0 +# +# MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT CGC CGCT GCT +# 0.0 1056768.0 8832.0 0.0 1048576.0 896.0 5 0 0.000 0 0.000 0.245 +# +# -J-XX:+UseParallelGC -gcmetacapacity 0 +# +# MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT CGC CGCT GCT +# 0.0 1056768.0 8064.0 0.0 1048576.0 896.0 4 0 0.000 - - 0.113 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT CGC CGCT GCT $/ { +/^ MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT CGC CGCT GCT $/ { headerlines++; } diff --git a/test/jdk/sun/tools/jstat/gcNewCapacityOutput1.awk b/test/jdk/sun/tools/jstat/gcNewCapacityOutput1.awk index 378b787b661..13d0386404d 100644 --- a/test/jdk/sun/tools/jstat/gcNewCapacityOutput1.awk +++ b/test/jdk/sun/tools/jstat/gcNewCapacityOutput1.awk @@ -3,15 +3,21 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC CGC -# 2176.0 7232.0 2176.0 192.0 64.0 192.0 64.0 6848.0 2048.0 1 0 0 - +# -gcnewcapacity 0 +# +# NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC CGC +# 0.0 4194304.0 6144.0 0.0 0.0 4194304.0 2048.0 4194304.0 4096.0 4 0 0 +# +# -J-XX:+UseParallelGC -gcnewcapacity 0 +# +# NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC CGC +# 1536.0 1397760.0 7168.0 465920.0 512.0 465920.0 512.0 1396736.0 6144.0 4 0 - BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC CGC $/ { +/^ NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC CGC $/ { headerlines++; } diff --git a/test/jdk/sun/tools/jstat/gcNewOutput1.awk b/test/jdk/sun/tools/jstat/gcNewOutput1.awk index 357fa282030..f9728ffd08c 100644 --- a/test/jdk/sun/tools/jstat/gcNewOutput1.awk +++ b/test/jdk/sun/tools/jstat/gcNewOutput1.awk @@ -3,16 +3,21 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT -# 64.0 64.0 0.0 64.0 1 31 32.0 2048.0 41.4 1 0.031 - - +# -gcnew 0 +# +# S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT +# 0.0 2048.0 0.0 1113.5 15 15 1024.0 4096.0 0.0 4 0.228 +# +# -J-XX:+UseParallelGC -gcnew 0 +# +# S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT +# 1024.0 512.0 0.0 512.0 6 15 1024.0 3072.0 830.1 5 0.164 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT $/ { +/^ S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT $/ { headerlines++; } diff --git a/test/jdk/sun/tools/jstat/gcOldCapacityOutput1.awk b/test/jdk/sun/tools/jstat/gcOldCapacityOutput1.awk index 1534dbf2ffe..dde529cdc7c 100644 --- a/test/jdk/sun/tools/jstat/gcOldCapacityOutput1.awk +++ b/test/jdk/sun/tools/jstat/gcOldCapacityOutput1.awk @@ -3,14 +3,21 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# OGCMN OGCMX OGC OC YGC FGC FGCT CGC CGCT GCT -# 6016.0 58304.0 6016.0 6016.0 1 0 0.000 0 0.000 0.030 +# -gcoldcapacity 0 +# +# OGCMN OGCMX OGC OC YGC FGC FGCT CGC CGCT GCT +# 0.0 4194304.0 2048.0 2048.0 5 0 0.000 0 0.000 0.407 +# +# -J-XX:+UseParallelGC -gcoldcpacity 0 +# +# OGCMN OGCMX OGC OC YGC FGC FGCT CGC CGCT GCT +# 512.0 2796544.0 5632.0 5632.0 5 0 0.000 - - 0.180 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ OGCMN OGCMX OGC OC YGC FGC FGCT CGC CGCT GCT $/ { +/^ OGCMN OGCMX OGC OC YGC FGC FGCT CGC CGCT GCT $/ { headerlines++; } diff --git a/test/jdk/sun/tools/jstat/gcOldOutput1.awk b/test/jdk/sun/tools/jstat/gcOldOutput1.awk index 74f46cca56a..fca0d38a108 100644 --- a/test/jdk/sun/tools/jstat/gcOldOutput1.awk +++ b/test/jdk/sun/tools/jstat/gcOldOutput1.awk @@ -3,15 +3,21 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# MC MU CCSC CCSU OC OU YGC FGC FGCT CGC CGCT GCT -# 5120.0 4152.0 512.0 397.9 6144.0 200.0 1 0 0.000 0.005 - +# -gcold 0 +# +# MC MU CCSC CCSU OC OU YGC FGC FGCT CGC CGCT GCT +# 7680.0 7202.3 768.0 638.6 2048.0 0.0 4 0 0.000 0 0.000 0.240 +# +# -J-XX:+UseParallelGC -gcold 0 +# +# MC MU CCSC CCSU OC OU YGC FGC FGCT CGC CGCT GCT +# 8320.0 7759.4 896.0 718.3 5632.0 904.1 5 0 0.000 - - 0.175 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ MC MU CCSC CCSU OC OU YGC FGC FGCT CGC CGCT GCT $/ { +/^ MC MU CCSC CCSU OC OU YGC FGC FGCT CGC CGCT GCT $/ { headerlines++; } diff --git a/test/jdk/sun/tools/jstat/gcOutput1.awk b/test/jdk/sun/tools/jstat/gcOutput1.awk index 10764ae2e2c..c8be39a7970 100644 --- a/test/jdk/sun/tools/jstat/gcOutput1.awk +++ b/test/jdk/sun/tools/jstat/gcOutput1.awk @@ -3,15 +3,22 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT -# 512.0 512.0 0.0 496.0 3072.0 615.5 6144.0 280.0 5120.0 4176.0 512.0 401.0 1 0.005 0 0.000 0 0.000 0.005 +# -gc 0 +# +# S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT +# 0.0 2048.0 0.0 1079.5 4096.0 0.0 2048.0 0.0 7680.0 7378.6 768.0 664.7 4 0.140 0 0.000 0 0.000 0.140 +# +# -J-XX:+UseParallelGC -gc 0 +# +# S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT +# 512.0 512.0 512.0 0.0 6144.0 634.8 5632.0 748.1 8320.0 7851.5 896.0 730.2 4 0.171 0 0.000 - - 0.171 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT $/ { +/^ S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT $/ { headerlines++; } diff --git a/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh index c11f1ad4f61..ccc95be281f 100644 --- a/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gccapacity 0 2>&1 | awk -f ${TESTSRC}/gcCapacityOutput1.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gccapacity 0 2>&1 | awk -f ${TESTSRC}/gcCapacityOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh index 691b94d1498..c34a1881673 100644 --- a/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -37,4 +37,5 @@ JSTAT="${TESTJAVA}/bin/jstat" # class machine, ergonomics will automatically use UseParallelGC. # The UseParallelGC collector does not currently update the gc cause counters. +${JSTAT} ${COMMON_JSTAT_FLAGS} -gccause 0 2>&1 | awk -f ${TESTSRC}/gcCauseOutput1.awk ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseSerialGC -gccause 0 2>&1 | awk -f ${TESTSRC}/gcCauseOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh index b1fe28914c2..66446517c50 100644 --- a/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcmetacapacity 0 2>&1 | awk -f ${TESTSRC}/gcMetaCapacityOutput1.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcmetacapacity 0 2>&1 | awk -f ${TESTSRC}/gcMetaCapacityOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh index bbef2761c81..44aa864b475 100644 --- a/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcnewcapacity 0 2>&1 | awk -f ${TESTSRC}/gcNewCapacityOutput1.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcnewcapacity 0 2>&1 | awk -f ${TESTSRC}/gcNewCapacityOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh index 0ddb4879dd8..0f909f18a9e 100644 --- a/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcnew 0 2>&1 | awk -f ${TESTSRC}/gcNewOutput1.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcnew 0 2>&1 | awk -f ${TESTSRC}/gcNewOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh index 95c1d9c01e0..433072fddfa 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcoldcapacity 0 2>&1 | awk -f ${TESTSRC}/gcOldCapacityOutput1.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcoldcapacity 0 2>&1 | awk -f ${TESTSRC}/gcOldCapacityOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh index 71a6313e07e..ee9e30296e0 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcold 0 2>&1 | awk -f ${TESTSRC}/gcOldOutput1.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcold 0 2>&1 | awk -f ${TESTSRC}/gcOldOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOutput1.sh index 150263174d9..167c53606ad 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gc 0 2>&1 | awk -f ${TESTSRC}/gcOutput1.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gc 0 2>&1 | awk -f ${TESTSRC}/gcOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts1.sh b/test/jdk/sun/tools/jstat/jstatLineCounts1.sh index 674f2e0f3c9..75cb051cccf 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts1.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil 0 250 5 2>&1 | awk -f ${TESTSRC}/lineCounts1.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil 0 250 5 2>&1 | awk -f ${TESTSRC}/lineCounts1.awk diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts2.sh b/test/jdk/sun/tools/jstat/jstatLineCounts2.sh index ec4237f6941..5e0cbafe08d 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts2.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts2.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil 0 2>&1 | awk -f ${TESTSRC}/lineCounts2.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil 0 2>&1 | awk -f ${TESTSRC}/lineCounts2.awk diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts3.sh b/test/jdk/sun/tools/jstat/jstatLineCounts3.sh index 8b48b7bf317..ef8bbc8ad75 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts3.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts3.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil -h 10 0 250 10 2>&1 | awk -f ${TESTSRC}/lineCounts3.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil -h 10 0 250 10 2>&1 | awk -f ${TESTSRC}/lineCounts3.awk diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts4.sh b/test/jdk/sun/tools/jstat/jstatLineCounts4.sh index a365c27c3f3..537172c75e3 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts4.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts4.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil -h 10 0 250 11 2>&1 | awk -f ${TESTSRC}/lineCounts4.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil -h 10 0 250 11 2>&1 | awk -f ${TESTSRC}/lineCounts4.awk diff --git a/test/jdk/sun/tools/jstat/jstatTimeStamp1.sh b/test/jdk/sun/tools/jstat/jstatTimeStamp1.sh index 112b369f35a..db71314fcf9 100644 --- a/test/jdk/sun/tools/jstat/jstatTimeStamp1.sh +++ b/test/jdk/sun/tools/jstat/jstatTimeStamp1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,3 +34,4 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil -t 0 2>&1 | awk -f ${TESTSRC}/timeStamp1.awk +${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil -t 0 2>&1 | awk -f ${TESTSRC}/timeStamp1.awk diff --git a/test/jdk/sun/tools/jstat/lineCounts1.awk b/test/jdk/sun/tools/jstat/lineCounts1.awk index 9517d1bfddd..d7a7c1d9fb7 100644 --- a/test/jdk/sun/tools/jstat/lineCounts1.awk +++ b/test/jdk/sun/tools/jstat/lineCounts1.awk @@ -3,22 +3,33 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT -# 0.00 93.76 28.80 1.82 77.74 68.02 1 0.005 0 0.000 0 0.000 0.005 -# 0.00 93.76 73.04 1.82 77.74 68.02 1 0.005 0 0.000 0 0.000 0.005 -# 0.00 93.76 73.04 1.82 77.74 68.02 1 0.005 0 0.000 0 0.000 0.005 -# 0.00 93.76 73.04 1.82 77.74 68.02 1 0.005 0 0.000 0 0.000 0.005 -# 0.00 93.76 75.00 1.82 77.74 68.02 1 0.005 0 0.000 0 0.000 0.005 +# -gcutil 0 250 5 +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 64.15 0.00 0.00 95.71 84.70 5 0.258 0 0.000 0 0.000 0.258 +# 0.00 64.15 0.00 0.00 95.71 84.70 5 0.258 0 0.000 0 0.000 0.258 +# 0.00 64.15 0.00 0.00 95.71 84.70 5 0.258 0 0.000 0 0.000 0.258 +# 0.00 64.15 0.00 0.00 95.71 84.70 5 0.258 0 0.000 0 0.000 0.258 +# 0.00 64.15 0.00 0.00 95.71 84.70 5 0.258 0 0.000 0 0.000 0.258 +# +# -J-XX:+UseParallelGC -gcutil 0 250 5 +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 100.00 46.54 14.99 94.73 89.25 5 0.197 0 0.000 - - 0.197 +# 0.00 100.00 46.54 14.99 94.73 89.25 5 0.197 0 0.000 - - 0.197 +# 0.00 100.00 48.50 14.99 94.73 89.25 5 0.197 0 0.000 - - 0.197 +# 0.00 100.00 48.50 14.99 94.73 89.25 5 0.197 0 0.000 - - 0.197 +# 0.00 100.00 50.46 14.99 94.73 89.25 5 0.197 0 0.000 - - 0.197 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/test/jdk/sun/tools/jstat/lineCounts2.awk b/test/jdk/sun/tools/jstat/lineCounts2.awk index fcd832a6658..201457a3833 100644 --- a/test/jdk/sun/tools/jstat/lineCounts2.awk +++ b/test/jdk/sun/tools/jstat/lineCounts2.awk @@ -3,18 +3,25 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT -# 0.00 93.76 28.40 1.82 77.74 68.02 1 0.005 0 0.000 0 0.000 0.005 +# -gcutil 0 +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 66.43 0.00 0.00 95.69 84.70 5 0.251 0 0.000 0 0.000 0.251 +# +# -J-XX:+UseParallelGC -gcutil 0 +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 100.00 46.41 14.85 95.00 89.25 5 0.151 0 0.000 - - 0.151 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/test/jdk/sun/tools/jstat/lineCounts3.awk b/test/jdk/sun/tools/jstat/lineCounts3.awk index d1414a96b67..1f155a99ed5 100644 --- a/test/jdk/sun/tools/jstat/lineCounts3.awk +++ b/test/jdk/sun/tools/jstat/lineCounts3.awk @@ -3,27 +3,43 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT -# 0.00 93.76 26.48 1.95 77.78 68.02 1 0.006 0 0.000 0 0.000 0.006 -# 0.00 93.76 71.58 1.95 77.78 68.02 1 0.006 0 0.000 0 0.000 0.006 -# 0.00 93.76 73.58 1.95 77.78 68.02 1 0.006 0 0.000 0 0.000 0.006 -# 0.00 93.76 73.58 1.95 77.78 68.02 1 0.006 0 0.000 0 0.000 0.006 -# 0.00 93.76 73.58 1.95 77.78 68.02 1 0.006 0 0.000 0 0.000 0.006 -# 0.00 93.76 75.58 1.95 77.78 68.02 1 0.006 0 0.000 0 0.000 0.006 -# 0.00 93.76 75.58 1.95 77.78 68.02 1 0.006 0 0.000 0 0.000 0.006 -# 0.00 93.76 77.58 1.95 77.78 68.02 1 0.006 0 0.000 0 0.000 0.006 -# 0.00 93.76 77.58 1.95 77.78 68.02 1 0.006 0 0.000 0 0.000 0.006 -# 0.00 93.76 77.58 1.95 77.78 68.02 1 0.006 0 0.000 0 0.000 0.006 +# -gcutil -h 10 0 250 10 +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 63.87 0.00 0.00 95.70 84.70 5 0.229 0 0.000 0 0.000 0.229 +# 0.00 63.87 0.00 0.00 95.70 84.70 5 0.229 0 0.000 0 0.000 0.229 +# 0.00 63.87 0.00 0.00 95.70 84.70 5 0.229 0 0.000 0 0.000 0.229 +# 0.00 63.87 0.00 0.00 95.70 84.70 5 0.229 0 0.000 0 0.000 0.229 +# 0.00 63.87 0.00 0.00 95.70 84.70 5 0.229 0 0.000 0 0.000 0.229 +# 0.00 63.87 0.00 0.00 95.70 84.70 5 0.229 0 0.000 0 0.000 0.229 +# 0.00 63.87 0.00 0.00 95.70 84.70 5 0.229 0 0.000 0 0.000 0.229 +# 0.00 63.87 0.00 0.00 95.70 84.70 5 0.229 0 0.000 0 0.000 0.229 +# 0.00 63.87 0.00 0.00 95.70 84.70 5 0.229 0 0.000 0 0.000 0.229 +# 0.00 63.87 0.00 0.00 95.70 84.70 5 0.229 0 0.000 0 0.000 0.229 +# +# -J-XX:+UseParallelGC -gcutil -h 10 0 250 10 +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 100.00 46.46 15.06 95.02 89.25 5 0.219 0 0.000 - - 0.219 +# 0.00 100.00 46.46 15.06 95.02 89.25 5 0.219 0 0.000 - - 0.219 +# 0.00 100.00 48.42 15.06 95.02 89.25 5 0.219 0 0.000 - - 0.219 +# 0.00 100.00 48.42 15.06 95.02 89.25 5 0.219 0 0.000 - - 0.219 +# 0.00 100.00 50.39 15.06 95.02 89.25 5 0.219 0 0.000 - - 0.219 +# 0.00 100.00 50.39 15.06 95.02 89.25 5 0.219 0 0.000 - - 0.219 +# 0.00 100.00 52.35 15.06 95.02 89.25 5 0.219 0 0.000 - - 0.219 +# 0.00 100.00 52.35 15.06 95.02 89.25 5 0.219 0 0.000 - - 0.219 +# 0.00 100.00 54.31 15.06 95.02 89.25 5 0.219 0 0.000 - - 0.219 +# 0.00 100.00 54.31 15.06 95.02 89.25 5 0.219 0 0.000 - - 0.219 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/test/jdk/sun/tools/jstat/lineCounts4.awk b/test/jdk/sun/tools/jstat/lineCounts4.awk index 6afcbcedf82..62aea881e71 100644 --- a/test/jdk/sun/tools/jstat/lineCounts4.awk +++ b/test/jdk/sun/tools/jstat/lineCounts4.awk @@ -3,30 +3,48 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT -# 0.00 96.88 66.55 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 -# 0.00 96.88 71.58 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 -# 0.00 96.88 73.58 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 -# 0.00 96.88 73.58 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 -# 0.00 96.88 73.58 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 -# 0.00 96.88 75.58 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 -# 0.00 96.88 75.58 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 -# 0.00 96.88 77.58 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 -# 0.00 96.88 77.58 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 -# 0.00 96.88 77.58 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 -# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT -# 0.00 96.88 79.58 2.34 77.78 68.02 1 0.003 0 0.000 0 0.000 0.003 +# -gcutil -h 10 0 250 11 +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 0.00 57.14 47.16 97.09 92.27 5 0.283 51 23.751 2 0.068 24.102 +# +# -J-XX:+UseParallelGC -gcutil -h 10 0 250 11 +# +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 100.00 46.57 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 +# 0.00 100.00 46.57 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 +# 0.00 100.00 48.53 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 +# 0.00 100.00 48.53 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 +# 0.00 100.00 50.49 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 +# 0.00 100.00 50.49 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 +# 0.00 100.00 52.45 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 +# 0.00 100.00 52.45 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 +# 0.00 100.00 54.41 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 +# 0.00 100.00 54.41 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 +# S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 0.00 100.00 56.37 14.56 94.70 89.25 5 0.206 0 0.000 - - 0.206 BEGIN { headerlines=0; datalines=0; totallines=0 datalines2=0; } -/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { if (headerlines == 2) { datalines2++; } diff --git a/test/jdk/sun/tools/jstat/timeStamp1.awk b/test/jdk/sun/tools/jstat/timeStamp1.awk index 9854fcf571e..a71ec77ad84 100644 --- a/test/jdk/sun/tools/jstat/timeStamp1.awk +++ b/test/jdk/sun/tools/jstat/timeStamp1.awk @@ -3,15 +3,22 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -#Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT -# 0.3 0.00 100.00 68.74 1.95 77.73 68.02 1 0.004 0 0.000 0 0.000 0.004 -# 0.3 0.00 0.00 37.50 0.00 - - 0 0.000 0 0.000 0 0.000 0.000 +# -gcutil -t 0 +# +#Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 3.4 0.00 63.85 0.00 0.00 93.83 81.78 5 0.203 0 0.000 0 0.000 0.203 +# 3.7 0.00 63.85 0.00 0.00 93.83 81.78 5 0.203 0 0.000 0 0.000 0.203 +# +# -J-XX:+UseParallelGC -gcutil -t 0 +# +#Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT +# 2.6 100.00 0.00 22.51 10.16 94.74 88.88 4 0.100 0 0.000 - - 0.100 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { +/^Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT $/ { headerlines++; } diff --git a/test/jdk/sun/tools/jstatd/JstatGCUtilParser.java b/test/jdk/sun/tools/jstatd/JstatGCUtilParser.java index 14f9d6e8854..3674feca285 100644 --- a/test/jdk/sun/tools/jstatd/JstatGCUtilParser.java +++ b/test/jdk/sun/tools/jstatd/JstatGCUtilParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,9 +30,8 @@ /** * The helper class for parsing following output from command 'jstat -gcutil': * - * S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT - * 0.00 0.00 86.67 0.00 - - 0 0.000 0 0.000 0 0.000 0.000 - * 0.00 0.00 86.67 0.00 - - 0 0.000 0 0.000 0 0.000 0.000 + * S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT + * 0.00 0.00 0.00 52.39 97.76 92.71 4 0.286 28 28.006 2 0.086 28.378 * * It will be verified that numerical values have defined types and are reasonable, * for example percentage should fit within 0-100 interval. diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index a607d15cbd2..899286ca44a 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -308,7 +308,7 @@ public static JPackageCommand helloAppImage(String javaAppDesc) { public static JPackageCommand helloAppImage(JavaAppDesc javaAppDesc) { JPackageCommand cmd = new JPackageCommand(); cmd.setDefaultInputOutput().setDefaultAppName(); - PackageType.IMAGE.applyTo(cmd); + cmd.setPackageType(PackageType.IMAGE); new HelloApp(javaAppDesc).addTo(cmd); return cmd; } diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java new file mode 100644 index 00000000000..d916fe5c7de --- /dev/null +++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest3.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jpackage.tests; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; +import jdk.incubator.jpackage.internal.AppImageFile; +import jdk.jpackage.test.HelloApp; +import jdk.jpackage.test.JavaAppDesc; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.Parameters; +import jdk.jpackage.test.Executor; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.JavaTool; +import jdk.jpackage.test.PackageType; +import jdk.jpackage.test.TKit; +import org.w3c.dom.Document; + + +/* + * @test + * @summary jpackage for app's module linked in external runtime + * @library ../../../../helpers + * @build jdk.jpackage.test.* + * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal + * @compile ModulePathTest3.java + * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * --jpt-run=jdk.jpackage.tests.ModulePathTest3 + */ + +/* + * @test + * @summary jpackage for app's module linked in external runtime + * @library ../../../../helpers + * @build jdk.jpackage.test.* + * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal + * @compile ModulePathTest3.java + * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * --jpt-run=jdk.jpackage.tests.ModulePathTest3 + * --jpt-exclude=test8248418 + */ + +public final class ModulePathTest3 { + + public ModulePathTest3(String jlinkOutputSubdir, String runtimeSubdir) { + this.jlinkOutputSubdir = Path.of(jlinkOutputSubdir); + this.runtimeSubdir = Path.of(runtimeSubdir); + } + + /** + * Test case for JDK-8248254. + * App's module in runtime directory. + */ + @Test + public void test8248254() throws XPathExpressionException, IOException { + testIt("me.mymodule/me.mymodule.Main"); + } + + /** + * Test case for JDK-8248418. + * App's module with version specified in runtime directory. + */ + @Test + public void test8248418() throws XPathExpressionException, IOException { + testIt("me.mymodule/me.mymodule.Main@3.7"); + } + + private void testIt(String mainAppDesc) throws XPathExpressionException, + IOException { + final JavaAppDesc appDesc = JavaAppDesc.parse(mainAppDesc); + final Path moduleOutputDir = TKit.createTempDirectory("modules"); + HelloApp.createBundle(appDesc, moduleOutputDir); + + final Path workDir = TKit.createTempDirectory("runtime").resolve("data"); + final Path jlinkOutputDir = workDir.resolve(jlinkOutputSubdir); + Files.createDirectories(jlinkOutputDir.getParent()); + + new Executor() + .setToolProvider(JavaTool.JLINK) + .dumpOutput() + .addArguments( + "--add-modules", appDesc.moduleName(), + "--output", jlinkOutputDir.toString(), + "--module-path", moduleOutputDir.resolve(appDesc.jarFileName()).toString(), + "--strip-debug", + "--no-header-files", + "--no-man-pages", + "--strip-native-commands") + .execute(); + + JPackageCommand cmd = new JPackageCommand() + .setDefaultAppName() + .setPackageType(PackageType.IMAGE) + .setDefaultInputOutput() + .removeArgumentWithValue("--input") + .addArguments("--module", appDesc.moduleName() + "/" + appDesc.className()) + .setArgumentValue("--runtime-image", workDir.resolve(runtimeSubdir)); + + cmd.executeAndAssertHelloAppImageCreated(); + + if (appDesc.moduleVersion() != null) { + Document xml = AppImageFile.readXml(cmd.outputBundle()); + String actualVersion = XPathFactory.newInstance().newXPath().evaluate( + "/jpackage-state/app-version/text()", xml, + XPathConstants.STRING).toString(); + + TKit.assertEquals(appDesc.moduleVersion(), actualVersion, + "Check application version"); + } + } + + @Parameters + public static Collection data() { + final List paths = new ArrayList<>(); + paths.add(new String[] { "", "" }); + if (TKit.isOSX()) { + // On OSX jpackage should accept both runtime root and runtime home + // directories. + paths.add(new String[] { "Contents/Home", "" }); + } + + List data = new ArrayList<>(); + for (var pathCfg : paths) { + data.add(new Object[] { pathCfg[0], pathCfg[1] }); + } + + return data; + } + + private final Path jlinkOutputSubdir; + private final Path runtimeSubdir; +} diff --git a/test/langtools/ProblemList.txt b/test/langtools/ProblemList.txt index 35edcf1ee4d..dc129b07a52 100644 --- a/test/langtools/ProblemList.txt +++ b/test/langtools/ProblemList.txt @@ -26,7 +26,7 @@ ########################################################################### # # javadoc -jdk/javadoc/doclet/testIOException/TestIOException.java 8164597 windows-all +jdk/javadoc/doclet/testHeadTag/TestHeadTag.java 8248417 generic-all ########################################################################### # diff --git a/test/langtools/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java b/test/langtools/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java index ceb6d08fd51..299452cc646 100644 --- a/test/langtools/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java +++ b/test/langtools/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java @@ -79,9 +79,9 @@ void checkTimestamps(boolean timestamp) { } void checkTimestamps(boolean timestamp, String... files) { - String version = System.getProperty("java.version"); - String genBy = "Generated by javadoc (" + version + ")"; - if (timestamp) genBy += " on "; + String version = System.getProperty("java.specification.version"); + String genBy = "Generated by javadoc"; + if (timestamp) genBy += " (" + version + ") on "; for (String file: files) { // genBy is the current standard "Generated by" text diff --git a/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java b/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java index 73bcb7ec924..aea2233e4d2 100644 --- a/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java +++ b/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java @@ -33,9 +33,19 @@ import java.io.File; import java.io.FileWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Locale; +import java.util.Map; import javadoc.tester.JavadocTester; +/** + * Tests IO Exception handling. + * + * Update: Windows does not permit setting folder to be readonly. + * https://support.microsoft.com/en-us/help/326549/you-cannot-view-or-change-the-read-only-or-the-system-attributes-of-fo + */ public class TestIOException extends JavadocTester { public static void main(String... args) throws Exception { @@ -43,21 +53,29 @@ public static void main(String... args) throws Exception { tester.runTests(); } + /** + * Tests a read-only directory. + * On Windows, this test may be skipped. + */ @Test public void testReadOnlyDirectory() { File outDir = new File("out1"); if (!outDir.mkdir()) { - throw new Error("Cannot create directory"); + throw error(outDir, "Cannot create directory"); } if (!outDir.setReadOnly()) { - throw new Error("could not set directory read-only"); + if (skip(outDir)) { + return; + } + throw error(outDir, "could not set directory read-only"); } if (outDir.canWrite()) { - throw new Error("directory is writable"); + throw error(outDir, "directory is writable"); } try { javadoc("-d", outDir.toString(), + "-Xdoclint:-missing", new File(testSrc, "TestIOException.java").getPath()); checkExit(Exit.ERROR); checkOutput(Output.OUT, true, @@ -67,24 +85,29 @@ public void testReadOnlyDirectory() { } } + /** + * Tests a read-only file. + * @throws Exception if an error occurred + */ @Test public void testReadOnlyFile() throws Exception { File outDir = new File("out2"); if (!outDir.mkdir()) { - throw new Error("Cannot create directory"); + throw error(outDir, "Cannot create directory"); } File index = new File(outDir, "index.html"); try (FileWriter fw = new FileWriter(index)) { } if (!index.setReadOnly()) { - throw new Error("could not set index read-only"); + throw error(index, "could not set index read-only"); } if (index.canWrite()) { - throw new Error("index is writable"); + throw error(index, "index is writable"); } try { setOutputDirectoryCheck(DirectoryCheck.NONE); javadoc("-d", outDir.toString(), + "-Xdoclint:-missing", new File(testSrc, "TestIOException.java").getPath()); checkExit(Exit.ERROR); @@ -96,6 +119,11 @@ public void testReadOnlyFile() throws Exception { } } + /** + * Tests a read-only subdirectory. + * On Windows, this test may be skipped. + * @throws Exception if an error occurred + */ @Test public void testReadOnlySubdirectory() throws Exception { // init source file @@ -111,19 +139,23 @@ public void testReadOnlySubdirectory() throws Exception { File outDir = new File("out3"); File pkgOutDir = new File(outDir, "p"); if (!pkgOutDir.mkdirs()) { - throw new Error("Cannot create directory"); + throw error(pkgOutDir, "Cannot create directory"); } if (!pkgOutDir.setReadOnly()) { - throw new Error("could not set directory read-only"); + if (skip(pkgOutDir)) { + return; + } + throw error(pkgOutDir, "could not set directory read-only"); } if (pkgOutDir.canWrite()) { - throw new Error("directory is writable"); + throw error(pkgOutDir, "directory is writable"); } // run javadoc and check results try { setOutputDirectoryCheck(DirectoryCheck.NONE); javadoc("-d", outDir.toString(), + "-Xdoclint:-missing", src_p_C.getPath()); checkExit(Exit.ERROR); checkOutput(Output.OUT, true, @@ -134,6 +166,11 @@ public void testReadOnlySubdirectory() throws Exception { } } + /** + * Tests a read-only doc-files directory. + * On Windows, this test may be skipped. + * @throws Exception if an error occurred + */ @Test public void testReadOnlyDocFilesDir() throws Exception { // init source files @@ -155,18 +192,22 @@ public void testReadOnlyDocFilesDir() throws Exception { File pkgOutDir = new File(outDir, "p"); File docFilesOutDir = new File(pkgOutDir, "doc-files"); if (!docFilesOutDir.mkdirs()) { - throw new Error("Cannot create directory"); + throw error(docFilesOutDir, "Cannot create directory"); } if (!docFilesOutDir.setReadOnly()) { - throw new Error("could not set directory read-only"); + if (skip(docFilesOutDir)) { + return; + } + throw error(docFilesOutDir, "could not set directory read-only"); } if (docFilesOutDir.canWrite()) { - throw new Error("directory is writable"); + throw error(docFilesOutDir, "directory is writable"); } try { setOutputDirectoryCheck(DirectoryCheck.NONE); javadoc("-d", outDir.toString(), + "-Xdoclint:-missing", "-sourcepath", srcDir.getPath(), "p"); checkExit(Exit.ERROR); @@ -177,5 +218,44 @@ public void testReadOnlyDocFilesDir() throws Exception { docFilesOutDir.setWritable(true); } } + + private Error error(File f, String message) { + out.println(f + ": " + message); + showAllAttributes(f.toPath()); + throw new Error(f + ": " + message); + } + + private void showAllAttributes(Path p) { + showAttributes(p, "*"); + showAttributes(p, "posix:*"); + showAttributes(p, "dos:*"); + } + + private void showAttributes(Path p, String attributes) { + out.println("Attributes: " + attributes); + try { + Map map = Files.readAttributes(p, attributes); + map.forEach((n, v) -> out.format(" %-10s: %s%n", n, v)); + } catch (UnsupportedOperationException e) { + out.println("Attributes not available " + attributes); + } catch (Throwable t) { + out.println("Error accessing attributes " + attributes + ": " + t); + } + } + + private boolean skip(File dir) { + if (isWindows()) { + showAllAttributes(dir.toPath()); + out.println("Windows: cannot set directory read only:" + dir); + out.println("TEST CASE SKIPPED"); + return true; + } else { + return false; + } + } + + private boolean isWindows() { + return System.getProperty("os.name").toLowerCase(Locale.US).startsWith("windows"); + } } diff --git a/test/langtools/jdk/jshell/ExecutionControlTestBase.java b/test/langtools/jdk/jshell/ExecutionControlTestBase.java index 6bf5a55fb72..201150797f5 100644 --- a/test/langtools/jdk/jshell/ExecutionControlTestBase.java +++ b/test/langtools/jdk/jshell/ExecutionControlTestBase.java @@ -25,12 +25,30 @@ import org.testng.annotations.Test; import jdk.jshell.VarSnippet; +import java.net.InetAddress; import static jdk.jshell.Snippet.Status.VALID; import static jdk.jshell.Snippet.SubKind.*; public class ExecutionControlTestBase extends KullaTesting { + String standardListenSpec() { + String loopback = InetAddress.getLoopbackAddress().getHostAddress(); + return "jdi:hostname(" + loopback + ")"; + } + + String standardLaunchSpec() { + return "jdi:launch(true)"; + } + + String standardJdiSpec() { + return "jdi"; + } + + String standardSpecs() { + return "5(" + standardListenSpec() + "), 6(" + standardLaunchSpec() + "), 7(" + standardJdiSpec() + ")"; + } + @Test public void classesDeclaration() { assertEval("interface A { }"); diff --git a/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java b/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java index 4f6700927a3..da838798f8e 100644 --- a/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java +++ b/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java @@ -129,7 +129,9 @@ public void setUp() { Map pm = provider.defaultParameters(); pm.put("0", "alwaysFailing"); pm.put("1", "alwaysFailing"); - pm.put("2", "jdi"); + pm.put("2", standardListenSpec()); + pm.put("3", standardLaunchSpec()); + pm.put("4", standardJdiSpec()); setUp(builder -> builder.executionEngine(provider, pm)); } @@ -156,6 +158,10 @@ public void variables() { assertTrue(log.contains("Failure failover -- 1 = alwaysFailing"), log); assertTrue(log.contains("This operation intentionally broken"), log); log = logged.get(Level.FINEST).get(0); - assertTrue(log.contains("Success failover -- 2 = jdi"), log); + assertTrue( + log.contains("Success failover -- 2 = " + standardListenSpec()) + || log.contains("Success failover -- 3 = " + standardLaunchSpec()) + || log.contains("Success failover -- 4 = " + standardJdiSpec()), + log); } } diff --git a/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java b/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java index 0cc828a01d3..f3218fab7c7 100644 --- a/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java +++ b/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java @@ -42,6 +42,7 @@ public class FailOverExecutionControlDyingLaunchTest extends ExecutionControlTes @Override public void setUp() { setUp(builder -> builder.executionEngine( - "failover:0(jdi:remoteAgent(DyingRemoteAgent),launch(true)), 4(jdi:launch(true))")); + "failover:0(jdi:remoteAgent(DyingRemoteAgent),launch(true)), " + + standardSpecs())); } } diff --git a/test/langtools/jdk/jshell/FailOverExecutionControlHangingLaunchTest.java b/test/langtools/jdk/jshell/FailOverExecutionControlHangingLaunchTest.java index 852f891f8c1..778d004915c 100644 --- a/test/langtools/jdk/jshell/FailOverExecutionControlHangingLaunchTest.java +++ b/test/langtools/jdk/jshell/FailOverExecutionControlHangingLaunchTest.java @@ -41,6 +41,7 @@ public class FailOverExecutionControlHangingLaunchTest extends ExecutionControlT @Override public void setUp() { setUp(builder -> builder.executionEngine( - "failover:0(jdi:remoteAgent(HangingRemoteAgent),launch(true)), 1(jdi:launch(true))")); + "failover:0(jdi:remoteAgent(HangingRemoteAgent),launch(true)), " + + standardSpecs())); } } diff --git a/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java b/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java index 8c0131df288..f22dd821f40 100644 --- a/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java +++ b/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java @@ -45,6 +45,6 @@ public void setUp() { String loopback = InetAddress.getLoopbackAddress().getHostAddress(); setUp(builder -> builder.executionEngine( "failover:0(jdi:remoteAgent(HangingRemoteAgent),hostname(" + loopback + "))," - + "1(jdi:hostname(" + loopback + "))")); + + standardSpecs())); } } diff --git a/test/langtools/jdk/jshell/FailOverExecutionControlTest.java b/test/langtools/jdk/jshell/FailOverExecutionControlTest.java index b3f140adc9d..0843351815f 100644 --- a/test/langtools/jdk/jshell/FailOverExecutionControlTest.java +++ b/test/langtools/jdk/jshell/FailOverExecutionControlTest.java @@ -40,7 +40,8 @@ public class FailOverExecutionControlTest extends ExecutionControlTestBase { @BeforeMethod @Override public void setUp() { - setUp(builder -> builder.executionEngine("failover:0(nonExistent), 1(nonExistent), 2(jdi:launch(true))")); + setUp(builder -> builder.executionEngine("failover:0(expectedFailureNonExistent1), 1(expectedFailureNonExistent2), " + + standardSpecs())); } } diff --git a/test/langtools/tools/doclint/AccessibilityTest5.java b/test/langtools/tools/doclint/AccessibilityTest5.java new file mode 100644 index 00000000000..5e357ab15cd --- /dev/null +++ b/test/langtools/tools/doclint/AccessibilityTest5.java @@ -0,0 +1,30 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8247955 + * @summary Add new doclint package + * @modules jdk.compiler/com.sun.tools.doclint + * @build DocLintTester + * @run main DocLintTester -XhtmlVersion:html5 -Xmsgs:-accessibility AccessibilityTest5.java + * @run main DocLintTester -XhtmlVersion:html5 -ref AccessibilityTest5.out AccessibilityTest5.java + */ + +// This test should be merged into AccessibilityTest.java when we drop support for html4. + +/** */ +public class AccessibilityTest5 { + /** + *
    ok
    head
    data
    + */ + public void table_with_caption() { } + + /** + *
    head
    data
    + */ + public void table_without_caption() { } + + /** + *
    head
    data
    + */ + public void table_presentation() { } +} + diff --git a/test/langtools/tools/doclint/AccessibilityTest5.out b/test/langtools/tools/doclint/AccessibilityTest5.out new file mode 100644 index 00000000000..23ccfda6681 --- /dev/null +++ b/test/langtools/tools/doclint/AccessibilityTest5.out @@ -0,0 +1,4 @@ +AccessibilityTest5.java:21: error: no summary or caption for table + *
    head
    data
    + ^ +1 error diff --git a/test/langtools/tools/javac/platform/PreviewAPIsWithRelease.java b/test/langtools/tools/javac/platform/PreviewAPIsWithRelease.java new file mode 100644 index 00000000000..155dd5335d9 --- /dev/null +++ b/test/langtools/tools/javac/platform/PreviewAPIsWithRelease.java @@ -0,0 +1,15 @@ +/** + * @test /nodynamiccopyright/ + * @bug 8246704 + * @summary Verify preview APIs are reported correctly when using --release. + * @compile/fail/ref=PreviewAPIsWithRelease.out -XDrawDiagnostics --release 14 PreviewAPIsWithRelease.java + */ + +import com.sun.source.tree.Tree.Kind; + +public class PreviewAPIsWithRelease { + void test() { + "".stripIndent(); + Kind r = Kind.RECORD; + } +} diff --git a/test/langtools/tools/javac/platform/PreviewAPIsWithRelease.out b/test/langtools/tools/javac/platform/PreviewAPIsWithRelease.out new file mode 100644 index 00000000000..f07ff3a3b96 --- /dev/null +++ b/test/langtools/tools/javac/platform/PreviewAPIsWithRelease.out @@ -0,0 +1,4 @@ +PreviewAPIsWithRelease.java:12:11: compiler.err.is.preview: stripIndent() +PreviewAPIsWithRelease.java:13:22: compiler.warn.is.preview: RECORD +1 error +1 warning diff --git a/test/langtools/tools/javac/sealed/SealedCompilationTests.java b/test/langtools/tools/javac/sealed/SealedCompilationTests.java index eacd60f6b32..5313d5a1275 100644 --- a/test/langtools/tools/javac/sealed/SealedCompilationTests.java +++ b/test/langtools/tools/javac/sealed/SealedCompilationTests.java @@ -768,8 +768,14 @@ sealed class C permits Sub {} } } - public void testParameterizedPermitted() { + private static String[] PRIMITIVES_VOID_AND_PRIMITIVE_ARRAYS = new String[] { + "byte", "short", "int", "long", "float", "double", "char", "boolean", "void", + "byte[]", "short[]", "int[]", "long[]", "float[]", "double[]", "char[]", "boolean[]" + }; + + public void testPermitsClause() { for (String s : List.of( + // can't include a parameterized type """ sealed class C permits Sub {} final class Sub extends C {} @@ -777,10 +783,52 @@ final class Sub extends C {} """ sealed class C permits Sub {} final class Sub extends C {} + """, + """ + sealed class C permits Sub {} + non-sealed class Sub extends C {} + """, + """ + sealed interface IC permits ID {} + non-sealed interface ID extends IC {} + """, + + // can't include an array type + """ + sealed class C permits Sub[] {} + final class Sub extends C {} + """, + """ + sealed class C permits Sub[] {} + non-sealed class Sub extends C {} + """, + """ + sealed interface IC permits ID[] {} + non-sealed interface ID extends IC {} """ )) { assertFail("compiler.err.expected", s); } + + for (String s : List.of( + // can't include primitives, void or primitive arrays + """ + sealed class C permits # {} + final class Sub extends C {} + """, + """ + sealed class C permits # {} + non-sealed class Sub extends C {} + """, + """ + sealed interface IC permits # {} + non-sealed interface ID extends IC {} + """ + )) { + for (String t: PRIMITIVES_VOID_AND_PRIMITIVE_ARRAYS){ + assertFail("compiler.err.expected", s, t); + } + } } private Path[] findJavaFiles(Path... paths) throws IOException { diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index 7c5ede485eb..57cddedfc90 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -110,6 +110,8 @@ public boolean isClassAlive(String name) { public native int getSymbolRefcount(String name); + public native boolean deflateIdleMonitors(); + private native boolean isMonitorInflated0(Object obj); public boolean isMonitorInflated(Object obj) { Objects.requireNonNull(obj); diff --git a/test/micro/org/openjdk/bench/java/io/RecordDeserialization.java b/test/micro/org/openjdk/bench/java/io/RecordDeserialization.java new file mode 100644 index 00000000000..b2dbefe3c05 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/io/RecordDeserialization.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + +Sample runs on Ryzen 3700X: + +before 8247532: + +Benchmark (length) Mode Cnt Score Error Units +RecordDeserialization.deserializeClasses 10 avgt 10 8.382 : 0.013 us/op +RecordDeserialization.deserializeClasses 100 avgt 10 33.736 : 0.171 us/op +RecordDeserialization.deserializeClasses 1000 avgt 10 271.224 : 0.953 us/op +RecordDeserialization.deserializeRecords 10 avgt 10 58.606 : 0.446 us/op +RecordDeserialization.deserializeRecords 100 avgt 10 530.044 : 1.752 us/op +RecordDeserialization.deserializeRecords 1000 avgt 10 5335.624 : 44.942 us/op + +after 8247532: + +Benchmark (length) Mode Cnt Score Error Units +RecordDeserialization.deserializeClasses 10 avgt 10 8.681 : 0.155 us/op +RecordDeserialization.deserializeClasses 100 avgt 10 32.496 : 0.087 us/op +RecordDeserialization.deserializeClasses 1000 avgt 10 279.014 : 1.189 us/op +RecordDeserialization.deserializeRecords 10 avgt 10 8.537 : 0.032 us/op +RecordDeserialization.deserializeRecords 100 avgt 10 31.451 : 0.083 us/op +RecordDeserialization.deserializeRecords 1000 avgt 10 250.854 : 2.772 us/op + +*/ + +package org.openjdk.bench.java.io; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.io.UncheckedIOException; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +/** + * A micro benchmark used to measure/compare the performance of + * de-serializing record(s) vs. classical class(es) + */ +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 10, time = 1) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +@Fork(value = 1, warmups = 0, jvmArgsAppend = "--enable-preview") +public class RecordDeserialization { + + public record PointR(int x, int y) implements Serializable {} + + public record LineR(PointR p1, PointR p2) implements Serializable {} + + public static class PointC implements Serializable { + private final int x, y; + + public PointC(int x, int y) { + this.x = x; + this.y = y; + } + } + + public static class LineC implements Serializable { + private final PointC p1, p2; + + public LineC(PointC p1, PointC p2) { + this.p1 = p1; + this.p2 = p2; + } + } + + private byte[] lineRsBytes, lineCsBytes; + + private static LineR newLineR() { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + return new LineR(new PointR(rnd.nextInt(), rnd.nextInt()), + new PointR(rnd.nextInt(), rnd.nextInt())); + } + + private static LineC newLineC() { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + return new LineC(new PointC(rnd.nextInt(), rnd.nextInt()), + new PointC(rnd.nextInt(), rnd.nextInt())); + } + + private static byte[] serialize(Object o) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(o); + oos.close(); + return baos.toByteArray(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static Object deserialize(byte[] bytes) { + try { + return new ObjectInputStream(new ByteArrayInputStream(bytes)) + .readObject(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Param({"10", "100", "1000"}) + public int length; + + @Setup(Level.Trial) + public void setup() { + LineR[] lineRs = IntStream + .range(0, length) + .mapToObj(i -> newLineR()) + .toArray(LineR[]::new); + lineRsBytes = serialize(lineRs); + + LineC[] lineCs = IntStream + .range(0, length) + .mapToObj(i -> newLineC()) + .toArray(LineC[]::new); + lineCsBytes = serialize(lineCs); + } + + @Benchmark + public Object deserializeRecords() { + return deserialize(lineRsBytes); + } + + @Benchmark + public Object deserializeClasses() { + return deserialize(lineCsBytes); + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkOps.java b/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkOps.java index e5c42448163..69950eacbac 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkOps.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/foreign/BulkOps.java @@ -35,6 +35,7 @@ import sun.misc.Unsafe; import jdk.incubator.foreign.MemorySegment; +import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT; @@ -60,6 +61,36 @@ public class BulkOps { static final MemorySegment bytesSegment = MemorySegment.ofArray(bytes); static final int UNSAFE_INT_OFFSET = unsafe.arrayBaseOffset(int[].class); + // large(ish) segments/buffers with same content, 0, for mismatch, non-multiple-of-8 sized + static final int SIZE_WITH_TAIL = (1024 * 1024) + 7; + static final MemorySegment mismatchSegmentLarge1 = MemorySegment.allocateNative(SIZE_WITH_TAIL); + static final MemorySegment mismatchSegmentLarge2 = MemorySegment.allocateNative(SIZE_WITH_TAIL); + static final ByteBuffer mismatchBufferLarge1 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); + static final ByteBuffer mismatchBufferLarge2 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); + + // mismatch at first byte + static final MemorySegment mismatchSegmentSmall1 = MemorySegment.allocateNative(7); + static final MemorySegment mismatchSegmentSmall2 = MemorySegment.allocateNative(7); + static final ByteBuffer mismatchBufferSmall1 = ByteBuffer.allocateDirect(7); + static final ByteBuffer mismatchBufferSmall2 = ByteBuffer.allocateDirect(7); + static { + mismatchSegmentSmall1.fill((byte) 0xFF); + mismatchBufferSmall1.put((byte) 0xFF).clear(); + // verify expected mismatch indices + long si = mismatchSegmentLarge1.mismatch(mismatchSegmentLarge2); + if (si != -1) + throw new AssertionError("Unexpected mismatch index:" + si); + int bi = mismatchBufferLarge1.mismatch(mismatchBufferLarge2); + if (bi != -1) + throw new AssertionError("Unexpected mismatch index:" + bi); + si = mismatchSegmentSmall1.mismatch(mismatchSegmentSmall2); + if (si != 0) + throw new AssertionError("Unexpected mismatch index:" + si); + bi = mismatchBufferSmall1.mismatch(mismatchBufferSmall2); + if (bi != 0) + throw new AssertionError("Unexpected mismatch index:" + bi); + } + static { for (int i = 0 ; i < bytes.length ; i++) { bytes[i] = i; @@ -89,4 +120,28 @@ public void unsafe_copy() { public void segment_copy() { segment.copyFrom(bytesSegment); } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public long mismatch_large_segment() { + return mismatchSegmentLarge1.mismatch(mismatchSegmentLarge2); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int mismatch_large_bytebuffer() { + return mismatchBufferLarge1.mismatch(mismatchBufferLarge2); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public long mismatch_small_segment() { + return mismatchSegmentSmall1.mismatch(mismatchSegmentSmall2); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int mismatch_small_bytebuffer() { + return mismatchBufferSmall1.mismatch(mismatchBufferSmall2); + } } diff --git a/test/micro/org/openjdk/bench/vm/compiler/ArrayFill.java b/test/micro/org/openjdk/bench/vm/compiler/ArrayFill.java new file mode 100644 index 00000000000..872732fbe52 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/ArrayFill.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; +import java.util.Arrays; + +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ArrayFill { + @Param("65536") private int size; + + private byte[] ba; + private short[] sa; + private int[] ia; + + @Setup + public void setup() { + ba = new byte[size]; + sa = new short[size]; + ia = new int[size]; + } + + @Benchmark + public void fillByteArray() { + for (int i = 0; i < size; i++) { + ba[i] = (byte) 123; + } + } + + @Benchmark + public void fillShortArray() { + for (int i = 0; i < size; i++) { + sa[i] = (short) 12345; + } + } + + @Benchmark + public void fillIntArray() { + for (int i = 0; i < size; i++) { + ia[i] = 1234567890; + } + } + + @Benchmark + public void zeroByteArray() { + for (int i = 0; i < size; i++) { + ba[i] = 0; + } + } + + @Benchmark + public void zeroShortArray() { + for (int i = 0; i < size; i++) { + sa[i] = 0; + } + } + + @Benchmark + public void zeroIntArray() { + for (int i = 0; i < size; i++) { + ia[i] = 0; + } + } +} + diff --git a/test/micro/org/openjdk/bench/vm/compiler/BitTest.java b/test/micro/org/openjdk/bench/vm/compiler/BitTest.java new file mode 100644 index 00000000000..35669cd0ffa --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/BitTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class BitTest { + + private static final int COUNT = 1000; + + @Benchmark + public int bitTestAndBranch() { + int dummy = 0; + for (int value = 0; value < COUNT; value++) { + dummy++; + if ((value & 32) == 32) { + dummy = value ^ dummy; + } else { + dummy = value ^ value; + } + } + return dummy; + } +}