mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 03:24:38 +02:00
Merge
This commit is contained in:
commit
3e85467bc6
322 changed files with 8135 additions and 4008 deletions
1
.hgtags
1
.hgtags
|
@ -518,3 +518,4 @@ f0f5d23449d31f1b3580c8a73313918cafeaefd7 jdk-12+11
|
||||||
8897e41b327c0a5601c6ba2bba5d07f15a3ffc91 jdk-12+14
|
8897e41b327c0a5601c6ba2bba5d07f15a3ffc91 jdk-12+14
|
||||||
6f04692c7d5137ee34a6bd94c0c8a6c9219cb127 jdk-12+14
|
6f04692c7d5137ee34a6bd94c0c8a6c9219cb127 jdk-12+14
|
||||||
f8626bcc169813a4b2a15880386b952719d1d6d1 jdk-12+15
|
f8626bcc169813a4b2a15880386b952719d1d6d1 jdk-12+15
|
||||||
|
199658d1ef860cdc17055b4fd3e94b057f292fe9 jdk-12+16
|
||||||
|
|
|
@ -46,6 +46,7 @@ $(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
|
||||||
SETUP := GENERATE_OLDBYTECODE, \
|
SETUP := GENERATE_OLDBYTECODE, \
|
||||||
SRC := $(BUILD_TOOLS_SRC_DIRS), \
|
SRC := $(BUILD_TOOLS_SRC_DIRS), \
|
||||||
EXCLUDES := \
|
EXCLUDES := \
|
||||||
|
build/tools/classlist \
|
||||||
build/tools/deps \
|
build/tools/deps \
|
||||||
build/tools/docs \
|
build/tools/docs \
|
||||||
build/tools/jigsaw \
|
build/tools/jigsaw \
|
||||||
|
|
|
@ -31,15 +31,17 @@ default: all
|
||||||
|
|
||||||
include $(SPEC)
|
include $(SPEC)
|
||||||
include MakeBase.gmk
|
include MakeBase.gmk
|
||||||
include JarArchive.gmk
|
include SetupJavaCompilers.gmk
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Create a jar with our generator class. Using a jar is intentional since it
|
# Create a jar with our generator class. Using a jar is intentional since it
|
||||||
# will load more classes
|
# will load more classes
|
||||||
|
|
||||||
$(eval $(call SetupJarArchive, CLASSLIST_JAR, \
|
$(eval $(call SetupJavaCompilation, CLASSLIST_JAR, \
|
||||||
SRCS := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
|
SETUP := GENERATE_JDKBYTECODE, \
|
||||||
|
SRC := $(TOPDIR)/make/jdk/src/classes, \
|
||||||
INCLUDES := build/tools/classlist, \
|
INCLUDES := build/tools/classlist, \
|
||||||
|
BIN := $(BUILDTOOLS_OUTPUTDIR)/classlist_classes, \
|
||||||
JAR := $(SUPPORT_OUTPUTDIR)/classlist.jar, \
|
JAR := $(SUPPORT_OUTPUTDIR)/classlist.jar, \
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
@ -656,8 +656,11 @@ dups = \
|
||||||
|
|
||||||
# String equals
|
# String equals
|
||||||
equals = \
|
equals = \
|
||||||
$(and $(findstring $(strip $1),$(strip $2)),\
|
$(if $(strip $1)$(strip $2),$(strip \
|
||||||
$(findstring $(strip $2),$(strip $1)))
|
$(and $(findstring $(strip $1),$(strip $2)),\
|
||||||
|
$(findstring $(strip $2),$(strip $1)))), \
|
||||||
|
true \
|
||||||
|
)
|
||||||
|
|
||||||
# Remove a whole list of prefixes
|
# Remove a whole list of prefixes
|
||||||
# $1 - List of prefixes
|
# $1 - List of prefixes
|
||||||
|
|
|
@ -67,7 +67,6 @@ endef
|
||||||
# Param 2: Working directory
|
# Param 2: Working directory
|
||||||
# Param 3: Source file
|
# Param 3: Source file
|
||||||
# Param 4: Compile command
|
# Param 4: Compile command
|
||||||
# Param 5: Object name
|
|
||||||
################################################################################
|
################################################################################
|
||||||
define WriteCompileCommandsFragment
|
define WriteCompileCommandsFragment
|
||||||
$(call LogInfo, Creating compile commands fragment for $(notdir $3))
|
$(call LogInfo, Creating compile commands fragment for $(notdir $3))
|
||||||
|
@ -76,8 +75,7 @@ define WriteCompileCommandsFragment
|
||||||
"directory": "$(strip $2)"$(COMMA) \
|
"directory": "$(strip $2)"$(COMMA) \
|
||||||
"file": "$(strip $3)"$(COMMA) \
|
"file": "$(strip $3)"$(COMMA) \
|
||||||
"command": "$(strip $(subst $(DQUOTE),\$(DQUOTE),$(subst \,\\,\
|
"command": "$(strip $(subst $(DQUOTE),\$(DQUOTE),$(subst \,\\,\
|
||||||
$(subst $(FIXPATH),,$4))))"$(COMMA) \
|
$(subst $(FIXPATH),,$4))))" \
|
||||||
"output": "$(strip $5)" \
|
|
||||||
}$(COMMA), \
|
}$(COMMA), \
|
||||||
$1)
|
$1)
|
||||||
endef
|
endef
|
||||||
|
@ -331,7 +329,7 @@ define SetupCompileNativeFileBody
|
||||||
|
|
||||||
$$($1_OBJ_JSON): $$($1_OBJ_DEPS)
|
$$($1_OBJ_JSON): $$($1_OBJ_DEPS)
|
||||||
$$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$($1_SRC_FILE), \
|
$$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$($1_SRC_FILE), \
|
||||||
$$($1_COMPILER) $$($1_COMPILE_OPTIONS), $$($1_OBJ))
|
$$($1_COMPILER) $$($1_COMPILE_OPTIONS))
|
||||||
|
|
||||||
$$($1_OBJ): $$($1_OBJ_DEPS) | $$($$($1_BASE)_BUILD_INFO)
|
$$($1_OBJ): $$($1_OBJ_DEPS) | $$($$($1_BASE)_BUILD_INFO)
|
||||||
$$(call LogInfo, Compiling $$($1_FILENAME) (for $$($$($1_BASE)_BASENAME)))
|
$$(call LogInfo, Compiling $$($1_FILENAME) (for $$($$($1_BASE)_BASENAME)))
|
||||||
|
@ -744,7 +742,7 @@ define SetupNativeCompilationBody
|
||||||
|
|
||||||
$$($1_PCH_FILE_JSON): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE)
|
$$($1_PCH_FILE_JSON): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE)
|
||||||
$$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$<, \
|
$$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$<, \
|
||||||
$$($1_PCH_COMMAND) $$< -o $$($1_PCH_FILE), $$($1_PCH_FILE))
|
$$($1_PCH_COMMAND) $$< -o $$($1_PCH_FILE))
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -66,6 +66,15 @@ public class HelloClasslist {
|
||||||
Stream.of(helloWorld.split(","))
|
Stream.of(helloWorld.split(","))
|
||||||
.forEach(System.out::println);
|
.forEach(System.out::println);
|
||||||
|
|
||||||
|
// Common concatenation patterns
|
||||||
|
String const_I = "string" + args.length;
|
||||||
|
String const_S = "string" + String.valueOf(args.length);
|
||||||
|
String S_const = String.valueOf(args.length) + "string";
|
||||||
|
String S_S = String.valueOf(args.length) + String.valueOf(args.length);
|
||||||
|
String const_J = "string" + System.currentTimeMillis();
|
||||||
|
String I_const = args.length + "string";
|
||||||
|
String J_const = System.currentTimeMillis() + "string";
|
||||||
|
|
||||||
String newDate = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(
|
String newDate = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(
|
||||||
LocalDateTime.now(ZoneId.of("GMT")));
|
LocalDateTime.now(ZoneId.of("GMT")));
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::disarm(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return false;
|
||||||
|
}
|
40
src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp
Normal file
40
src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::disarm(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -110,7 +110,6 @@ class VM_Version: public Abstract_VM_Version {
|
||||||
static bool supports_kuser_cmpxchg64() { return _kuser_helper_version >= KUSER_VERSION_CMPXCHG64; }
|
static bool supports_kuser_cmpxchg64() { return _kuser_helper_version >= KUSER_VERSION_CMPXCHG64; }
|
||||||
// Override Abstract_VM_Version implementation
|
// Override Abstract_VM_Version implementation
|
||||||
static bool use_biased_locking();
|
static bool use_biased_locking();
|
||||||
static const char* vm_info_string();
|
|
||||||
|
|
||||||
static bool has_vfp() { return (_features & vfp_m) != 0; }
|
static bool has_vfp() { return (_features & vfp_m) != 0; }
|
||||||
static bool has_vfp3_32() { return (_features & vfp3_32_m) != 0; }
|
static bool has_vfp3_32() { return (_features & vfp3_32_m) != 0; }
|
||||||
|
|
|
@ -318,20 +318,3 @@ bool VM_Version::use_biased_locking() {
|
||||||
//
|
//
|
||||||
return (!os::is_MP() && (arm_arch() > 5)) ? false : true;
|
return (!os::is_MP() && (arm_arch() > 5)) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EXP
|
|
||||||
|
|
||||||
// Temporary override for experimental features
|
|
||||||
// Copied from Abstract_VM_Version
|
|
||||||
const char* VM_Version::vm_info_string() {
|
|
||||||
switch (Arguments::mode()) {
|
|
||||||
case Arguments::_int:
|
|
||||||
return UseSharedSpaces ? "interpreted mode, sharing" EXP : "interpreted mode" EXP;
|
|
||||||
case Arguments::_mixed:
|
|
||||||
return UseSharedSpaces ? "mixed mode, sharing" EXP : "mixed mode" EXP;
|
|
||||||
case Arguments::_comp:
|
|
||||||
return UseSharedSpaces ? "compiled mode, sharing" EXP : "compiled mode" EXP;
|
|
||||||
};
|
|
||||||
ShouldNotReachHere();
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
40
src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp
Normal file
40
src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::disarm(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return false;
|
||||||
|
}
|
40
src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp
Normal file
40
src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::disarm(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return false;
|
||||||
|
}
|
40
src/hotspot/cpu/sparc/gc/shared/barrierSetNMethod_sparc.cpp
Normal file
40
src/hotspot/cpu/sparc/gc/shared/barrierSetNMethod_sparc.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::disarm(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -26,6 +26,8 @@
|
||||||
#include "c1/c1_MacroAssembler.hpp"
|
#include "c1/c1_MacroAssembler.hpp"
|
||||||
#include "c1/c1_Runtime1.hpp"
|
#include "c1/c1_Runtime1.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
#include "gc/shared/barrierSet.hpp"
|
||||||
|
#include "gc/shared/barrierSetAssembler.hpp"
|
||||||
#include "gc/shared/collectedHeap.hpp"
|
#include "gc/shared/collectedHeap.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "oops/arrayOop.hpp"
|
#include "oops/arrayOop.hpp"
|
||||||
|
@ -330,6 +332,9 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_by
|
||||||
}
|
}
|
||||||
#endif // TIERED
|
#endif // TIERED
|
||||||
decrement(rsp, frame_size_in_bytes); // does not emit code for frame_size == 0
|
decrement(rsp, frame_size_in_bytes); // does not emit code for frame_size == 0
|
||||||
|
|
||||||
|
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||||
|
bs->nmethod_entry_barrier(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "gc/shared/barrierSet.hpp"
|
||||||
#include "gc/shared/barrierSetAssembler.hpp"
|
#include "gc/shared/barrierSetAssembler.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
#include "gc/shared/collectedHeap.hpp"
|
#include "gc/shared/collectedHeap.hpp"
|
||||||
#include "interpreter/interp_masm.hpp"
|
#include "interpreter/interp_masm.hpp"
|
||||||
#include "runtime/jniHandles.hpp"
|
#include "runtime/jniHandles.hpp"
|
||||||
|
@ -322,3 +324,22 @@ void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm, Register th
|
||||||
__ adcl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())+4), 0);
|
__ adcl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())+4), 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) {
|
||||||
|
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
|
||||||
|
if (bs_nm == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifndef _LP64
|
||||||
|
ShouldNotReachHere();
|
||||||
|
#else
|
||||||
|
Label continuation;
|
||||||
|
Register thread = LP64_ONLY(r15_thread);
|
||||||
|
Address disarmed_addr(thread, in_bytes(bs_nm->thread_disarmed_offset()));
|
||||||
|
__ align(8);
|
||||||
|
__ cmpl(disarmed_addr, 0);
|
||||||
|
__ jcc(Assembler::equal, continuation);
|
||||||
|
__ call(RuntimeAddress(StubRoutines::x86::method_entry_barrier()));
|
||||||
|
__ bind(continuation);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -83,6 +83,8 @@ public:
|
||||||
Label& slow_case);
|
Label& slow_case);
|
||||||
|
|
||||||
virtual void barrier_stubs_init() {}
|
virtual void barrier_stubs_init() {}
|
||||||
|
|
||||||
|
virtual void nmethod_entry_barrier(MacroAssembler* masm);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPU_X86_GC_SHARED_BARRIERSETASSEMBLER_X86_HPP
|
#endif // CPU_X86_GC_SHARED_BARRIERSETASSEMBLER_X86_HPP
|
||||||
|
|
155
src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp
Normal file
155
src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "code/codeCache.hpp"
|
||||||
|
#include "code/nativeInst.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "runtime/sharedRuntime.hpp"
|
||||||
|
#include "runtime/thread.hpp"
|
||||||
|
#include "utilities/align.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
class NativeNMethodCmpBarrier: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
enum Intel_specific_constants {
|
||||||
|
instruction_code = 0x81,
|
||||||
|
instruction_size = 8,
|
||||||
|
imm_offset = 4,
|
||||||
|
instruction_rex_prefix = Assembler::REX | Assembler::REX_B,
|
||||||
|
instruction_modrm = 0x7f // [r15 + offset]
|
||||||
|
};
|
||||||
|
|
||||||
|
address instruction_address() const { return addr_at(0); }
|
||||||
|
address immediate_address() const { return addr_at(imm_offset); }
|
||||||
|
|
||||||
|
jint get_immedate() const { return int_at(imm_offset); }
|
||||||
|
void set_immediate(jint imm) { set_int_at(imm_offset, imm); }
|
||||||
|
void verify() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
void NativeNMethodCmpBarrier::verify() const {
|
||||||
|
if (((uintptr_t) instruction_address()) & 0x7) {
|
||||||
|
fatal("Not properly aligned");
|
||||||
|
}
|
||||||
|
|
||||||
|
int prefix = ubyte_at(0);
|
||||||
|
if (prefix != instruction_rex_prefix) {
|
||||||
|
tty->print_cr("Addr: " INTPTR_FORMAT " Prefix: 0x%x", p2i(instruction_address()),
|
||||||
|
prefix);
|
||||||
|
fatal("not a cmp barrier");
|
||||||
|
}
|
||||||
|
|
||||||
|
int inst = ubyte_at(1);
|
||||||
|
if (inst != instruction_code) {
|
||||||
|
tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()),
|
||||||
|
inst);
|
||||||
|
fatal("not a cmp barrier");
|
||||||
|
}
|
||||||
|
|
||||||
|
int modrm = ubyte_at(2);
|
||||||
|
if (modrm != instruction_modrm) {
|
||||||
|
tty->print_cr("Addr: " INTPTR_FORMAT " mod/rm: 0x%x", p2i(instruction_address()),
|
||||||
|
modrm);
|
||||||
|
fatal("not a cmp barrier");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||||
|
/*
|
||||||
|
* [ callers frame ]
|
||||||
|
* [ callers return address ] <- callers rsp
|
||||||
|
* [ callers rbp ] <- callers rbp
|
||||||
|
* [ callers frame slots ]
|
||||||
|
* [ return_address ] <- return_address_ptr
|
||||||
|
* [ cookie ] <- used to write the new rsp (callers rsp)
|
||||||
|
* [ stub rbp ]
|
||||||
|
* [ stub stuff ]
|
||||||
|
*/
|
||||||
|
|
||||||
|
address* stub_rbp = return_address_ptr - 2;
|
||||||
|
address* callers_rsp = return_address_ptr + nm->frame_size(); /* points to callers return_address now */
|
||||||
|
address* callers_rbp = callers_rsp - 1; // 1 to move to the callers return address, 1 more to move to the rbp
|
||||||
|
address* cookie = return_address_ptr - 1;
|
||||||
|
|
||||||
|
LogTarget(Trace, nmethod, barrier) out;
|
||||||
|
if (out.is_enabled()) {
|
||||||
|
Thread* thread = Thread::current();
|
||||||
|
assert(thread->is_Java_thread(), "must be JavaThread");
|
||||||
|
JavaThread* jth = (JavaThread*) thread;
|
||||||
|
ResourceMark mark;
|
||||||
|
log_trace(nmethod, barrier)("deoptimize(nmethod: %p, return_addr: %p, osr: %d, thread: %p(%s), making rsp: %p) -> %p",
|
||||||
|
nm, (address *) return_address_ptr, nm->is_osr_method(), jth,
|
||||||
|
jth->get_thread_name(), callers_rsp, nm->verified_entry_point());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(nm->frame_size() >= 3, "invariant");
|
||||||
|
assert(*cookie == (address) -1, "invariant");
|
||||||
|
|
||||||
|
// Preserve caller rbp.
|
||||||
|
*stub_rbp = *callers_rbp;
|
||||||
|
|
||||||
|
// At the cookie address put the callers rsp.
|
||||||
|
*cookie = (address) callers_rsp; // should point to the return address
|
||||||
|
|
||||||
|
// In the slot that used to be the callers rbp we put the address that our stub needs to jump to at the end.
|
||||||
|
// Overwriting the caller rbp should be okay since our stub rbp has the same value.
|
||||||
|
address* jmp_addr_ptr = callers_rbp;
|
||||||
|
*jmp_addr_ptr = SharedRuntime::get_handle_wrong_method_stub();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the offset of the entry barrier from where the frame is completed.
|
||||||
|
// If any code changes between the end of the verified entry where the entry
|
||||||
|
// barrier resides, and the completion of the frame, then
|
||||||
|
// NativeNMethodCmpBarrier::verify() will immediately complain when it does
|
||||||
|
// not find the expected native instruction at this offset, which needs updating.
|
||||||
|
// Note that this offset is invariant of PreserveFramePointer.
|
||||||
|
static const int entry_barrier_offset = -19;
|
||||||
|
|
||||||
|
static NativeNMethodCmpBarrier* native_nmethod_barrier(nmethod* nm) {
|
||||||
|
address barrier_address = nm->code_begin() + nm->frame_complete_offset() + entry_barrier_offset;
|
||||||
|
NativeNMethodCmpBarrier* barrier = reinterpret_cast<NativeNMethodCmpBarrier*>(barrier_address);
|
||||||
|
debug_only(barrier->verify());
|
||||||
|
return barrier;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::disarm(nmethod* nm) {
|
||||||
|
if (!supports_entry_barrier(nm)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeNMethodCmpBarrier* cmp = native_nmethod_barrier(nm);
|
||||||
|
cmp->set_immediate(disarmed_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
|
if (!supports_entry_barrier(nm)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeNMethodCmpBarrier* cmp = native_nmethod_barrier(nm);
|
||||||
|
return (disarmed_value() != cmp->get_immedate());
|
||||||
|
}
|
|
@ -5453,7 +5453,7 @@ void MacroAssembler::reinit_heapbase() {
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
|
|
||||||
// C2 compiled method's prolog code.
|
// C2 compiled method's prolog code.
|
||||||
void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b) {
|
void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b, bool is_stub) {
|
||||||
|
|
||||||
// WARNING: Initial instruction MUST be 5 bytes or longer so that
|
// WARNING: Initial instruction MUST be 5 bytes or longer so that
|
||||||
// NativeJump::patch_verified_entry will be able to patch out the entry
|
// NativeJump::patch_verified_entry will be able to patch out the entry
|
||||||
|
@ -5535,6 +5535,10 @@ void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!is_stub) {
|
||||||
|
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||||
|
bs->nmethod_entry_barrier(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear memory of size 'cnt' qwords, starting at 'base' using XMM/YMM registers
|
// clear memory of size 'cnt' qwords, starting at 'base' using XMM/YMM registers
|
||||||
|
|
|
@ -1588,7 +1588,7 @@ public:
|
||||||
void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); }
|
void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); }
|
||||||
|
|
||||||
// C2 compiled method's prolog code.
|
// C2 compiled method's prolog code.
|
||||||
void verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b);
|
void verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b, bool is_stub);
|
||||||
|
|
||||||
// clear memory of size 'cnt' qwords, starting at 'base';
|
// clear memory of size 'cnt' qwords, starting at 'base';
|
||||||
// if 'is_large' is set, do not try to produce short loop
|
// if 'is_large' is set, do not try to produce short loop
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "gc/shared/collectedHeap.hpp"
|
#include "gc/shared/collectedHeap.hpp"
|
||||||
#include "gc/shared/gcLocker.hpp"
|
#include "gc/shared/gcLocker.hpp"
|
||||||
|
#include "gc/shared/barrierSet.hpp"
|
||||||
|
#include "gc/shared/barrierSetAssembler.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "logging/log.hpp"
|
#include "logging/log.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
@ -2160,6 +2162,9 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||||
// -2 because return address is already present and so is saved rbp
|
// -2 because return address is already present and so is saved rbp
|
||||||
__ subptr(rsp, stack_size - 2*wordSize);
|
__ subptr(rsp, stack_size - 2*wordSize);
|
||||||
|
|
||||||
|
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||||
|
bs->nmethod_entry_barrier(masm);
|
||||||
|
|
||||||
// Frame is now completed as far as size and linkage.
|
// Frame is now completed as far as size and linkage.
|
||||||
int frame_complete = ((intptr_t)__ pc()) - start;
|
int frame_complete = ((intptr_t)__ pc()) - start;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "ci/ciUtilities.hpp"
|
#include "ci/ciUtilities.hpp"
|
||||||
#include "gc/shared/barrierSet.hpp"
|
#include "gc/shared/barrierSet.hpp"
|
||||||
#include "gc/shared/barrierSetAssembler.hpp"
|
#include "gc/shared/barrierSetAssembler.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "nativeInst_x86.hpp"
|
#include "nativeInst_x86.hpp"
|
||||||
#include "oops/instanceOop.hpp"
|
#include "oops/instanceOop.hpp"
|
||||||
|
@ -5194,6 +5195,83 @@ address generate_cipherBlockChaining_decryptVectorAESCrypt() {
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
address generate_method_entry_barrier() {
|
||||||
|
__ align(CodeEntryAlignment);
|
||||||
|
StubCodeMark mark(this, "StubRoutines", "nmethod_entry_barrier");
|
||||||
|
|
||||||
|
Label deoptimize_label;
|
||||||
|
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
__ push(-1); // cookie, this is used for writing the new rsp when deoptimizing
|
||||||
|
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
__ enter(); // save rbp
|
||||||
|
|
||||||
|
// save c_rarg0, because we want to use that value.
|
||||||
|
// We could do without it but then we depend on the number of slots used by pusha
|
||||||
|
__ push(c_rarg0);
|
||||||
|
|
||||||
|
__ lea(c_rarg0, Address(rsp, wordSize * 3)); // 1 for cookie, 1 for rbp, 1 for c_rarg0 - this should be the return address
|
||||||
|
|
||||||
|
__ pusha();
|
||||||
|
|
||||||
|
// The method may have floats as arguments, and we must spill them before calling
|
||||||
|
// the VM runtime.
|
||||||
|
assert(Argument::n_float_register_parameters_j == 8, "Assumption");
|
||||||
|
const int xmm_size = wordSize * 2;
|
||||||
|
const int xmm_spill_size = xmm_size * Argument::n_float_register_parameters_j;
|
||||||
|
__ subptr(rsp, xmm_spill_size);
|
||||||
|
__ movdqu(Address(rsp, xmm_size * 7), xmm7);
|
||||||
|
__ movdqu(Address(rsp, xmm_size * 6), xmm6);
|
||||||
|
__ movdqu(Address(rsp, xmm_size * 5), xmm5);
|
||||||
|
__ movdqu(Address(rsp, xmm_size * 4), xmm4);
|
||||||
|
__ movdqu(Address(rsp, xmm_size * 3), xmm3);
|
||||||
|
__ movdqu(Address(rsp, xmm_size * 2), xmm2);
|
||||||
|
__ movdqu(Address(rsp, xmm_size * 1), xmm1);
|
||||||
|
__ movdqu(Address(rsp, xmm_size * 0), xmm0);
|
||||||
|
|
||||||
|
__ call_VM_leaf(CAST_FROM_FN_PTR(address, static_cast<int (*)(address*)>(BarrierSetNMethod::nmethod_stub_entry_barrier)), 1);
|
||||||
|
|
||||||
|
__ movdqu(xmm0, Address(rsp, xmm_size * 0));
|
||||||
|
__ movdqu(xmm1, Address(rsp, xmm_size * 1));
|
||||||
|
__ movdqu(xmm2, Address(rsp, xmm_size * 2));
|
||||||
|
__ movdqu(xmm3, Address(rsp, xmm_size * 3));
|
||||||
|
__ movdqu(xmm4, Address(rsp, xmm_size * 4));
|
||||||
|
__ movdqu(xmm5, Address(rsp, xmm_size * 5));
|
||||||
|
__ movdqu(xmm6, Address(rsp, xmm_size * 6));
|
||||||
|
__ movdqu(xmm7, Address(rsp, xmm_size * 7));
|
||||||
|
__ addptr(rsp, xmm_spill_size);
|
||||||
|
|
||||||
|
__ cmpl(rax, 1); // 1 means deoptimize
|
||||||
|
__ jcc(Assembler::equal, deoptimize_label);
|
||||||
|
|
||||||
|
__ popa();
|
||||||
|
__ pop(c_rarg0);
|
||||||
|
|
||||||
|
__ leave();
|
||||||
|
|
||||||
|
__ addptr(rsp, 1 * wordSize); // cookie
|
||||||
|
__ ret(0);
|
||||||
|
|
||||||
|
|
||||||
|
__ BIND(deoptimize_label);
|
||||||
|
|
||||||
|
__ popa();
|
||||||
|
__ pop(c_rarg0);
|
||||||
|
|
||||||
|
__ leave();
|
||||||
|
|
||||||
|
// this can be taken out, but is good for verification purposes. getting a SIGSEGV
|
||||||
|
// here while still having a correct stack is valuable
|
||||||
|
__ testptr(rsp, Address(rsp, 0));
|
||||||
|
|
||||||
|
__ movptr(rsp, Address(rsp, 0)); // new rsp was written in the barrier
|
||||||
|
__ jmp(Address(rsp, -1 * wordSize)); // jmp target should be callers verified_entry_point
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arguments:
|
* Arguments:
|
||||||
*
|
*
|
||||||
|
@ -5831,6 +5909,11 @@ address generate_cipherBlockChaining_decryptVectorAESCrypt() {
|
||||||
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
|
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
|
||||||
&StubRoutines::_safefetchN_fault_pc,
|
&StubRoutines::_safefetchN_fault_pc,
|
||||||
&StubRoutines::_safefetchN_continuation_pc);
|
&StubRoutines::_safefetchN_continuation_pc);
|
||||||
|
|
||||||
|
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
|
||||||
|
if (bs_nm != NULL) {
|
||||||
|
StubRoutines::x86::_method_entry_barrier = generate_method_entry_barrier();
|
||||||
|
}
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
if (UseMultiplyToLenIntrinsic) {
|
if (UseMultiplyToLenIntrinsic) {
|
||||||
StubRoutines::_multiplyToLen = generate_multiplyToLen();
|
StubRoutines::_multiplyToLen = generate_multiplyToLen();
|
||||||
|
|
|
@ -55,8 +55,14 @@ class x86 {
|
||||||
static address _double_sign_mask;
|
static address _double_sign_mask;
|
||||||
static address _double_sign_flip;
|
static address _double_sign_flip;
|
||||||
|
|
||||||
|
static address _method_entry_barrier;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
static address method_entry_barrier() {
|
||||||
|
return _method_entry_barrier;
|
||||||
|
}
|
||||||
|
|
||||||
static address get_previous_fp_entry() {
|
static address get_previous_fp_entry() {
|
||||||
return _get_previous_fp_entry;
|
return _get_previous_fp_entry;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,3 +42,4 @@ address StubRoutines::x86::_float_sign_mask = NULL;
|
||||||
address StubRoutines::x86::_float_sign_flip = NULL;
|
address StubRoutines::x86::_float_sign_flip = NULL;
|
||||||
address StubRoutines::x86::_double_sign_mask = NULL;
|
address StubRoutines::x86::_double_sign_mask = NULL;
|
||||||
address StubRoutines::x86::_double_sign_flip = NULL;
|
address StubRoutines::x86::_double_sign_flip = NULL;
|
||||||
|
address StubRoutines::x86::_method_entry_barrier = NULL;
|
||||||
|
|
|
@ -619,7 +619,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||||
int framesize = C->frame_size_in_bytes();
|
int framesize = C->frame_size_in_bytes();
|
||||||
int bangsize = C->bang_size_in_bytes();
|
int bangsize = C->bang_size_in_bytes();
|
||||||
|
|
||||||
__ verified_entry(framesize, C->need_stack_bang(bangsize)?bangsize:0, C->in_24_bit_fp_mode());
|
__ verified_entry(framesize, C->need_stack_bang(bangsize)?bangsize:0, C->in_24_bit_fp_mode(), C->stub_function() != NULL);
|
||||||
|
|
||||||
C->set_frame_complete(cbuf.insts_size());
|
C->set_frame_complete(cbuf.insts_size());
|
||||||
|
|
||||||
|
|
|
@ -890,6 +890,15 @@ void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
|
||||||
st->print("# stack alignment check");
|
st->print("# stack alignment check");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
if (C->stub_function() != NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) {
|
||||||
|
st->print("\n\t");
|
||||||
|
st->print("cmpl [r15_thread + #disarmed_offset], #disarmed_value\t");
|
||||||
|
st->print("\n\t");
|
||||||
|
st->print("je fast_entry\t");
|
||||||
|
st->print("\n\t");
|
||||||
|
st->print("call #nmethod_entry_barrier_stub\t");
|
||||||
|
st->print("\n\tfast_entry:");
|
||||||
|
}
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -901,7 +910,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||||
int framesize = C->frame_size_in_bytes();
|
int framesize = C->frame_size_in_bytes();
|
||||||
int bangsize = C->bang_size_in_bytes();
|
int bangsize = C->bang_size_in_bytes();
|
||||||
|
|
||||||
__ verified_entry(framesize, C->need_stack_bang(bangsize)?bangsize:0, false);
|
__ verified_entry(framesize, C->need_stack_bang(bangsize)?bangsize:0, false, C->stub_function() != NULL);
|
||||||
|
|
||||||
C->set_frame_complete(cbuf.insts_size());
|
C->set_frame_complete(cbuf.insts_size());
|
||||||
|
|
||||||
|
|
40
src/hotspot/cpu/zero/gc/shared/barrierSetNMethod_zero.cpp
Normal file
40
src/hotspot/cpu/zero/gc/shared/barrierSetNMethod_zero.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BarrierSetNMethod::disarm(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -137,6 +137,12 @@ void AOTLoader::initialize() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
const char pathSep = ';';
|
||||||
|
#else
|
||||||
|
const char pathSep = ':';
|
||||||
|
#endif
|
||||||
|
|
||||||
// Scan the AOTLibrary option.
|
// Scan the AOTLibrary option.
|
||||||
if (AOTLibrary != NULL) {
|
if (AOTLibrary != NULL) {
|
||||||
const int len = (int)strlen(AOTLibrary);
|
const int len = (int)strlen(AOTLibrary);
|
||||||
|
@ -147,7 +153,7 @@ void AOTLoader::initialize() {
|
||||||
char* end = cp + len;
|
char* end = cp + len;
|
||||||
while (cp < end) {
|
while (cp < end) {
|
||||||
const char* name = cp;
|
const char* name = cp;
|
||||||
while ((*cp) != '\0' && (*cp) != '\n' && (*cp) != ',' && (*cp) != ':' && (*cp) != ';') cp++;
|
while ((*cp) != '\0' && (*cp) != '\n' && (*cp) != ',' && (*cp) != pathSep) cp++;
|
||||||
cp[0] = '\0'; // Terminate name
|
cp[0] = '\0'; // Terminate name
|
||||||
cp++;
|
cp++;
|
||||||
load_library(name, true);
|
load_library(name, true);
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
|
|
||||||
ciObject* ciEnv::_null_object_instance;
|
ciObject* ciEnv::_null_object_instance;
|
||||||
|
|
||||||
#define WK_KLASS_DEFN(name, ignore_s, ignore_o) ciInstanceKlass* ciEnv::_##name = NULL;
|
#define WK_KLASS_DEFN(name, ignore_s) ciInstanceKlass* ciEnv::_##name = NULL;
|
||||||
WK_KLASSES_DO(WK_KLASS_DEFN)
|
WK_KLASSES_DO(WK_KLASS_DEFN)
|
||||||
#undef WK_KLASS_DEFN
|
#undef WK_KLASS_DEFN
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ private:
|
||||||
// Distinguished instances of certain ciObjects..
|
// Distinguished instances of certain ciObjects..
|
||||||
static ciObject* _null_object_instance;
|
static ciObject* _null_object_instance;
|
||||||
|
|
||||||
#define WK_KLASS_DECL(name, ignore_s, ignore_o) static ciInstanceKlass* _##name;
|
#define WK_KLASS_DECL(name, ignore_s) static ciInstanceKlass* _##name;
|
||||||
WK_KLASSES_DO(WK_KLASS_DECL)
|
WK_KLASSES_DO(WK_KLASS_DECL)
|
||||||
#undef WK_KLASS_DECL
|
#undef WK_KLASS_DECL
|
||||||
|
|
||||||
|
@ -374,7 +374,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
// Access to certain well known ciObjects.
|
// Access to certain well known ciObjects.
|
||||||
#define WK_KLASS_FUNC(name, ignore_s, ignore_o) \
|
#define WK_KLASS_FUNC(name, ignore_s) \
|
||||||
ciInstanceKlass* name() { \
|
ciInstanceKlass* name() { \
|
||||||
return _##name;\
|
return _##name;\
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,8 +157,8 @@ void ciObjectFactory::init_shared_objects() {
|
||||||
ciEnv::_null_object_instance = new (_arena) ciNullObject();
|
ciEnv::_null_object_instance = new (_arena) ciNullObject();
|
||||||
init_ident_of(ciEnv::_null_object_instance);
|
init_ident_of(ciEnv::_null_object_instance);
|
||||||
|
|
||||||
#define WK_KLASS_DEFN(name, ignore_s, opt) \
|
#define WK_KLASS_DEFN(name, ignore_s) \
|
||||||
if (SystemDictionary::name() != NULL) \
|
if (SystemDictionary::name##_is_loaded()) \
|
||||||
ciEnv::_##name = get_metadata(SystemDictionary::name())->as_instance_klass();
|
ciEnv::_##name = get_metadata(SystemDictionary::name())->as_instance_klass();
|
||||||
|
|
||||||
WK_KLASSES_DO(WK_KLASS_DEFN)
|
WK_KLASSES_DO(WK_KLASS_DEFN)
|
||||||
|
|
|
@ -163,7 +163,7 @@ static const char* get_jimage_version_string() {
|
||||||
static char version_string[10] = "";
|
static char version_string[10] = "";
|
||||||
if (version_string[0] == '\0') {
|
if (version_string[0] == '\0') {
|
||||||
jio_snprintf(version_string, sizeof(version_string), "%d.%d",
|
jio_snprintf(version_string, sizeof(version_string), "%d.%d",
|
||||||
Abstract_VM_Version::vm_major_version(), Abstract_VM_Version::vm_minor_version());
|
VM_Version::vm_major_version(), VM_Version::vm_minor_version());
|
||||||
}
|
}
|
||||||
return (const char*)version_string;
|
return (const char*)version_string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_unsafe_anonymous
|
||||||
// it from being unloaded during parsing of the unsafe anonymous class.
|
// it from being unloaded during parsing of the unsafe anonymous class.
|
||||||
// The null-class-loader should always be kept alive.
|
// The null-class-loader should always be kept alive.
|
||||||
_keep_alive((is_unsafe_anonymous || h_class_loader.is_null()) ? 1 : 0),
|
_keep_alive((is_unsafe_anonymous || h_class_loader.is_null()) ? 1 : 0),
|
||||||
_claimed(0),
|
_claim(0),
|
||||||
_handles(),
|
_handles(),
|
||||||
_klasses(NULL), _packages(NULL), _modules(NULL), _unnamed_module(NULL), _dictionary(NULL),
|
_klasses(NULL), _packages(NULL), _modules(NULL), _unnamed_module(NULL), _dictionary(NULL),
|
||||||
_jmethod_ids(NULL),
|
_jmethod_ids(NULL),
|
||||||
|
@ -268,12 +268,17 @@ bool ClassLoaderData::ChunkedHandleList::owner_of(oop* oop_handle) {
|
||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
bool ClassLoaderData::claim() {
|
bool ClassLoaderData::try_claim(int claim) {
|
||||||
if (_claimed == 1) {
|
for (;;) {
|
||||||
return false;
|
int old_claim = Atomic::load(&_claim);
|
||||||
|
if ((old_claim & claim) == claim) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int new_claim = old_claim | claim;
|
||||||
|
if (Atomic::cmpxchg(new_claim, &_claim, old_claim) == old_claim) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int) Atomic::cmpxchg(1, &_claimed, 0) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsafe anonymous classes have their own ClassLoaderData that is marked to keep alive
|
// Unsafe anonymous classes have their own ClassLoaderData that is marked to keep alive
|
||||||
|
@ -295,8 +300,8 @@ void ClassLoaderData::dec_keep_alive() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassLoaderData::oops_do(OopClosure* f, bool must_claim, bool clear_mod_oops) {
|
void ClassLoaderData::oops_do(OopClosure* f, int claim_value, bool clear_mod_oops) {
|
||||||
if (must_claim && !claim()) {
|
if (claim_value != ClassLoaderData::_claim_none && !try_claim(claim_value)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,9 +128,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||||
// loader. _keep_alive does not need to be volatile or
|
// loader. _keep_alive does not need to be volatile or
|
||||||
// atomic since there is one unique CLD per unsafe anonymous class.
|
// atomic since there is one unique CLD per unsafe anonymous class.
|
||||||
|
|
||||||
volatile int _claimed; // true if claimed, for example during GC traces.
|
volatile int _claim; // non-zero if claimed, for example during GC traces.
|
||||||
// To avoid applying oop closure more than once.
|
// To avoid applying oop closure more than once.
|
||||||
// Has to be an int because we cas it.
|
|
||||||
ChunkedHandleList _handles; // Handles to constant pool arrays, Modules, etc, which
|
ChunkedHandleList _handles; // Handles to constant pool arrays, Modules, etc, which
|
||||||
// have the same life cycle of the corresponding ClassLoader.
|
// have the same life cycle of the corresponding ClassLoader.
|
||||||
|
|
||||||
|
@ -200,11 +199,22 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||||
Dictionary* create_dictionary();
|
Dictionary* create_dictionary();
|
||||||
|
|
||||||
void initialize_name(Handle class_loader);
|
void initialize_name(Handle class_loader);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// GC interface.
|
// GC interface.
|
||||||
void clear_claimed() { _claimed = 0; }
|
|
||||||
bool claimed() const { return _claimed == 1; }
|
// The "claim" is typically used to check if oops_do needs to be applied on
|
||||||
bool claim();
|
// the CLD or not. Most GCs only perform strong marking during the marking phase.
|
||||||
|
enum {
|
||||||
|
_claim_none = 0,
|
||||||
|
_claim_finalizable = 2,
|
||||||
|
_claim_strong = 3
|
||||||
|
};
|
||||||
|
void clear_claim() { _claim = 0; }
|
||||||
|
bool claimed() const { return _claim != 0; }
|
||||||
|
bool try_claim(int claim);
|
||||||
|
int get_claim() const { return _claim; }
|
||||||
|
void set_claim(int claim) { _claim = claim; }
|
||||||
|
|
||||||
// Computes if the CLD is alive or not. This is safe to call in concurrent
|
// Computes if the CLD is alive or not. This is safe to call in concurrent
|
||||||
// contexts.
|
// contexts.
|
||||||
|
@ -264,7 +274,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||||
|
|
||||||
void initialize_holder(Handle holder);
|
void initialize_holder(Handle holder);
|
||||||
|
|
||||||
void oops_do(OopClosure* f, bool must_claim, bool clear_modified_oops = false);
|
void oops_do(OopClosure* f, int claim_value, bool clear_modified_oops = false);
|
||||||
|
|
||||||
void classes_do(KlassClosure* klass_closure);
|
void classes_do(KlassClosure* klass_closure);
|
||||||
Klass* klasses() { return _klasses; }
|
Klass* klasses() { return _klasses; }
|
||||||
|
|
|
@ -48,7 +48,7 @@ volatile size_t ClassLoaderDataGraph::_num_instance_classes = 0;
|
||||||
|
|
||||||
void ClassLoaderDataGraph::clear_claimed_marks() {
|
void ClassLoaderDataGraph::clear_claimed_marks() {
|
||||||
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
|
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
|
||||||
cld->clear_claimed();
|
cld->clear_claim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,14 +231,14 @@ ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_unsafe_anonymo
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
|
void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
|
||||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
|
||||||
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
|
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
|
||||||
cl->do_cld(cld);
|
cl->do_cld(cld);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
|
void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
|
||||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
|
||||||
// Only walk the head until any clds not purged from prior unloading
|
// Only walk the head until any clds not purged from prior unloading
|
||||||
// (CMS doesn't purge right away).
|
// (CMS doesn't purge right away).
|
||||||
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
|
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
|
||||||
|
@ -248,7 +248,7 @@ void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
|
void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
|
||||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
|
||||||
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
|
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
|
||||||
CLDClosure* closure = cld->keep_alive() ? strong : weak;
|
CLDClosure* closure = cld->keep_alive() ? strong : weak;
|
||||||
if (closure != NULL) {
|
if (closure != NULL) {
|
||||||
|
@ -258,7 +258,7 @@ void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) {
|
void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) {
|
||||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
|
||||||
if (ClassUnloading) {
|
if (ClassUnloading) {
|
||||||
roots_cld_do(cl, NULL);
|
roots_cld_do(cl, NULL);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1963,41 +1963,30 @@ void SystemDictionary::initialize(TRAPS) {
|
||||||
|
|
||||||
// Compact table of directions on the initialization of klasses:
|
// Compact table of directions on the initialization of klasses:
|
||||||
static const short wk_init_info[] = {
|
static const short wk_init_info[] = {
|
||||||
#define WK_KLASS_INIT_INFO(name, symbol, option) \
|
#define WK_KLASS_INIT_INFO(name, symbol) \
|
||||||
( ((int)vmSymbols::VM_SYMBOL_ENUM_NAME(symbol) \
|
((short)vmSymbols::VM_SYMBOL_ENUM_NAME(symbol)),
|
||||||
<< SystemDictionary::CEIL_LG_OPTION_LIMIT) \
|
|
||||||
| (int)SystemDictionary::option ),
|
|
||||||
WK_KLASSES_DO(WK_KLASS_INIT_INFO)
|
WK_KLASSES_DO(WK_KLASS_INIT_INFO)
|
||||||
#undef WK_KLASS_INIT_INFO
|
#undef WK_KLASS_INIT_INFO
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
bool SystemDictionary::resolve_wk_klass(WKID id, int init_opt, TRAPS) {
|
bool SystemDictionary::resolve_wk_klass(WKID id, TRAPS) {
|
||||||
assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
|
assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
|
||||||
int info = wk_init_info[id - FIRST_WKID];
|
int sid = wk_init_info[id - FIRST_WKID];
|
||||||
int sid = (info >> CEIL_LG_OPTION_LIMIT);
|
|
||||||
Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
|
Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
|
||||||
InstanceKlass** klassp = &_well_known_klasses[id];
|
InstanceKlass** klassp = &_well_known_klasses[id];
|
||||||
|
|
||||||
bool must_load;
|
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
if (EnableJVMCI) {
|
if (id >= FIRST_JVMCI_WKID) {
|
||||||
// If JVMCI is enabled we require its classes to be found.
|
assert(EnableJVMCI, "resolve JVMCI classes only when EnableJVMCI is true");
|
||||||
must_load = (init_opt < SystemDictionary::Opt) || (init_opt == SystemDictionary::Jvmci);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
must_load = (init_opt < SystemDictionary::Opt);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((*klassp) == NULL) {
|
if ((*klassp) == NULL) {
|
||||||
Klass* k;
|
Klass* k = resolve_or_fail(symbol, true, CHECK_0);
|
||||||
if (must_load) {
|
(*klassp) = InstanceKlass::cast(k);
|
||||||
k = resolve_or_fail(symbol, true, CHECK_0); // load required class
|
|
||||||
} else {
|
|
||||||
k = resolve_or_null(symbol, CHECK_0); // load optional klass
|
|
||||||
}
|
|
||||||
(*klassp) = (k == NULL) ? NULL : InstanceKlass::cast(k);
|
|
||||||
}
|
}
|
||||||
return ((*klassp) != NULL);
|
return ((*klassp) != NULL);
|
||||||
}
|
}
|
||||||
|
@ -2006,11 +1995,7 @@ void SystemDictionary::resolve_wk_klasses_until(WKID limit_id, WKID &start_id, T
|
||||||
assert((int)start_id <= (int)limit_id, "IDs are out of order!");
|
assert((int)start_id <= (int)limit_id, "IDs are out of order!");
|
||||||
for (int id = (int)start_id; id < (int)limit_id; id++) {
|
for (int id = (int)start_id; id < (int)limit_id; id++) {
|
||||||
assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
|
assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
|
||||||
int info = wk_init_info[id - FIRST_WKID];
|
resolve_wk_klass((WKID)id, CHECK);
|
||||||
int sid = (info >> CEIL_LG_OPTION_LIMIT);
|
|
||||||
int opt = (info & right_n_bits(CEIL_LG_OPTION_LIMIT));
|
|
||||||
|
|
||||||
resolve_wk_klass((WKID)id, opt, CHECK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// move the starting value forward to the limit:
|
// move the starting value forward to the limit:
|
||||||
|
|
|
@ -94,127 +94,125 @@ class OopStorage;
|
||||||
#define WK_KLASS_ENUM_NAME(kname) kname##_knum
|
#define WK_KLASS_ENUM_NAME(kname) kname##_knum
|
||||||
|
|
||||||
// Each well-known class has a short klass name (like object_klass),
|
// Each well-known class has a short klass name (like object_klass),
|
||||||
// a vmSymbol name (like java_lang_Object), and a flag word
|
// and a vmSymbol name (like java_lang_Object).
|
||||||
// that makes some minor distinctions, like whether the klass
|
|
||||||
// is preloaded, optional, release-specific, etc.
|
|
||||||
// The order of these definitions is significant; it is the order in which
|
// The order of these definitions is significant; it is the order in which
|
||||||
// preloading is actually performed by resolve_preloaded_classes.
|
// preloading is actually performed by resolve_preloaded_classes.
|
||||||
|
|
||||||
#define WK_KLASSES_DO(do_klass) \
|
#define WK_KLASSES_DO(do_klass) \
|
||||||
/* well-known classes */ \
|
/* well-known classes */ \
|
||||||
do_klass(Object_klass, java_lang_Object, Pre ) \
|
do_klass(Object_klass, java_lang_Object ) \
|
||||||
do_klass(String_klass, java_lang_String, Pre ) \
|
do_klass(String_klass, java_lang_String ) \
|
||||||
do_klass(Class_klass, java_lang_Class, Pre ) \
|
do_klass(Class_klass, java_lang_Class ) \
|
||||||
do_klass(Cloneable_klass, java_lang_Cloneable, Pre ) \
|
do_klass(Cloneable_klass, java_lang_Cloneable ) \
|
||||||
do_klass(ClassLoader_klass, java_lang_ClassLoader, Pre ) \
|
do_klass(ClassLoader_klass, java_lang_ClassLoader ) \
|
||||||
do_klass(Serializable_klass, java_io_Serializable, Pre ) \
|
do_klass(Serializable_klass, java_io_Serializable ) \
|
||||||
do_klass(System_klass, java_lang_System, Pre ) \
|
do_klass(System_klass, java_lang_System ) \
|
||||||
do_klass(Throwable_klass, java_lang_Throwable, Pre ) \
|
do_klass(Throwable_klass, java_lang_Throwable ) \
|
||||||
do_klass(Error_klass, java_lang_Error, Pre ) \
|
do_klass(Error_klass, java_lang_Error ) \
|
||||||
do_klass(ThreadDeath_klass, java_lang_ThreadDeath, Pre ) \
|
do_klass(ThreadDeath_klass, java_lang_ThreadDeath ) \
|
||||||
do_klass(Exception_klass, java_lang_Exception, Pre ) \
|
do_klass(Exception_klass, java_lang_Exception ) \
|
||||||
do_klass(RuntimeException_klass, java_lang_RuntimeException, Pre ) \
|
do_klass(RuntimeException_klass, java_lang_RuntimeException ) \
|
||||||
do_klass(SecurityManager_klass, java_lang_SecurityManager, Pre ) \
|
do_klass(SecurityManager_klass, java_lang_SecurityManager ) \
|
||||||
do_klass(ProtectionDomain_klass, java_security_ProtectionDomain, Pre ) \
|
do_klass(ProtectionDomain_klass, java_security_ProtectionDomain ) \
|
||||||
do_klass(AccessControlContext_klass, java_security_AccessControlContext, Pre ) \
|
do_klass(AccessControlContext_klass, java_security_AccessControlContext ) \
|
||||||
do_klass(SecureClassLoader_klass, java_security_SecureClassLoader, Pre ) \
|
do_klass(SecureClassLoader_klass, java_security_SecureClassLoader ) \
|
||||||
do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre ) \
|
do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException ) \
|
||||||
do_klass(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre ) \
|
do_klass(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError ) \
|
||||||
do_klass(LinkageError_klass, java_lang_LinkageError, Pre ) \
|
do_klass(LinkageError_klass, java_lang_LinkageError ) \
|
||||||
do_klass(ClassCastException_klass, java_lang_ClassCastException, Pre ) \
|
do_klass(ClassCastException_klass, java_lang_ClassCastException ) \
|
||||||
do_klass(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre ) \
|
do_klass(ArrayStoreException_klass, java_lang_ArrayStoreException ) \
|
||||||
do_klass(VirtualMachineError_klass, java_lang_VirtualMachineError, Pre ) \
|
do_klass(VirtualMachineError_klass, java_lang_VirtualMachineError ) \
|
||||||
do_klass(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre ) \
|
do_klass(OutOfMemoryError_klass, java_lang_OutOfMemoryError ) \
|
||||||
do_klass(StackOverflowError_klass, java_lang_StackOverflowError, Pre ) \
|
do_klass(StackOverflowError_klass, java_lang_StackOverflowError ) \
|
||||||
do_klass(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre ) \
|
do_klass(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException ) \
|
||||||
do_klass(Reference_klass, java_lang_ref_Reference, Pre ) \
|
do_klass(Reference_klass, java_lang_ref_Reference ) \
|
||||||
\
|
\
|
||||||
/* Preload ref klasses and set reference types */ \
|
/* Preload ref klasses and set reference types */ \
|
||||||
do_klass(SoftReference_klass, java_lang_ref_SoftReference, Pre ) \
|
do_klass(SoftReference_klass, java_lang_ref_SoftReference ) \
|
||||||
do_klass(WeakReference_klass, java_lang_ref_WeakReference, Pre ) \
|
do_klass(WeakReference_klass, java_lang_ref_WeakReference ) \
|
||||||
do_klass(FinalReference_klass, java_lang_ref_FinalReference, Pre ) \
|
do_klass(FinalReference_klass, java_lang_ref_FinalReference ) \
|
||||||
do_klass(PhantomReference_klass, java_lang_ref_PhantomReference, Pre ) \
|
do_klass(PhantomReference_klass, java_lang_ref_PhantomReference ) \
|
||||||
do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \
|
do_klass(Finalizer_klass, java_lang_ref_Finalizer ) \
|
||||||
\
|
\
|
||||||
do_klass(Thread_klass, java_lang_Thread, Pre ) \
|
do_klass(Thread_klass, java_lang_Thread ) \
|
||||||
do_klass(ThreadGroup_klass, java_lang_ThreadGroup, Pre ) \
|
do_klass(ThreadGroup_klass, java_lang_ThreadGroup ) \
|
||||||
do_klass(Properties_klass, java_util_Properties, Pre ) \
|
do_klass(Properties_klass, java_util_Properties ) \
|
||||||
do_klass(Module_klass, java_lang_Module, Pre ) \
|
do_klass(Module_klass, java_lang_Module ) \
|
||||||
do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre ) \
|
do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject ) \
|
||||||
do_klass(reflect_Field_klass, java_lang_reflect_Field, Pre ) \
|
do_klass(reflect_Field_klass, java_lang_reflect_Field ) \
|
||||||
do_klass(reflect_Parameter_klass, java_lang_reflect_Parameter, Opt ) \
|
do_klass(reflect_Parameter_klass, java_lang_reflect_Parameter ) \
|
||||||
do_klass(reflect_Method_klass, java_lang_reflect_Method, Pre ) \
|
do_klass(reflect_Method_klass, java_lang_reflect_Method ) \
|
||||||
do_klass(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre ) \
|
do_klass(reflect_Constructor_klass, java_lang_reflect_Constructor ) \
|
||||||
\
|
\
|
||||||
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
|
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
|
||||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||||
do_klass(reflect_MagicAccessorImpl_klass, reflect_MagicAccessorImpl, Opt ) \
|
do_klass(reflect_MagicAccessorImpl_klass, reflect_MagicAccessorImpl ) \
|
||||||
do_klass(reflect_MethodAccessorImpl_klass, reflect_MethodAccessorImpl, Pre ) \
|
do_klass(reflect_MethodAccessorImpl_klass, reflect_MethodAccessorImpl ) \
|
||||||
do_klass(reflect_ConstructorAccessorImpl_klass, reflect_ConstructorAccessorImpl, Pre ) \
|
do_klass(reflect_ConstructorAccessorImpl_klass, reflect_ConstructorAccessorImpl ) \
|
||||||
do_klass(reflect_DelegatingClassLoader_klass, reflect_DelegatingClassLoader, Opt ) \
|
do_klass(reflect_DelegatingClassLoader_klass, reflect_DelegatingClassLoader ) \
|
||||||
do_klass(reflect_ConstantPool_klass, reflect_ConstantPool, Opt ) \
|
do_klass(reflect_ConstantPool_klass, reflect_ConstantPool ) \
|
||||||
do_klass(reflect_UnsafeStaticFieldAccessorImpl_klass, reflect_UnsafeStaticFieldAccessorImpl, Opt ) \
|
do_klass(reflect_UnsafeStaticFieldAccessorImpl_klass, reflect_UnsafeStaticFieldAccessorImpl ) \
|
||||||
do_klass(reflect_CallerSensitive_klass, reflect_CallerSensitive, Opt ) \
|
do_klass(reflect_CallerSensitive_klass, reflect_CallerSensitive ) \
|
||||||
\
|
\
|
||||||
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
|
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
|
||||||
do_klass(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle, Opt ) \
|
do_klass(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle ) \
|
||||||
do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre ) \
|
do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle ) \
|
||||||
do_klass(VarHandle_klass, java_lang_invoke_VarHandle, Pre ) \
|
do_klass(VarHandle_klass, java_lang_invoke_VarHandle ) \
|
||||||
do_klass(MemberName_klass, java_lang_invoke_MemberName, Pre ) \
|
do_klass(MemberName_klass, java_lang_invoke_MemberName ) \
|
||||||
do_klass(ResolvedMethodName_klass, java_lang_invoke_ResolvedMethodName, Pre ) \
|
do_klass(ResolvedMethodName_klass, java_lang_invoke_ResolvedMethodName ) \
|
||||||
do_klass(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre ) \
|
do_klass(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives ) \
|
||||||
do_klass(LambdaForm_klass, java_lang_invoke_LambdaForm, Opt ) \
|
do_klass(LambdaForm_klass, java_lang_invoke_LambdaForm ) \
|
||||||
do_klass(MethodType_klass, java_lang_invoke_MethodType, Pre ) \
|
do_klass(MethodType_klass, java_lang_invoke_MethodType ) \
|
||||||
do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre ) \
|
do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError ) \
|
||||||
do_klass(CallSite_klass, java_lang_invoke_CallSite, Pre ) \
|
do_klass(CallSite_klass, java_lang_invoke_CallSite ) \
|
||||||
do_klass(Context_klass, java_lang_invoke_MethodHandleNatives_CallSiteContext, Pre ) \
|
do_klass(Context_klass, java_lang_invoke_MethodHandleNatives_CallSiteContext ) \
|
||||||
do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre ) \
|
do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite ) \
|
||||||
do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre ) \
|
do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite ) \
|
||||||
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre ) \
|
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite ) \
|
||||||
/* Note: MethodHandle must be first, and VolatileCallSite last in group */ \
|
/* Note: MethodHandle must be first, and VolatileCallSite last in group */ \
|
||||||
\
|
\
|
||||||
do_klass(AssertionStatusDirectives_klass, java_lang_AssertionStatusDirectives, Pre ) \
|
do_klass(AssertionStatusDirectives_klass, java_lang_AssertionStatusDirectives ) \
|
||||||
do_klass(StringBuffer_klass, java_lang_StringBuffer, Pre ) \
|
do_klass(StringBuffer_klass, java_lang_StringBuffer ) \
|
||||||
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
|
do_klass(StringBuilder_klass, java_lang_StringBuilder ) \
|
||||||
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe, Pre ) \
|
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe ) \
|
||||||
do_klass(module_Modules_klass, jdk_internal_module_Modules, Pre ) \
|
do_klass(module_Modules_klass, jdk_internal_module_Modules ) \
|
||||||
\
|
\
|
||||||
/* support for CDS */ \
|
/* support for CDS */ \
|
||||||
do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream, Pre ) \
|
do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream ) \
|
||||||
do_klass(URL_klass, java_net_URL, Pre ) \
|
do_klass(URL_klass, java_net_URL ) \
|
||||||
do_klass(Jar_Manifest_klass, java_util_jar_Manifest, Pre ) \
|
do_klass(Jar_Manifest_klass, java_util_jar_Manifest ) \
|
||||||
do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders, Pre ) \
|
do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders ) \
|
||||||
do_klass(jdk_internal_loader_ClassLoaders_AppClassLoader_klass, jdk_internal_loader_ClassLoaders_AppClassLoader, Pre ) \
|
do_klass(jdk_internal_loader_ClassLoaders_AppClassLoader_klass, jdk_internal_loader_ClassLoaders_AppClassLoader) \
|
||||||
do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader, Pre ) \
|
do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader) \
|
||||||
do_klass(CodeSource_klass, java_security_CodeSource, Pre ) \
|
do_klass(CodeSource_klass, java_security_CodeSource ) \
|
||||||
\
|
\
|
||||||
do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \
|
do_klass(StackTraceElement_klass, java_lang_StackTraceElement ) \
|
||||||
\
|
\
|
||||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||||
do_klass(nio_Buffer_klass, java_nio_Buffer, Opt ) \
|
do_klass(nio_Buffer_klass, java_nio_Buffer ) \
|
||||||
\
|
\
|
||||||
/* Stack Walking */ \
|
/* Stack Walking */ \
|
||||||
do_klass(StackWalker_klass, java_lang_StackWalker, Opt ) \
|
do_klass(StackWalker_klass, java_lang_StackWalker ) \
|
||||||
do_klass(AbstractStackWalker_klass, java_lang_StackStreamFactory_AbstractStackWalker, Opt ) \
|
do_klass(AbstractStackWalker_klass, java_lang_StackStreamFactory_AbstractStackWalker ) \
|
||||||
do_klass(StackFrameInfo_klass, java_lang_StackFrameInfo, Opt ) \
|
do_klass(StackFrameInfo_klass, java_lang_StackFrameInfo ) \
|
||||||
do_klass(LiveStackFrameInfo_klass, java_lang_LiveStackFrameInfo, Opt ) \
|
do_klass(LiveStackFrameInfo_klass, java_lang_LiveStackFrameInfo ) \
|
||||||
\
|
\
|
||||||
/* support for stack dump lock analysis */ \
|
/* support for stack dump lock analysis */ \
|
||||||
do_klass(java_util_concurrent_locks_AbstractOwnableSynchronizer_klass, java_util_concurrent_locks_AbstractOwnableSynchronizer, Pre ) \
|
do_klass(java_util_concurrent_locks_AbstractOwnableSynchronizer_klass, java_util_concurrent_locks_AbstractOwnableSynchronizer) \
|
||||||
\
|
\
|
||||||
/* Preload boxing klasses */ \
|
/* Preload boxing klasses */ \
|
||||||
do_klass(Boolean_klass, java_lang_Boolean, Pre ) \
|
do_klass(Boolean_klass, java_lang_Boolean ) \
|
||||||
do_klass(Character_klass, java_lang_Character, Pre ) \
|
do_klass(Character_klass, java_lang_Character ) \
|
||||||
do_klass(Float_klass, java_lang_Float, Pre ) \
|
do_klass(Float_klass, java_lang_Float ) \
|
||||||
do_klass(Double_klass, java_lang_Double, Pre ) \
|
do_klass(Double_klass, java_lang_Double ) \
|
||||||
do_klass(Byte_klass, java_lang_Byte, Pre ) \
|
do_klass(Byte_klass, java_lang_Byte ) \
|
||||||
do_klass(Short_klass, java_lang_Short, Pre ) \
|
do_klass(Short_klass, java_lang_Short ) \
|
||||||
do_klass(Integer_klass, java_lang_Integer, Pre ) \
|
do_klass(Integer_klass, java_lang_Integer ) \
|
||||||
do_klass(Long_klass, java_lang_Long, Pre ) \
|
do_klass(Long_klass, java_lang_Long ) \
|
||||||
\
|
\
|
||||||
/* JVMCI classes. These are loaded on-demand. */ \
|
/* JVMCI classes. These are loaded on-demand. */ \
|
||||||
JVMCI_WK_KLASSES_DO(do_klass) \
|
JVMCI_WK_KLASSES_DO(do_klass) \
|
||||||
\
|
\
|
||||||
/*end*/
|
/*end*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -226,7 +224,7 @@ class SystemDictionary : AllStatic {
|
||||||
enum WKID {
|
enum WKID {
|
||||||
NO_WKID = 0,
|
NO_WKID = 0,
|
||||||
|
|
||||||
#define WK_KLASS_ENUM(name, symbol, ignore_o) WK_KLASS_ENUM_NAME(name), WK_KLASS_ENUM_NAME(symbol) = WK_KLASS_ENUM_NAME(name),
|
#define WK_KLASS_ENUM(name, symbol) WK_KLASS_ENUM_NAME(name), WK_KLASS_ENUM_NAME(symbol) = WK_KLASS_ENUM_NAME(name),
|
||||||
WK_KLASSES_DO(WK_KLASS_ENUM)
|
WK_KLASSES_DO(WK_KLASS_ENUM)
|
||||||
#undef WK_KLASS_ENUM
|
#undef WK_KLASS_ENUM
|
||||||
|
|
||||||
|
@ -240,21 +238,6 @@ class SystemDictionary : AllStatic {
|
||||||
FIRST_WKID = NO_WKID + 1
|
FIRST_WKID = NO_WKID + 1
|
||||||
};
|
};
|
||||||
|
|
||||||
enum InitOption {
|
|
||||||
Pre, // preloaded; error if not present
|
|
||||||
|
|
||||||
// Order is significant. Options before this point require resolve_or_fail.
|
|
||||||
// Options after this point will use resolve_or_null instead.
|
|
||||||
|
|
||||||
Opt, // preload tried; NULL if not present
|
|
||||||
#if INCLUDE_JVMCI
|
|
||||||
Jvmci, // preload tried; error if not present if JVMCI enabled
|
|
||||||
#endif
|
|
||||||
OPTION_LIMIT,
|
|
||||||
CEIL_LG_OPTION_LIMIT = 2 // OPTION_LIMIT <= (1<<CEIL_LG_OPTION_LIMIT)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Returns a class with a given class name and class loader. Loads the
|
// Returns a class with a given class name and class loader. Loads the
|
||||||
// class if needed. If not found a NoClassDefFoundError or a
|
// class if needed. If not found a NoClassDefFoundError or a
|
||||||
// ClassNotFoundException is thrown, depending on the value on the
|
// ClassNotFoundException is thrown, depending on the value on the
|
||||||
|
@ -414,12 +397,7 @@ public:
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
static InstanceKlass* check_klass_Pre(InstanceKlass* k) { return check_klass(k); }
|
static bool resolve_wk_klass(WKID id, TRAPS);
|
||||||
static InstanceKlass* check_klass_Opt(InstanceKlass* k) { return k; }
|
|
||||||
|
|
||||||
JVMCI_ONLY(static InstanceKlass* check_klass_Jvmci(InstanceKlass* k) { return k; })
|
|
||||||
|
|
||||||
static bool resolve_wk_klass(WKID id, int init_opt, TRAPS);
|
|
||||||
static void resolve_wk_klasses_until(WKID limit_id, WKID &start_id, TRAPS);
|
static void resolve_wk_klasses_until(WKID limit_id, WKID &start_id, TRAPS);
|
||||||
static void resolve_wk_klasses_through(WKID end_id, WKID &start_id, TRAPS) {
|
static void resolve_wk_klasses_through(WKID end_id, WKID &start_id, TRAPS) {
|
||||||
int limit = (int)end_id + 1;
|
int limit = (int)end_id + 1;
|
||||||
|
@ -427,10 +405,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#define WK_KLASS_DECLARE(name, symbol, option) \
|
#define WK_KLASS_DECLARE(name, symbol) \
|
||||||
static InstanceKlass* name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \
|
static InstanceKlass* name() { return check_klass(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \
|
||||||
static InstanceKlass** name##_addr() { \
|
static InstanceKlass** name##_addr() { \
|
||||||
return &SystemDictionary::_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \
|
return &_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \
|
||||||
|
} \
|
||||||
|
static bool name##_is_loaded() { \
|
||||||
|
return _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)] != NULL; \
|
||||||
}
|
}
|
||||||
WK_KLASSES_DO(WK_KLASS_DECLARE);
|
WK_KLASSES_DO(WK_KLASS_DECLARE);
|
||||||
#undef WK_KLASS_DECLARE
|
#undef WK_KLASS_DECLARE
|
||||||
|
|
|
@ -172,7 +172,11 @@ void VerificationType::print_on(outputStream* st) const {
|
||||||
} else if (is_uninitialized()) {
|
} else if (is_uninitialized()) {
|
||||||
st->print("uninitialized %d", bci());
|
st->print("uninitialized %d", bci());
|
||||||
} else {
|
} else {
|
||||||
name()->print_value_on(st);
|
if (name() != NULL) {
|
||||||
|
name()->print_value_on(st);
|
||||||
|
} else {
|
||||||
|
st->print_cr("NULL");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,6 +186,7 @@ public:
|
||||||
bool contains(address addr) const { return content_begin() <= addr && addr < content_end(); }
|
bool contains(address addr) const { return content_begin() <= addr && addr < content_end(); }
|
||||||
bool is_frame_complete_at(address addr) const { return _frame_complete_offset != CodeOffsets::frame_never_safe &&
|
bool is_frame_complete_at(address addr) const { return _frame_complete_offset != CodeOffsets::frame_never_safe &&
|
||||||
code_contains(addr) && addr >= code_begin() + _frame_complete_offset; }
|
code_contains(addr) && addr >= code_begin() + _frame_complete_offset; }
|
||||||
|
int frame_complete_offset() const { return _frame_complete_offset; }
|
||||||
|
|
||||||
// CodeCache support: really only used by the nmethods, but in order to get
|
// CodeCache support: really only used by the nmethods, but in order to get
|
||||||
// asserts and certain bookkeeping to work in the CodeCache they are defined
|
// asserts and certain bookkeeping to work in the CodeCache they are defined
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
|
* Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -45,7 +46,7 @@ void CMSArguments::set_parnew_gc_flags() {
|
||||||
assert(UseConcMarkSweepGC, "CMS is expected to be on here");
|
assert(UseConcMarkSweepGC, "CMS is expected to be on here");
|
||||||
|
|
||||||
if (FLAG_IS_DEFAULT(ParallelGCThreads)) {
|
if (FLAG_IS_DEFAULT(ParallelGCThreads)) {
|
||||||
FLAG_SET_DEFAULT(ParallelGCThreads, Abstract_VM_Version::parallel_worker_threads());
|
FLAG_SET_DEFAULT(ParallelGCThreads, VM_Version::parallel_worker_threads());
|
||||||
assert(ParallelGCThreads > 0, "We should always have at least one thread by default");
|
assert(ParallelGCThreads > 0, "We should always have at least one thread by default");
|
||||||
} else if (ParallelGCThreads == 0) {
|
} else if (ParallelGCThreads == 0) {
|
||||||
jio_fprintf(defaultStream::error_stream(),
|
jio_fprintf(defaultStream::error_stream(),
|
||||||
|
|
|
@ -41,8 +41,7 @@ inline void MetadataVisitingOopsInGenClosure::do_klass(Klass* k) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void MetadataVisitingOopsInGenClosure::do_cld(ClassLoaderData* cld) {
|
inline void MetadataVisitingOopsInGenClosure::do_cld(ClassLoaderData* cld) {
|
||||||
bool claim = true; // Must claim the class loader data before processing.
|
cld->oops_do(this, ClassLoaderData::_claim_strong);
|
||||||
cld->oops_do(this, claim);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode the oop and call do_oop on it.
|
// Decode the oop and call do_oop on it.
|
||||||
|
|
|
@ -2398,7 +2398,7 @@ class VerifyCLDOopsCLDClosure : public CLDClosure {
|
||||||
public:
|
public:
|
||||||
VerifyCLDOopsCLDClosure(CMSBitMap* bitmap) : _oop_closure(bitmap) {}
|
VerifyCLDOopsCLDClosure(CMSBitMap* bitmap) : _oop_closure(bitmap) {}
|
||||||
void do_cld(ClassLoaderData* cld) {
|
void do_cld(ClassLoaderData* cld) {
|
||||||
cld->oops_do(&_oop_closure, false, false);
|
cld->oops_do(&_oop_closure, ClassLoaderData::_claim_none, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2413,7 +2413,7 @@ void CMSCollector::verify_after_remark_work_2() {
|
||||||
// Mark from roots one level into CMS
|
// Mark from roots one level into CMS
|
||||||
MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(),
|
MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(),
|
||||||
markBitMap());
|
markBitMap());
|
||||||
CLDToOopClosure cld_closure(¬Older, true);
|
CLDToOopClosure cld_closure(¬Older, ClassLoaderData::_claim_strong);
|
||||||
|
|
||||||
heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||||
|
|
||||||
|
@ -2886,7 +2886,7 @@ void CMSCollector::checkpointRootsInitialWork() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The serial version.
|
// The serial version.
|
||||||
CLDToOopClosure cld_closure(¬Older, true);
|
CLDToOopClosure cld_closure(¬Older, ClassLoaderData::_claim_strong);
|
||||||
heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||||
|
|
||||||
StrongRootsScope srs(1);
|
StrongRootsScope srs(1);
|
||||||
|
@ -4269,7 +4269,7 @@ void CMSParInitialMarkTask::work(uint worker_id) {
|
||||||
_timer.reset();
|
_timer.reset();
|
||||||
_timer.start();
|
_timer.start();
|
||||||
|
|
||||||
CLDToOopClosure cld_closure(&par_mri_cl, true);
|
CLDToOopClosure cld_closure(&par_mri_cl, ClassLoaderData::_claim_strong);
|
||||||
|
|
||||||
heap->cms_process_roots(_strong_roots_scope,
|
heap->cms_process_roots(_strong_roots_scope,
|
||||||
false, // yg was scanned above
|
false, // yg was scanned above
|
||||||
|
@ -4331,7 +4331,7 @@ class CMSParRemarkTask: public CMSParMarkTask {
|
||||||
class RemarkCLDClosure : public CLDClosure {
|
class RemarkCLDClosure : public CLDClosure {
|
||||||
CLDToOopClosure _cm_closure;
|
CLDToOopClosure _cm_closure;
|
||||||
public:
|
public:
|
||||||
RemarkCLDClosure(OopClosure* oop_closure) : _cm_closure(oop_closure) {}
|
RemarkCLDClosure(OopClosure* oop_closure) : _cm_closure(oop_closure, ClassLoaderData::_claim_strong) {}
|
||||||
void do_cld(ClassLoaderData* cld) {
|
void do_cld(ClassLoaderData* cld) {
|
||||||
// Check if we have modified any oops in the CLD during the concurrent marking.
|
// Check if we have modified any oops in the CLD during the concurrent marking.
|
||||||
if (cld->has_accumulated_modified_oops()) {
|
if (cld->has_accumulated_modified_oops()) {
|
||||||
|
|
|
@ -40,6 +40,7 @@ EpsilonBarrierSet::EpsilonBarrierSet() : BarrierSet(
|
||||||
make_barrier_set_assembler<BarrierSetAssembler>(),
|
make_barrier_set_assembler<BarrierSetAssembler>(),
|
||||||
make_barrier_set_c1<BarrierSetC1>(),
|
make_barrier_set_c1<BarrierSetC1>(),
|
||||||
make_barrier_set_c2<BarrierSetC2>(),
|
make_barrier_set_c2<BarrierSetC2>(),
|
||||||
|
NULL /* barrier_set_nmethod */,
|
||||||
BarrierSet::FakeRtti(BarrierSet::EpsilonBarrierSet)) {};
|
BarrierSet::FakeRtti(BarrierSet::EpsilonBarrierSet)) {};
|
||||||
|
|
||||||
void EpsilonBarrierSet::on_thread_create(Thread *thread) {
|
void EpsilonBarrierSet::on_thread_create(Thread *thread) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ jint EpsilonHeap::initialize() {
|
||||||
_space->initialize(committed_region, /* clear_space = */ true, /* mangle_space = */ true);
|
_space->initialize(committed_region, /* clear_space = */ true, /* mangle_space = */ true);
|
||||||
|
|
||||||
// Precompute hot fields
|
// Precompute hot fields
|
||||||
_max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), EpsilonMaxTLABSize / HeapWordSize);
|
_max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), align_object_size(EpsilonMaxTLABSize / HeapWordSize));
|
||||||
_step_counter_update = MIN2<size_t>(max_byte_size / 16, EpsilonUpdateCountersStep);
|
_step_counter_update = MIN2<size_t>(max_byte_size / 16, EpsilonUpdateCountersStep);
|
||||||
_step_heap_print = (EpsilonPrintHeapSteps == 0) ? SIZE_MAX : (max_byte_size / EpsilonPrintHeapSteps);
|
_step_heap_print = (EpsilonPrintHeapSteps == 0) ? SIZE_MAX : (max_byte_size / EpsilonPrintHeapSteps);
|
||||||
_decay_time_ns = (int64_t) EpsilonTLABDecayTime * NANOSECS_PER_MILLISEC;
|
_decay_time_ns = (int64_t) EpsilonTLABDecayTime * NANOSECS_PER_MILLISEC;
|
||||||
|
@ -217,6 +217,16 @@ HeapWord* EpsilonHeap::allocate_new_tlab(size_t min_size,
|
||||||
// Always honor alignment
|
// Always honor alignment
|
||||||
size = align_up(size, MinObjAlignment);
|
size = align_up(size, MinObjAlignment);
|
||||||
|
|
||||||
|
// Check that adjustments did not break local and global invariants
|
||||||
|
assert(is_object_aligned(size),
|
||||||
|
"Size honors object alignment: " SIZE_FORMAT, size);
|
||||||
|
assert(min_size <= size,
|
||||||
|
"Size honors min size: " SIZE_FORMAT " <= " SIZE_FORMAT, min_size, size);
|
||||||
|
assert(size <= _max_tlab_size,
|
||||||
|
"Size honors max size: " SIZE_FORMAT " <= " SIZE_FORMAT, size, _max_tlab_size);
|
||||||
|
assert(size <= CollectedHeap::max_tlab_size(),
|
||||||
|
"Size honors global max size: " SIZE_FORMAT " <= " SIZE_FORMAT, size, CollectedHeap::max_tlab_size());
|
||||||
|
|
||||||
if (log_is_enabled(Trace, gc)) {
|
if (log_is_enabled(Trace, gc)) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
log_trace(gc)("TLAB size for \"%s\" (Requested: " SIZE_FORMAT "K, Min: " SIZE_FORMAT
|
log_trace(gc)("TLAB size for \"%s\" (Requested: " SIZE_FORMAT "K, Min: " SIZE_FORMAT
|
||||||
|
|
|
@ -75,7 +75,7 @@ void G1Arguments::parse_verification_type(const char* type) {
|
||||||
void G1Arguments::initialize() {
|
void G1Arguments::initialize() {
|
||||||
GCArguments::initialize();
|
GCArguments::initialize();
|
||||||
assert(UseG1GC, "Error");
|
assert(UseG1GC, "Error");
|
||||||
FLAG_SET_DEFAULT(ParallelGCThreads, Abstract_VM_Version::parallel_worker_threads());
|
FLAG_SET_DEFAULT(ParallelGCThreads, VM_Version::parallel_worker_threads());
|
||||||
if (ParallelGCThreads == 0) {
|
if (ParallelGCThreads == 0) {
|
||||||
assert(!FLAG_IS_DEFAULT(ParallelGCThreads), "The default value for ParallelGCThreads should not be 0.");
|
assert(!FLAG_IS_DEFAULT(ParallelGCThreads), "The default value for ParallelGCThreads should not be 0.");
|
||||||
vm_exit_during_initialization("The flag -XX:+UseG1GC can not be combined with -XX:ParallelGCThreads=0", NULL);
|
vm_exit_during_initialization("The flag -XX:+UseG1GC can not be combined with -XX:ParallelGCThreads=0", NULL);
|
||||||
|
|
|
@ -108,7 +108,7 @@ void G1FullGCAdjustTask::work(uint worker_id) {
|
||||||
AlwaysTrueClosure always_alive;
|
AlwaysTrueClosure always_alive;
|
||||||
_weak_proc_task.work(worker_id, &always_alive, &_adjust);
|
_weak_proc_task.work(worker_id, &always_alive, &_adjust);
|
||||||
|
|
||||||
CLDToOopClosure adjust_cld(&_adjust);
|
CLDToOopClosure adjust_cld(&_adjust, ClassLoaderData::_claim_strong);
|
||||||
CodeBlobToOopClosure adjust_code(&_adjust, CodeBlobToOopClosure::FixRelocations);
|
CodeBlobToOopClosure adjust_code(&_adjust, CodeBlobToOopClosure::FixRelocations);
|
||||||
_root_processor.process_all_roots(
|
_root_processor.process_all_roots(
|
||||||
&_adjust,
|
&_adjust,
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoaderData.hpp"
|
||||||
#include "gc/g1/g1FullGCMarker.inline.hpp"
|
#include "gc/g1/g1FullGCMarker.inline.hpp"
|
||||||
#include "gc/shared/referenceProcessor.hpp"
|
#include "gc/shared/referenceProcessor.hpp"
|
||||||
#include "memory/iterator.inline.hpp"
|
#include "memory/iterator.inline.hpp"
|
||||||
|
@ -36,7 +37,7 @@ G1FullGCMarker::G1FullGCMarker(uint worker_id, PreservedMarks* preserved_stack,
|
||||||
_mark_closure(worker_id, this, G1CollectedHeap::heap()->ref_processor_stw()),
|
_mark_closure(worker_id, this, G1CollectedHeap::heap()->ref_processor_stw()),
|
||||||
_verify_closure(VerifyOption_G1UseFullMarking),
|
_verify_closure(VerifyOption_G1UseFullMarking),
|
||||||
_stack_closure(this),
|
_stack_closure(this),
|
||||||
_cld_closure(mark_closure()) {
|
_cld_closure(mark_closure(), ClassLoaderData::_claim_strong) {
|
||||||
_oop_stack.initialize();
|
_oop_stack.initialize();
|
||||||
_objarray_stack.initialize();
|
_objarray_stack.initialize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#ifndef SHARE_VM_GC_G1_G1FULLGCOOPCLOSURES_INLINE_HPP
|
#ifndef SHARE_VM_GC_G1_G1FULLGCOOPCLOSURES_INLINE_HPP
|
||||||
#define SHARE_VM_GC_G1_G1FULLGCOOPCLOSURES_INLINE_HPP
|
#define SHARE_VM_GC_G1_G1FULLGCOOPCLOSURES_INLINE_HPP
|
||||||
|
|
||||||
#include "gc/g1/g1Allocator.hpp"
|
#include "gc/g1/g1Allocator.inline.hpp"
|
||||||
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
|
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
|
||||||
#include "gc/g1/g1FullGCMarker.inline.hpp"
|
#include "gc/g1/g1FullGCMarker.inline.hpp"
|
||||||
#include "gc/g1/g1FullGCOopClosures.hpp"
|
#include "gc/g1/g1FullGCOopClosures.hpp"
|
||||||
|
|
|
@ -24,14 +24,12 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "gc/g1/g1Allocator.inline.hpp"
|
#include "gc/g1/g1Allocator.inline.hpp"
|
||||||
#include "gc/g1/g1CollectedHeap.hpp"
|
|
||||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||||
#include "gc/g1/g1ConcurrentMarkThread.hpp"
|
#include "gc/g1/g1ConcurrentMarkThread.hpp"
|
||||||
#include "gc/g1/g1HeapVerifier.hpp"
|
#include "gc/g1/g1HeapVerifier.hpp"
|
||||||
#include "gc/g1/g1Policy.hpp"
|
#include "gc/g1/g1Policy.hpp"
|
||||||
#include "gc/g1/g1RemSet.hpp"
|
#include "gc/g1/g1RemSet.hpp"
|
||||||
#include "gc/g1/g1RootProcessor.hpp"
|
#include "gc/g1/g1RootProcessor.hpp"
|
||||||
#include "gc/g1/heapRegion.hpp"
|
|
||||||
#include "gc/g1/heapRegion.inline.hpp"
|
#include "gc/g1/heapRegion.inline.hpp"
|
||||||
#include "gc/g1/heapRegionRemSet.hpp"
|
#include "gc/g1/heapRegionRemSet.hpp"
|
||||||
#include "gc/g1/g1StringDedup.hpp"
|
#include "gc/g1/g1StringDedup.hpp"
|
||||||
|
@ -170,10 +168,10 @@ class VerifyCLDClosure: public CLDClosure {
|
||||||
public:
|
public:
|
||||||
VerifyCLDClosure(G1CollectedHeap* g1h, OopClosure* cl) : _young_ref_counter_closure(g1h), _oop_closure(cl) {}
|
VerifyCLDClosure(G1CollectedHeap* g1h, OopClosure* cl) : _young_ref_counter_closure(g1h), _oop_closure(cl) {}
|
||||||
void do_cld(ClassLoaderData* cld) {
|
void do_cld(ClassLoaderData* cld) {
|
||||||
cld->oops_do(_oop_closure, false);
|
cld->oops_do(_oop_closure, ClassLoaderData::_claim_none);
|
||||||
|
|
||||||
_young_ref_counter_closure.reset_count();
|
_young_ref_counter_closure.reset_count();
|
||||||
cld->oops_do(&_young_ref_counter_closure, false);
|
cld->oops_do(&_young_ref_counter_closure, ClassLoaderData::_claim_none);
|
||||||
if (_young_ref_counter_closure.count() > 0) {
|
if (_young_ref_counter_closure.count() > 0) {
|
||||||
guarantee(cld->has_modified_oops(), "CLD " PTR_FORMAT ", has young %d refs but is not dirty.", p2i(cld), _young_ref_counter_closure.count());
|
guarantee(cld->has_modified_oops(), "CLD " PTR_FORMAT ", has young %d refs but is not dirty.", p2i(cld), _young_ref_counter_closure.count());
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ void G1CLDScanClosure::do_cld(ClassLoaderData* cld) {
|
||||||
|
|
||||||
// Clean the cld since we're going to scavenge all the metadata.
|
// Clean the cld since we're going to scavenge all the metadata.
|
||||||
// Clear modified oops only if this cld is claimed.
|
// Clear modified oops only if this cld is claimed.
|
||||||
cld->oops_do(_closure, _must_claim, /*clear_modified_oops*/true);
|
cld->oops_do(_closure, _claim, /*clear_modified_oops*/true);
|
||||||
|
|
||||||
_closure->set_scanned_cld(NULL);
|
_closure->set_scanned_cld(NULL);
|
||||||
|
|
||||||
|
|
|
@ -160,12 +160,12 @@ public:
|
||||||
class G1CLDScanClosure : public CLDClosure {
|
class G1CLDScanClosure : public CLDClosure {
|
||||||
G1ParCopyHelper* _closure;
|
G1ParCopyHelper* _closure;
|
||||||
bool _process_only_dirty;
|
bool _process_only_dirty;
|
||||||
bool _must_claim;
|
int _claim;
|
||||||
int _count;
|
int _count;
|
||||||
public:
|
public:
|
||||||
G1CLDScanClosure(G1ParCopyHelper* closure,
|
G1CLDScanClosure(G1ParCopyHelper* closure,
|
||||||
bool process_only_dirty, bool must_claim)
|
bool process_only_dirty, int claim_value)
|
||||||
: _closure(closure), _process_only_dirty(process_only_dirty), _must_claim(must_claim), _count(0) {}
|
: _closure(closure), _process_only_dirty(process_only_dirty), _claim(claim_value), _count(0) {}
|
||||||
void do_cld(ClassLoaderData* cld);
|
void do_cld(ClassLoaderData* cld);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -201,11 +201,11 @@ void G1ParScanThreadState::report_promotion_event(InCSetState const dest_state,
|
||||||
HeapWord * const obj_ptr) const {
|
HeapWord * const obj_ptr) const {
|
||||||
PLAB* alloc_buf = _plab_allocator->alloc_buffer(dest_state);
|
PLAB* alloc_buf = _plab_allocator->alloc_buffer(dest_state);
|
||||||
if (alloc_buf->contains(obj_ptr)) {
|
if (alloc_buf->contains(obj_ptr)) {
|
||||||
_g1h->_gc_tracer_stw->report_promotion_in_new_plab_event(old->klass(), word_sz, age,
|
_g1h->_gc_tracer_stw->report_promotion_in_new_plab_event(old->klass(), word_sz * HeapWordSize, age,
|
||||||
dest_state.value() == InCSetState::Old,
|
dest_state.value() == InCSetState::Old,
|
||||||
alloc_buf->word_sz());
|
alloc_buf->word_sz());
|
||||||
} else {
|
} else {
|
||||||
_g1h->_gc_tracer_stw->report_promotion_outside_plab_event(old->klass(), word_sz, age,
|
_g1h->_gc_tracer_stw->report_promotion_outside_plab_event(old->klass(), word_sz * HeapWordSize, age,
|
||||||
dest_state.value() == InCSetState::Old);
|
dest_state.value() == InCSetState::Old);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
G1EvacuationClosures(G1CollectedHeap* g1h,
|
G1EvacuationClosures(G1CollectedHeap* g1h,
|
||||||
G1ParScanThreadState* pss,
|
G1ParScanThreadState* pss,
|
||||||
bool in_young_gc) :
|
bool in_young_gc) :
|
||||||
_closures(g1h, pss, in_young_gc, /* must_claim_cld */ false) {}
|
_closures(g1h, pss, in_young_gc, /* cld_claim */ ClassLoaderData::_claim_none) {}
|
||||||
|
|
||||||
OopClosure* weak_oops() { return &_closures._oops; }
|
OopClosure* weak_oops() { return &_closures._oops; }
|
||||||
OopClosure* strong_oops() { return &_closures._oops; }
|
OopClosure* strong_oops() { return &_closures._oops; }
|
||||||
|
@ -73,8 +73,8 @@ class G1InitialMarkClosures : public G1EvacuationRootClosures {
|
||||||
public:
|
public:
|
||||||
G1InitialMarkClosures(G1CollectedHeap* g1h,
|
G1InitialMarkClosures(G1CollectedHeap* g1h,
|
||||||
G1ParScanThreadState* pss) :
|
G1ParScanThreadState* pss) :
|
||||||
_strong(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true),
|
_strong(g1h, pss, /* process_only_dirty_klasses */ false, /* cld_claim */ ClassLoaderData::_claim_strong),
|
||||||
_weak(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true) {}
|
_weak(g1h, pss, /* process_only_dirty_klasses */ false, /* cld_claim */ ClassLoaderData::_claim_strong) {}
|
||||||
|
|
||||||
OopClosure* weak_oops() { return &_weak._oops; }
|
OopClosure* weak_oops() { return &_weak._oops; }
|
||||||
OopClosure* strong_oops() { return &_strong._oops; }
|
OopClosure* strong_oops() { return &_strong._oops; }
|
||||||
|
|
|
@ -39,9 +39,9 @@ public:
|
||||||
G1CLDScanClosure _clds;
|
G1CLDScanClosure _clds;
|
||||||
G1CodeBlobClosure _codeblobs;
|
G1CodeBlobClosure _codeblobs;
|
||||||
|
|
||||||
G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty, bool must_claim_cld) :
|
G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty, int cld_claim) :
|
||||||
_oops(g1h, pss),
|
_oops(g1h, pss),
|
||||||
_oops_in_cld(g1h, pss),
|
_oops_in_cld(g1h, pss),
|
||||||
_clds(&_oops_in_cld, process_only_dirty, must_claim_cld),
|
_clds(&_oops_in_cld, process_only_dirty, cld_claim),
|
||||||
_codeblobs(&_oops) {}
|
_codeblobs(&_oops) {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
|
* Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -50,7 +51,7 @@ void ParallelArguments::initialize() {
|
||||||
// If no heap maximum was requested explicitly, use some reasonable fraction
|
// If no heap maximum was requested explicitly, use some reasonable fraction
|
||||||
// of the physical memory, up to a maximum of 1GB.
|
// of the physical memory, up to a maximum of 1GB.
|
||||||
FLAG_SET_DEFAULT(ParallelGCThreads,
|
FLAG_SET_DEFAULT(ParallelGCThreads,
|
||||||
Abstract_VM_Version::parallel_worker_threads());
|
VM_Version::parallel_worker_threads());
|
||||||
if (ParallelGCThreads == 0) {
|
if (ParallelGCThreads == 0) {
|
||||||
jio_fprintf(defaultStream::error_stream(),
|
jio_fprintf(defaultStream::error_stream(),
|
||||||
"The Parallel GC can not be combined with -XX:ParallelGCThreads=0\n");
|
"The Parallel GC can not be combined with -XX:ParallelGCThreads=0\n");
|
||||||
|
|
|
@ -110,7 +110,7 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case class_loader_data: {
|
case class_loader_data: {
|
||||||
CLDToOopClosure cld_closure(&mark_and_push_closure);
|
CLDToOopClosure cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_strong);
|
||||||
ClassLoaderDataGraph::always_strong_cld_do(&cld_closure);
|
ClassLoaderDataGraph::always_strong_cld_do(&cld_closure);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -2213,7 +2213,7 @@ void PSParallelCompact::adjust_roots(ParCompactionManager* cm) {
|
||||||
Management::oops_do(&oop_closure);
|
Management::oops_do(&oop_closure);
|
||||||
JvmtiExport::oops_do(&oop_closure);
|
JvmtiExport::oops_do(&oop_closure);
|
||||||
SystemDictionary::oops_do(&oop_closure);
|
SystemDictionary::oops_do(&oop_closure);
|
||||||
CLDToOopClosure cld_closure(&oop_closure);
|
CLDToOopClosure cld_closure(&oop_closure, ClassLoaderData::_claim_strong);
|
||||||
ClassLoaderDataGraph::cld_do(&cld_closure);
|
ClassLoaderDataGraph::cld_do(&cld_closure);
|
||||||
|
|
||||||
// Now adjust pointers in remaining weak roots. (All of which should
|
// Now adjust pointers in remaining weak roots. (All of which should
|
||||||
|
|
|
@ -137,7 +137,7 @@ void CLDScanClosure::do_cld(ClassLoaderData* cld) {
|
||||||
_scavenge_closure->set_scanned_cld(cld);
|
_scavenge_closure->set_scanned_cld(cld);
|
||||||
|
|
||||||
// Clean the cld since we're going to scavenge all the metadata.
|
// Clean the cld since we're going to scavenge all the metadata.
|
||||||
cld->oops_do(_scavenge_closure, false, /*clear_modified_oops*/true);
|
cld->oops_do(_scavenge_closure, ClassLoaderData::_claim_none, /*clear_modified_oops*/true);
|
||||||
|
|
||||||
_scavenge_closure->set_scanned_cld(NULL);
|
_scavenge_closure->set_scanned_cld(NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,9 +58,9 @@ SerialOldTracer* MarkSweep::_gc_tracer = NULL;
|
||||||
|
|
||||||
MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
|
MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
|
||||||
|
|
||||||
MarkAndPushClosure MarkSweep::mark_and_push_closure;
|
MarkAndPushClosure MarkSweep::mark_and_push_closure;
|
||||||
CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure);
|
CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_strong);
|
||||||
CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure);
|
CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure, ClassLoaderData::_claim_strong);
|
||||||
|
|
||||||
template <class T> inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) {
|
template <class T> inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) {
|
||||||
mark_and_push(p);
|
mark_and_push(p);
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
class BarrierSetAssembler;
|
class BarrierSetAssembler;
|
||||||
class BarrierSetC1;
|
class BarrierSetC1;
|
||||||
class BarrierSetC2;
|
class BarrierSetC2;
|
||||||
|
class BarrierSetNMethod;
|
||||||
class JavaThread;
|
class JavaThread;
|
||||||
|
|
||||||
// This class provides the interface between a barrier implementation and
|
// This class provides the interface between a barrier implementation and
|
||||||
|
@ -72,6 +73,7 @@ private:
|
||||||
BarrierSetAssembler* _barrier_set_assembler;
|
BarrierSetAssembler* _barrier_set_assembler;
|
||||||
BarrierSetC1* _barrier_set_c1;
|
BarrierSetC1* _barrier_set_c1;
|
||||||
BarrierSetC2* _barrier_set_c2;
|
BarrierSetC2* _barrier_set_c2;
|
||||||
|
BarrierSetNMethod* _barrier_set_nmethod;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Metafunction mapping a class derived from BarrierSet to the
|
// Metafunction mapping a class derived from BarrierSet to the
|
||||||
|
@ -95,11 +97,13 @@ protected:
|
||||||
BarrierSet(BarrierSetAssembler* barrier_set_assembler,
|
BarrierSet(BarrierSetAssembler* barrier_set_assembler,
|
||||||
BarrierSetC1* barrier_set_c1,
|
BarrierSetC1* barrier_set_c1,
|
||||||
BarrierSetC2* barrier_set_c2,
|
BarrierSetC2* barrier_set_c2,
|
||||||
|
BarrierSetNMethod* barrier_set_nmethod,
|
||||||
const FakeRtti& fake_rtti) :
|
const FakeRtti& fake_rtti) :
|
||||||
_fake_rtti(fake_rtti),
|
_fake_rtti(fake_rtti),
|
||||||
_barrier_set_assembler(barrier_set_assembler),
|
_barrier_set_assembler(barrier_set_assembler),
|
||||||
_barrier_set_c1(barrier_set_c1),
|
_barrier_set_c1(barrier_set_c1),
|
||||||
_barrier_set_c2(barrier_set_c2) {}
|
_barrier_set_c2(barrier_set_c2),
|
||||||
|
_barrier_set_nmethod(barrier_set_nmethod) {}
|
||||||
~BarrierSet() { }
|
~BarrierSet() { }
|
||||||
|
|
||||||
template <class BarrierSetAssemblerT>
|
template <class BarrierSetAssemblerT>
|
||||||
|
@ -156,6 +160,10 @@ public:
|
||||||
return _barrier_set_c2;
|
return _barrier_set_c2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BarrierSetNMethod* barrier_set_nmethod() {
|
||||||
|
return _barrier_set_nmethod;
|
||||||
|
}
|
||||||
|
|
||||||
// The AccessBarrier of a BarrierSet subclass is called by the Access API
|
// The AccessBarrier of a BarrierSet subclass is called by the Access API
|
||||||
// (cf. oops/access.hpp) to perform decorated accesses. GC implementations
|
// (cf. oops/access.hpp) to perform decorated accesses. GC implementations
|
||||||
// may override these default access operations by declaring an
|
// may override these default access operations by declaring an
|
||||||
|
|
87
src/hotspot/share/gc/shared/barrierSetNMethod.cpp
Normal file
87
src/hotspot/share/gc/shared/barrierSetNMethod.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "code/codeCache.hpp"
|
||||||
|
#include "code/nmethod.hpp"
|
||||||
|
#include "gc/shared/barrierSet.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
|
#include "runtime/thread.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
int BarrierSetNMethod::disarmed_value() const {
|
||||||
|
char* disarmed_addr = reinterpret_cast<char*>(Thread::current());
|
||||||
|
disarmed_addr += in_bytes(thread_disarmed_offset());
|
||||||
|
return *reinterpret_cast<int*>(disarmed_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BarrierSetNMethod::supports_entry_barrier(nmethod* nm) {
|
||||||
|
if (nm->method()->is_method_handle_intrinsic()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm->is_native_method() && !nm->is_compiled_by_c2() && !nm->is_compiled_by_c1()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BarrierSetNMethod::nmethod_stub_entry_barrier(address* return_address_ptr) {
|
||||||
|
address return_address = *return_address_ptr;
|
||||||
|
CodeBlob* cb = CodeCache::find_blob(return_address);
|
||||||
|
assert(cb != NULL, "invariant");
|
||||||
|
|
||||||
|
nmethod* nm = cb->as_nmethod();
|
||||||
|
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
|
||||||
|
|
||||||
|
if (!bs_nm->is_armed(nm)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!nm->is_osr_method(), "Should not reach here");
|
||||||
|
// Called upon first entry after being armed
|
||||||
|
bool may_enter = bs_nm->nmethod_entry_barrier(nm);
|
||||||
|
if (!may_enter) {
|
||||||
|
log_trace(nmethod, barrier)("Deoptimizing nmethod: " PTR_FORMAT, p2i(nm));
|
||||||
|
bs_nm->deoptimize(nm, return_address_ptr);
|
||||||
|
}
|
||||||
|
return may_enter ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BarrierSetNMethod::nmethod_osr_entry_barrier(nmethod* nm) {
|
||||||
|
// This check depends on the invariant that all nmethods that are deoptimized / made not entrant
|
||||||
|
// are NOT disarmed.
|
||||||
|
// This invariant is important because a method can be deoptimized after the method have been
|
||||||
|
// resolved / looked up by OSR by another thread. By not deoptimizing them we guarantee that
|
||||||
|
// a deoptimized method will always hit the barrier and come to the same conclusion - deoptimize
|
||||||
|
if (!is_armed(nm)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(nm->is_osr_method(), "Should not reach here");
|
||||||
|
log_trace(nmethod, barrier)("Running osr nmethod entry barrier: " PTR_FORMAT, p2i(nm));
|
||||||
|
return nmethod_entry_barrier(nm);
|
||||||
|
}
|
52
src/hotspot/share/gc/shared/barrierSetNMethod.hpp
Normal file
52
src/hotspot/share/gc/shared/barrierSetNMethod.hpp
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_CODE_NMETHOD_BARRIER_HPP
|
||||||
|
#define SHARE_CODE_NMETHOD_BARRIER_HPP
|
||||||
|
|
||||||
|
#include "memory/allocation.hpp"
|
||||||
|
#include "utilities/globalDefinitions.hpp"
|
||||||
|
#include "utilities/sizes.hpp"
|
||||||
|
|
||||||
|
class nmethod;
|
||||||
|
|
||||||
|
class BarrierSetNMethod: public CHeapObj<mtGC> {
|
||||||
|
bool supports_entry_barrier(nmethod* nm);
|
||||||
|
void deoptimize(nmethod* nm, address* return_addr_ptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int disarmed_value() const;
|
||||||
|
virtual bool nmethod_entry_barrier(nmethod* nm) = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ByteSize thread_disarmed_offset() const = 0;
|
||||||
|
|
||||||
|
static int nmethod_stub_entry_barrier(address* return_address_ptr);
|
||||||
|
bool nmethod_osr_entry_barrier(nmethod* nm);
|
||||||
|
bool is_armed(nmethod* nm);
|
||||||
|
void disarm(nmethod* nm);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SHARE_CODE_NMETHOD_BARRIER_HPP
|
|
@ -39,6 +39,7 @@ protected:
|
||||||
: BarrierSet(barrier_set_assembler,
|
: BarrierSet(barrier_set_assembler,
|
||||||
barrier_set_c1,
|
barrier_set_c1,
|
||||||
barrier_set_c2,
|
barrier_set_c2,
|
||||||
|
NULL /* barrier_set_nmethod */,
|
||||||
fake_rtti.add_tag(BarrierSet::ModRef)) { }
|
fake_rtti.add_tag(BarrierSet::ModRef)) { }
|
||||||
~ModRefBarrierSet() { }
|
~ModRefBarrierSet() { }
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ ZBarrierSet::ZBarrierSet() :
|
||||||
BarrierSet(make_barrier_set_assembler<ZBarrierSetAssembler>(),
|
BarrierSet(make_barrier_set_assembler<ZBarrierSetAssembler>(),
|
||||||
make_barrier_set_c1<ZBarrierSetC1>(),
|
make_barrier_set_c1<ZBarrierSetC1>(),
|
||||||
make_barrier_set_c2<ZBarrierSetC2>(),
|
make_barrier_set_c2<ZBarrierSetC2>(),
|
||||||
|
NULL /* barrier_set_nmethod */,
|
||||||
BarrierSet::FakeRtti(BarrierSet::ZBarrierSet)) {}
|
BarrierSet::FakeRtti(BarrierSet::ZBarrierSet)) {}
|
||||||
|
|
||||||
ZBarrierSetAssembler* ZBarrierSet::assembler() {
|
ZBarrierSetAssembler* ZBarrierSet::assembler() {
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "gc/shared/gcHeapSummary.hpp"
|
#include "gc/shared/gcHeapSummary.hpp"
|
||||||
|
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||||
#include "gc/z/zCollectedHeap.hpp"
|
#include "gc/z/zCollectedHeap.hpp"
|
||||||
#include "gc/z/zGlobals.hpp"
|
#include "gc/z/zGlobals.hpp"
|
||||||
#include "gc/z/zHeap.inline.hpp"
|
#include "gc/z/zHeap.inline.hpp"
|
||||||
|
@ -295,6 +296,14 @@ VirtualSpaceSummary ZCollectedHeap::create_heap_space_summary() {
|
||||||
reserved_region().start() + max_capacity_in_words);
|
reserved_region().start() + max_capacity_in_words);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZCollectedHeap::safepoint_synchronize_begin() {
|
||||||
|
SuspendibleThreadSet::synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZCollectedHeap::safepoint_synchronize_end() {
|
||||||
|
SuspendibleThreadSet::desynchronize();
|
||||||
|
}
|
||||||
|
|
||||||
void ZCollectedHeap::prepare_for_verify() {
|
void ZCollectedHeap::prepare_for_verify() {
|
||||||
// Does nothing
|
// Does nothing
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,9 @@ public:
|
||||||
|
|
||||||
virtual VirtualSpaceSummary create_heap_space_summary();
|
virtual VirtualSpaceSummary create_heap_space_summary();
|
||||||
|
|
||||||
|
virtual void safepoint_synchronize_begin();
|
||||||
|
virtual void safepoint_synchronize_end();
|
||||||
|
|
||||||
virtual void print_on(outputStream* st) const;
|
virtual void print_on(outputStream* st) const;
|
||||||
virtual void print_on_error(outputStream* st) const;
|
virtual void print_on_error(outputStream* st) const;
|
||||||
virtual void print_extended_on(outputStream* st) const;
|
virtual void print_extended_on(outputStream* st) const;
|
||||||
|
|
|
@ -336,7 +336,7 @@ void ZDriver::run_gc_cycle(GCCause::Cause cause) {
|
||||||
// Phase 2: Concurrent Mark
|
// Phase 2: Concurrent Mark
|
||||||
{
|
{
|
||||||
ZStatTimer timer(ZPhaseConcurrentMark);
|
ZStatTimer timer(ZPhaseConcurrentMark);
|
||||||
ZHeap::heap()->mark();
|
ZHeap::heap()->mark(true /* initial */);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 3: Pause Mark End
|
// Phase 3: Pause Mark End
|
||||||
|
@ -345,7 +345,7 @@ void ZDriver::run_gc_cycle(GCCause::Cause cause) {
|
||||||
while (!vm_operation(&cl)) {
|
while (!vm_operation(&cl)) {
|
||||||
// Phase 3.5: Concurrent Mark Continue
|
// Phase 3.5: Concurrent Mark Continue
|
||||||
ZStatTimer timer(ZPhaseConcurrentMarkContinue);
|
ZStatTimer timer(ZPhaseConcurrentMarkContinue);
|
||||||
ZHeap::heap()->mark();
|
ZHeap::heap()->mark(false /* initial */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -296,8 +296,8 @@ void ZHeap::mark_start() {
|
||||||
ZStatHeap::set_at_mark_start(capacity(), used());
|
ZStatHeap::set_at_mark_start(capacity(), used());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZHeap::mark() {
|
void ZHeap::mark(bool initial) {
|
||||||
_mark.mark();
|
_mark.mark(initial);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZHeap::mark_flush_and_free(Thread* thread) {
|
void ZHeap::mark_flush_and_free(Thread* thread) {
|
||||||
|
|
|
@ -133,7 +133,7 @@ public:
|
||||||
bool is_object_strongly_live(uintptr_t addr) const;
|
bool is_object_strongly_live(uintptr_t addr) const;
|
||||||
template <bool finalizable, bool publish> void mark_object(uintptr_t addr);
|
template <bool finalizable, bool publish> void mark_object(uintptr_t addr);
|
||||||
void mark_start();
|
void mark_start();
|
||||||
void mark();
|
void mark(bool initial);
|
||||||
void mark_flush_and_free(Thread* thread);
|
void mark_flush_and_free(Thread* thread);
|
||||||
bool mark_end();
|
bool mark_end();
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include "gc/z/zOop.inline.hpp"
|
#include "gc/z/zOop.inline.hpp"
|
||||||
#include "gc/z/zRootsIterator.hpp"
|
#include "gc/z/zRootsIterator.hpp"
|
||||||
#include "memory/iterator.inline.hpp"
|
#include "memory/iterator.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
|
||||||
#include "utilities/bitMap.inline.hpp"
|
#include "utilities/bitMap.inline.hpp"
|
||||||
#include "utilities/stack.inline.hpp"
|
#include "utilities/stack.inline.hpp"
|
||||||
|
|
||||||
|
@ -54,19 +53,18 @@ public:
|
||||||
class ZHeapIteratorRootOopClosure : public ZRootsIteratorClosure {
|
class ZHeapIteratorRootOopClosure : public ZRootsIteratorClosure {
|
||||||
private:
|
private:
|
||||||
ZHeapIterator* const _iter;
|
ZHeapIterator* const _iter;
|
||||||
ObjectClosure* const _cl;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ZHeapIteratorRootOopClosure(ZHeapIterator* iter, ObjectClosure* cl) :
|
ZHeapIteratorRootOopClosure(ZHeapIterator* iter) :
|
||||||
_iter(iter),
|
_iter(iter) {}
|
||||||
_cl(cl) {}
|
|
||||||
|
|
||||||
virtual void do_oop(oop* p) {
|
virtual void do_oop(oop* p) {
|
||||||
// Load barrier needed here for the same reason we
|
// Load barrier needed here for the same reason we
|
||||||
// need fixup_partial_loads() in ZHeap::mark_end()
|
// need fixup_partial_loads() in ZHeap::mark_end().
|
||||||
|
// This barrier is also needed here in case we're
|
||||||
|
// treating the JVMTI weak tag map as strong roots.
|
||||||
const oop obj = ZBarrier::load_barrier_on_oop_field(p);
|
const oop obj = ZBarrier::load_barrier_on_oop_field(p);
|
||||||
_iter->push(obj);
|
_iter->push(obj);
|
||||||
_iter->drain(_cl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void do_oop(narrowOop* p) {
|
virtual void do_oop(narrowOop* p) {
|
||||||
|
@ -74,19 +72,13 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ZHeapIteratorPushOopClosure : public BasicOopIterateClosure {
|
class ZHeapIteratorOopClosure : public BasicOopIterateClosure {
|
||||||
private:
|
private:
|
||||||
ZHeapIterator* const _iter;
|
ZHeapIterator* const _iter;
|
||||||
const oop _base;
|
const oop _base;
|
||||||
const bool _visit_referents;
|
const bool _visit_referents;
|
||||||
|
|
||||||
public:
|
oop load_oop(oop* p) const {
|
||||||
ZHeapIteratorPushOopClosure(ZHeapIterator* iter, oop base) :
|
|
||||||
_iter(iter),
|
|
||||||
_base(base),
|
|
||||||
_visit_referents(iter->visit_referents()) {}
|
|
||||||
|
|
||||||
oop load_oop(oop* p) {
|
|
||||||
if (_visit_referents) {
|
if (_visit_referents) {
|
||||||
return HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(_base, _base->field_offset(p));
|
return HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(_base, _base->field_offset(p));
|
||||||
} else {
|
} else {
|
||||||
|
@ -94,6 +86,12 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ZHeapIteratorOopClosure(ZHeapIterator* iter, oop base, bool visit_referents) :
|
||||||
|
_iter(iter),
|
||||||
|
_base(base),
|
||||||
|
_visit_referents(visit_referents) {}
|
||||||
|
|
||||||
virtual ReferenceIterationMode reference_iteration_mode() {
|
virtual ReferenceIterationMode reference_iteration_mode() {
|
||||||
return _visit_referents ? DO_FIELDS : DO_FIELDS_EXCEPT_REFERENT;
|
return _visit_referents ? DO_FIELDS : DO_FIELDS_EXCEPT_REFERENT;
|
||||||
}
|
}
|
||||||
|
@ -126,11 +124,11 @@ ZHeapIterator::~ZHeapIterator() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZHeapIterator::object_index_max() const {
|
static size_t object_index_max() {
|
||||||
return ZPageSizeMin >> ZObjectAlignmentSmallShift;
|
return ZPageSizeMin >> ZObjectAlignmentSmallShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZHeapIterator::object_index(oop obj) const {
|
static size_t object_index(oop obj) {
|
||||||
const uintptr_t addr = ZOop::to_address(obj);
|
const uintptr_t addr = ZOop::to_address(obj);
|
||||||
const uintptr_t offset = ZAddress::offset(addr);
|
const uintptr_t offset = ZAddress::offset(addr);
|
||||||
const uintptr_t mask = (1 << ZPageSizeMinShift) - 1;
|
const uintptr_t mask = (1 << ZPageSizeMinShift) - 1;
|
||||||
|
@ -165,7 +163,22 @@ void ZHeapIterator::push(oop obj) {
|
||||||
_visit_stack.push(obj);
|
_visit_stack.push(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZHeapIterator::drain(ObjectClosure* cl) {
|
void ZHeapIterator::objects_do(ObjectClosure* cl) {
|
||||||
|
// Push roots onto stack
|
||||||
|
{
|
||||||
|
// Note that we also visit the JVMTI weak tag map as if they were
|
||||||
|
// strong roots to make sure we visit all tagged objects, even
|
||||||
|
// those that might now have become unreachable. If we didn't do
|
||||||
|
// this the user would have expected to see ObjectFree events for
|
||||||
|
// unreachable objects in the tag map.
|
||||||
|
ZRootsIterator roots;
|
||||||
|
ZConcurrentRootsIterator concurrent_roots(false /* marking */);
|
||||||
|
ZHeapIteratorRootOopClosure root_cl(this);
|
||||||
|
roots.oops_do(&root_cl, true /* visit_jvmti_weak_export */);
|
||||||
|
concurrent_roots.oops_do(&root_cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drain stack
|
||||||
while (!_visit_stack.is_empty()) {
|
while (!_visit_stack.is_empty()) {
|
||||||
const oop obj = _visit_stack.pop();
|
const oop obj = _visit_stack.pop();
|
||||||
|
|
||||||
|
@ -173,23 +186,7 @@ void ZHeapIterator::drain(ObjectClosure* cl) {
|
||||||
cl->do_object(obj);
|
cl->do_object(obj);
|
||||||
|
|
||||||
// Push members to visit
|
// Push members to visit
|
||||||
ZHeapIteratorPushOopClosure push_cl(this, obj);
|
ZHeapIteratorOopClosure push_cl(this, obj, _visit_referents);
|
||||||
obj->oop_iterate(&push_cl);
|
obj->oop_iterate(&push_cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZHeapIterator::visit_referents() const {
|
|
||||||
return _visit_referents;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZHeapIterator::objects_do(ObjectClosure* cl) {
|
|
||||||
ZHeapIteratorRootOopClosure root_cl(this, cl);
|
|
||||||
ZRootsIterator roots;
|
|
||||||
|
|
||||||
// Follow roots. Note that we also visit the JVMTI weak tag map
|
|
||||||
// as if they were strong roots to make sure we visit all tagged
|
|
||||||
// objects, even those that might now have become unreachable.
|
|
||||||
// If we didn't do this the user would have expected to see
|
|
||||||
// ObjectFree events for unreachable objects in the tag map.
|
|
||||||
roots.oops_do(&root_cl, true /* visit_jvmti_weak_export */);
|
|
||||||
}
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ class ZHeapIteratorBitMap;
|
||||||
|
|
||||||
class ZHeapIterator : public StackObj {
|
class ZHeapIterator : public StackObj {
|
||||||
friend class ZHeapIteratorRootOopClosure;
|
friend class ZHeapIteratorRootOopClosure;
|
||||||
friend class ZHeapIteratorPushOopClosure;
|
friend class ZHeapIteratorOopClosure;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef ZAddressRangeMap<ZHeapIteratorBitMap*, ZPageSizeMinShift> ZVisitMap;
|
typedef ZAddressRangeMap<ZHeapIteratorBitMap*, ZPageSizeMinShift> ZVisitMap;
|
||||||
|
@ -44,14 +44,8 @@ private:
|
||||||
ZVisitMap _visit_map;
|
ZVisitMap _visit_map;
|
||||||
const bool _visit_referents;
|
const bool _visit_referents;
|
||||||
|
|
||||||
size_t object_index_max() const;
|
|
||||||
size_t object_index(oop obj) const;
|
|
||||||
ZHeapIteratorBitMap* object_map(oop obj);
|
ZHeapIteratorBitMap* object_map(oop obj);
|
||||||
|
|
||||||
void push(oop obj);
|
void push(oop obj);
|
||||||
void drain(ObjectClosure* cl);
|
|
||||||
|
|
||||||
bool visit_referents() const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ZHeapIterator(bool visit_referents);
|
ZHeapIterator(bool visit_referents);
|
||||||
|
|
|
@ -38,8 +38,8 @@
|
||||||
ZInitialize::ZInitialize(ZBarrierSet* barrier_set) {
|
ZInitialize::ZInitialize(ZBarrierSet* barrier_set) {
|
||||||
log_info(gc, init)("Initializing %s", ZGCName);
|
log_info(gc, init)("Initializing %s", ZGCName);
|
||||||
log_info(gc, init)("Version: %s (%s)",
|
log_info(gc, init)("Version: %s (%s)",
|
||||||
Abstract_VM_Version::vm_release(),
|
VM_Version::vm_release(),
|
||||||
Abstract_VM_Version::jdk_debug_level());
|
VM_Version::jdk_debug_level());
|
||||||
|
|
||||||
// Early initialization
|
// Early initialization
|
||||||
ZAddressMasks::initialize();
|
ZAddressMasks::initialize();
|
||||||
|
|
|
@ -615,6 +615,34 @@ void ZMark::work(uint64_t timeout_in_millis) {
|
||||||
stacks->free(&_allocator);
|
stacks->free(&_allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ZMarkConcurrentRootsIteratorClosure : public ZRootsIteratorClosure {
|
||||||
|
public:
|
||||||
|
virtual void do_oop(oop* p) {
|
||||||
|
ZBarrier::mark_barrier_on_oop_field(p, false /* finalizable */);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void do_oop(narrowOop* p) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ZMarkConcurrentRootsTask : public ZTask {
|
||||||
|
private:
|
||||||
|
ZConcurrentRootsIterator _roots;
|
||||||
|
ZMarkConcurrentRootsIteratorClosure _cl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ZMarkConcurrentRootsTask(ZMark* mark) :
|
||||||
|
ZTask("ZMarkConcurrentRootsTask"),
|
||||||
|
_roots(true /* marking */),
|
||||||
|
_cl() {}
|
||||||
|
|
||||||
|
virtual void work() {
|
||||||
|
_roots.oops_do(&_cl);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ZMarkTask : public ZTask {
|
class ZMarkTask : public ZTask {
|
||||||
private:
|
private:
|
||||||
ZMark* const _mark;
|
ZMark* const _mark;
|
||||||
|
@ -637,7 +665,12 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void ZMark::mark() {
|
void ZMark::mark(bool initial) {
|
||||||
|
if (initial) {
|
||||||
|
ZMarkConcurrentRootsTask task(this);
|
||||||
|
_workers->run_concurrent(&task);
|
||||||
|
}
|
||||||
|
|
||||||
ZMarkTask task(this);
|
ZMarkTask task(this);
|
||||||
_workers->run_concurrent(&task);
|
_workers->run_concurrent(&task);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ public:
|
||||||
template <bool finalizable, bool publish> void mark_object(uintptr_t addr);
|
template <bool finalizable, bool publish> void mark_object(uintptr_t addr);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void mark();
|
void mark(bool initial);
|
||||||
bool end();
|
bool end();
|
||||||
|
|
||||||
void flush_and_free();
|
void flush_and_free();
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "compiler/oopMap.hpp"
|
#include "compiler/oopMap.hpp"
|
||||||
#include "gc/shared/oopStorageParState.inline.hpp"
|
#include "gc/shared/oopStorageParState.inline.hpp"
|
||||||
|
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||||
#include "gc/z/zGlobals.hpp"
|
#include "gc/z/zGlobals.hpp"
|
||||||
#include "gc/z/zNMethodTable.hpp"
|
#include "gc/z/zNMethodTable.hpp"
|
||||||
#include "gc/z/zOopClosures.inline.hpp"
|
#include "gc/z/zOopClosures.inline.hpp"
|
||||||
|
@ -52,16 +53,20 @@ static const ZStatSubPhase ZSubPhasePauseRootsSetup("Pause Roots Setup");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRoots("Pause Roots");
|
static const ZStatSubPhase ZSubPhasePauseRoots("Pause Roots");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsTeardown("Pause Roots Teardown");
|
static const ZStatSubPhase ZSubPhasePauseRootsTeardown("Pause Roots Teardown");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsUniverse("Pause Roots Universe");
|
static const ZStatSubPhase ZSubPhasePauseRootsUniverse("Pause Roots Universe");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsJNIHandles("Pause Roots JNIHandles");
|
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsObjectSynchronizer("Pause Roots ObjectSynchronizer");
|
static const ZStatSubPhase ZSubPhasePauseRootsObjectSynchronizer("Pause Roots ObjectSynchronizer");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsManagement("Pause Roots Management");
|
static const ZStatSubPhase ZSubPhasePauseRootsManagement("Pause Roots Management");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsJVMTIExport("Pause Roots JVMTIExport");
|
static const ZStatSubPhase ZSubPhasePauseRootsJVMTIExport("Pause Roots JVMTIExport");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsJVMTIWeakExport("Pause Roots JVMTIWeakExport");
|
static const ZStatSubPhase ZSubPhasePauseRootsJVMTIWeakExport("Pause Roots JVMTIWeakExport");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsSystemDictionary("Pause Roots SystemDictionary");
|
static const ZStatSubPhase ZSubPhasePauseRootsSystemDictionary("Pause Roots SystemDictionary");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsClassLoaderDataGraph("Pause Roots ClassLoaderDataGraph");
|
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsThreads("Pause Roots Threads");
|
static const ZStatSubPhase ZSubPhasePauseRootsThreads("Pause Roots Threads");
|
||||||
static const ZStatSubPhase ZSubPhasePauseRootsCodeCache("Pause Roots CodeCache");
|
static const ZStatSubPhase ZSubPhasePauseRootsCodeCache("Pause Roots CodeCache");
|
||||||
|
|
||||||
|
static const ZStatSubPhase ZSubPhaseConcurrentRootsSetup("Concurrent Roots Setup");
|
||||||
|
static const ZStatSubPhase ZSubPhaseConcurrentRoots("Concurrent Roots");
|
||||||
|
static const ZStatSubPhase ZSubPhaseConcurrentRootsTeardown("Concurrent Roots Teardown");
|
||||||
|
static const ZStatSubPhase ZSubPhaseConcurrentRootsJNIHandles("Concurrent Roots JNIHandles");
|
||||||
|
static const ZStatSubPhase ZSubPhaseConcurrentRootsClassLoaderDataGraph("Concurrent Roots ClassLoaderDataGraph");
|
||||||
|
|
||||||
static const ZStatSubPhase ZSubPhasePauseWeakRootsSetup("Pause Weak Roots Setup");
|
static const ZStatSubPhase ZSubPhasePauseWeakRootsSetup("Pause Weak Roots Setup");
|
||||||
static const ZStatSubPhase ZSubPhasePauseWeakRoots("Pause Weak Roots");
|
static const ZStatSubPhase ZSubPhasePauseWeakRoots("Pause Weak Roots");
|
||||||
static const ZStatSubPhase ZSubPhasePauseWeakRootsTeardown("Pause Weak Roots Teardown");
|
static const ZStatSubPhase ZSubPhasePauseWeakRootsTeardown("Pause Weak Roots Teardown");
|
||||||
|
@ -128,21 +133,17 @@ void ZParallelWeakOopsDo<T, F>::weak_oops_do(BoolObjectClosure* is_alive, ZRoots
|
||||||
}
|
}
|
||||||
|
|
||||||
ZRootsIterator::ZRootsIterator() :
|
ZRootsIterator::ZRootsIterator() :
|
||||||
_jni_handles_iter(JNIHandles::global_handles()),
|
|
||||||
_universe(this),
|
_universe(this),
|
||||||
_object_synchronizer(this),
|
_object_synchronizer(this),
|
||||||
_management(this),
|
_management(this),
|
||||||
_jvmti_export(this),
|
_jvmti_export(this),
|
||||||
_jvmti_weak_export(this),
|
_jvmti_weak_export(this),
|
||||||
_system_dictionary(this),
|
_system_dictionary(this),
|
||||||
_jni_handles(this),
|
|
||||||
_class_loader_data_graph(this),
|
|
||||||
_threads(this),
|
_threads(this),
|
||||||
_code_cache(this) {
|
_code_cache(this) {
|
||||||
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
|
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
|
||||||
ZStatTimer timer(ZSubPhasePauseRootsSetup);
|
ZStatTimer timer(ZSubPhasePauseRootsSetup);
|
||||||
Threads::change_thread_claim_parity();
|
Threads::change_thread_claim_parity();
|
||||||
ClassLoaderDataGraph::clear_claimed_marks();
|
|
||||||
COMPILER2_PRESENT(DerivedPointerTable::clear());
|
COMPILER2_PRESENT(DerivedPointerTable::clear());
|
||||||
CodeCache::gc_prologue();
|
CodeCache::gc_prologue();
|
||||||
ZNMethodTable::gc_prologue();
|
ZNMethodTable::gc_prologue();
|
||||||
|
@ -163,11 +164,6 @@ void ZRootsIterator::do_universe(ZRootsIteratorClosure* cl) {
|
||||||
Universe::oops_do(cl);
|
Universe::oops_do(cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZRootsIterator::do_jni_handles(ZRootsIteratorClosure* cl) {
|
|
||||||
ZStatTimer timer(ZSubPhasePauseRootsJNIHandles);
|
|
||||||
_jni_handles_iter.oops_do(cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZRootsIterator::do_object_synchronizer(ZRootsIteratorClosure* cl) {
|
void ZRootsIterator::do_object_synchronizer(ZRootsIteratorClosure* cl) {
|
||||||
ZStatTimer timer(ZSubPhasePauseRootsObjectSynchronizer);
|
ZStatTimer timer(ZSubPhasePauseRootsObjectSynchronizer);
|
||||||
ObjectSynchronizer::oops_do(cl);
|
ObjectSynchronizer::oops_do(cl);
|
||||||
|
@ -194,12 +190,6 @@ void ZRootsIterator::do_system_dictionary(ZRootsIteratorClosure* cl) {
|
||||||
SystemDictionary::oops_do(cl);
|
SystemDictionary::oops_do(cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) {
|
|
||||||
ZStatTimer timer(ZSubPhasePauseRootsClassLoaderDataGraph);
|
|
||||||
CLDToOopClosure cld_cl(cl);
|
|
||||||
ClassLoaderDataGraph::cld_do(&cld_cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZRootsIterator::do_threads(ZRootsIteratorClosure* cl) {
|
void ZRootsIterator::do_threads(ZRootsIteratorClosure* cl) {
|
||||||
ZStatTimer timer(ZSubPhasePauseRootsThreads);
|
ZStatTimer timer(ZSubPhasePauseRootsThreads);
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
|
@ -218,8 +208,6 @@ void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl, bool visit_jvmti_weak_ex
|
||||||
_management.oops_do(cl);
|
_management.oops_do(cl);
|
||||||
_jvmti_export.oops_do(cl);
|
_jvmti_export.oops_do(cl);
|
||||||
_system_dictionary.oops_do(cl);
|
_system_dictionary.oops_do(cl);
|
||||||
_jni_handles.oops_do(cl);
|
|
||||||
_class_loader_data_graph.oops_do(cl);
|
|
||||||
_threads.oops_do(cl);
|
_threads.oops_do(cl);
|
||||||
_code_cache.oops_do(cl);
|
_code_cache.oops_do(cl);
|
||||||
if (visit_jvmti_weak_export) {
|
if (visit_jvmti_weak_export) {
|
||||||
|
@ -227,6 +215,43 @@ void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl, bool visit_jvmti_weak_ex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZConcurrentRootsIterator::ZConcurrentRootsIterator(bool marking) :
|
||||||
|
_marking(marking),
|
||||||
|
_sts_joiner(marking /* active */),
|
||||||
|
_jni_handles_iter(JNIHandles::global_handles()),
|
||||||
|
_jni_handles(this),
|
||||||
|
_class_loader_data_graph(this) {
|
||||||
|
ZStatTimer timer(ZSubPhaseConcurrentRootsSetup);
|
||||||
|
if (_marking) {
|
||||||
|
ClassLoaderDataGraph_lock->lock();
|
||||||
|
ClassLoaderDataGraph::clear_claimed_marks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZConcurrentRootsIterator::~ZConcurrentRootsIterator() {
|
||||||
|
ZStatTimer timer(ZSubPhaseConcurrentRootsTeardown);
|
||||||
|
if (_marking) {
|
||||||
|
ClassLoaderDataGraph_lock->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZConcurrentRootsIterator::do_jni_handles(ZRootsIteratorClosure* cl) {
|
||||||
|
ZStatTimer timer(ZSubPhaseConcurrentRootsJNIHandles);
|
||||||
|
_jni_handles_iter.oops_do(cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) {
|
||||||
|
ZStatTimer timer(ZSubPhaseConcurrentRootsClassLoaderDataGraph);
|
||||||
|
CLDToOopClosure cld_cl(cl, _marking ? ClassLoaderData::_claim_strong : ClassLoaderData::_claim_none);
|
||||||
|
ClassLoaderDataGraph::cld_do(&cld_cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZConcurrentRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
|
||||||
|
ZStatTimer timer(ZSubPhaseConcurrentRoots);
|
||||||
|
_jni_handles.oops_do(cl);
|
||||||
|
_class_loader_data_graph.oops_do(cl);
|
||||||
|
}
|
||||||
|
|
||||||
ZWeakRootsIterator::ZWeakRootsIterator() :
|
ZWeakRootsIterator::ZWeakRootsIterator() :
|
||||||
_jvmti_weak_export(this),
|
_jvmti_weak_export(this),
|
||||||
_jfr_weak(this) {
|
_jfr_weak(this) {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#define SHARE_GC_Z_ZROOTSITERATOR_HPP
|
#define SHARE_GC_Z_ZROOTSITERATOR_HPP
|
||||||
|
|
||||||
#include "gc/shared/oopStorageParState.hpp"
|
#include "gc/shared/oopStorageParState.hpp"
|
||||||
|
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "memory/iterator.hpp"
|
#include "memory/iterator.hpp"
|
||||||
#include "runtime/thread.hpp"
|
#include "runtime/thread.hpp"
|
||||||
|
@ -37,8 +38,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef OopStorage::ParState<false /* concurrent */, false /* is_const */> ZOopStorageIterator;
|
typedef OopStorage::ParState<true /* concurrent */, false /* is_const */> ZOopStorageIterator;
|
||||||
typedef OopStorage::ParState<true /* concurrent */, false /* is_const */> ZConcurrentOopStorageIterator;
|
|
||||||
|
|
||||||
template <typename T, void (T::*F)(ZRootsIteratorClosure*)>
|
template <typename T, void (T::*F)(ZRootsIteratorClosure*)>
|
||||||
class ZSerialOopsDo {
|
class ZSerialOopsDo {
|
||||||
|
@ -86,29 +86,23 @@ public:
|
||||||
|
|
||||||
class ZRootsIterator {
|
class ZRootsIterator {
|
||||||
private:
|
private:
|
||||||
ZOopStorageIterator _jni_handles_iter;
|
|
||||||
|
|
||||||
void do_universe(ZRootsIteratorClosure* cl);
|
void do_universe(ZRootsIteratorClosure* cl);
|
||||||
void do_jni_handles(ZRootsIteratorClosure* cl);
|
|
||||||
void do_object_synchronizer(ZRootsIteratorClosure* cl);
|
void do_object_synchronizer(ZRootsIteratorClosure* cl);
|
||||||
void do_management(ZRootsIteratorClosure* cl);
|
void do_management(ZRootsIteratorClosure* cl);
|
||||||
void do_jvmti_export(ZRootsIteratorClosure* cl);
|
void do_jvmti_export(ZRootsIteratorClosure* cl);
|
||||||
void do_jvmti_weak_export(ZRootsIteratorClosure* cl);
|
void do_jvmti_weak_export(ZRootsIteratorClosure* cl);
|
||||||
void do_system_dictionary(ZRootsIteratorClosure* cl);
|
void do_system_dictionary(ZRootsIteratorClosure* cl);
|
||||||
void do_class_loader_data_graph(ZRootsIteratorClosure* cl);
|
|
||||||
void do_threads(ZRootsIteratorClosure* cl);
|
void do_threads(ZRootsIteratorClosure* cl);
|
||||||
void do_code_cache(ZRootsIteratorClosure* cl);
|
void do_code_cache(ZRootsIteratorClosure* cl);
|
||||||
|
|
||||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_universe> _universe;
|
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_universe> _universe;
|
||||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_object_synchronizer> _object_synchronizer;
|
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_object_synchronizer> _object_synchronizer;
|
||||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_management> _management;
|
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_management> _management;
|
||||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_export> _jvmti_export;
|
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_export> _jvmti_export;
|
||||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_weak_export> _jvmti_weak_export;
|
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_weak_export> _jvmti_weak_export;
|
||||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_system_dictionary> _system_dictionary;
|
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_system_dictionary> _system_dictionary;
|
||||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_jni_handles> _jni_handles;
|
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_threads> _threads;
|
||||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_class_loader_data_graph> _class_loader_data_graph;
|
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_code_cache> _code_cache;
|
||||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_threads> _threads;
|
|
||||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_code_cache> _code_cache;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ZRootsIterator();
|
ZRootsIterator();
|
||||||
|
@ -117,6 +111,25 @@ public:
|
||||||
void oops_do(ZRootsIteratorClosure* cl, bool visit_jvmti_weak_export = false);
|
void oops_do(ZRootsIteratorClosure* cl, bool visit_jvmti_weak_export = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ZConcurrentRootsIterator {
|
||||||
|
private:
|
||||||
|
const bool _marking;
|
||||||
|
SuspendibleThreadSetJoiner _sts_joiner;
|
||||||
|
ZOopStorageIterator _jni_handles_iter;
|
||||||
|
|
||||||
|
void do_jni_handles(ZRootsIteratorClosure* cl);
|
||||||
|
void do_class_loader_data_graph(ZRootsIteratorClosure* cl);
|
||||||
|
|
||||||
|
ZParallelOopsDo<ZConcurrentRootsIterator, &ZConcurrentRootsIterator::do_jni_handles> _jni_handles;
|
||||||
|
ZParallelOopsDo<ZConcurrentRootsIterator, &ZConcurrentRootsIterator::do_class_loader_data_graph> _class_loader_data_graph;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ZConcurrentRootsIterator(bool marking);
|
||||||
|
~ZConcurrentRootsIterator();
|
||||||
|
|
||||||
|
void oops_do(ZRootsIteratorClosure* cl);
|
||||||
|
};
|
||||||
|
|
||||||
class ZWeakRootsIterator {
|
class ZWeakRootsIterator {
|
||||||
private:
|
private:
|
||||||
void do_jvmti_weak_export(BoolObjectClosure* is_alive, ZRootsIteratorClosure* cl);
|
void do_jvmti_weak_export(BoolObjectClosure* is_alive, ZRootsIteratorClosure* cl);
|
||||||
|
@ -135,9 +148,9 @@ public:
|
||||||
|
|
||||||
class ZConcurrentWeakRootsIterator {
|
class ZConcurrentWeakRootsIterator {
|
||||||
private:
|
private:
|
||||||
ZConcurrentOopStorageIterator _vm_weak_handles_iter;
|
ZOopStorageIterator _vm_weak_handles_iter;
|
||||||
ZConcurrentOopStorageIterator _jni_weak_handles_iter;
|
ZOopStorageIterator _jni_weak_handles_iter;
|
||||||
ZConcurrentOopStorageIterator _string_table_iter;
|
ZOopStorageIterator _string_table_iter;
|
||||||
|
|
||||||
void do_vm_weak_handles(ZRootsIteratorClosure* cl);
|
void do_vm_weak_handles(ZRootsIteratorClosure* cl);
|
||||||
void do_jni_weak_handles(ZRootsIteratorClosure* cl);
|
void do_jni_weak_handles(ZRootsIteratorClosure* cl);
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "compiler/compileBroker.hpp"
|
#include "compiler/compileBroker.hpp"
|
||||||
#include "compiler/disassembler.hpp"
|
#include "compiler/disassembler.hpp"
|
||||||
|
#include "gc/shared/barrierSetNMethod.hpp"
|
||||||
#include "gc/shared/collectedHeap.hpp"
|
#include "gc/shared/collectedHeap.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "interpreter/interpreterRuntime.hpp"
|
#include "interpreter/interpreterRuntime.hpp"
|
||||||
|
@ -1045,6 +1046,13 @@ nmethod* InterpreterRuntime::frequency_counter_overflow(JavaThread* thread, addr
|
||||||
Method* method = last_frame.method();
|
Method* method = last_frame.method();
|
||||||
int bci = method->bci_from(last_frame.bcp());
|
int bci = method->bci_from(last_frame.bcp());
|
||||||
nm = method->lookup_osr_nmethod_for(bci, CompLevel_none, false);
|
nm = method->lookup_osr_nmethod_for(bci, CompLevel_none, false);
|
||||||
|
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
|
||||||
|
if (nm != NULL && bs_nm != NULL) {
|
||||||
|
// in case the transition passed a safepoint we need to barrier this again
|
||||||
|
if (!bs_nm->nmethod_osr_entry_barrier(nm)) {
|
||||||
|
nm = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (nm != NULL && thread->is_interp_only_mode()) {
|
if (nm != NULL && thread->is_interp_only_mode()) {
|
||||||
// Normally we never get an nm if is_interp_only_mode() is true, because
|
// Normally we never get an nm if is_interp_only_mode() is true, because
|
||||||
|
@ -1081,6 +1089,13 @@ IRT_ENTRY(nmethod*,
|
||||||
nmethod* osr_nm = CompilationPolicy::policy()->event(method, method, branch_bci, bci, CompLevel_none, NULL, thread);
|
nmethod* osr_nm = CompilationPolicy::policy()->event(method, method, branch_bci, bci, CompLevel_none, NULL, thread);
|
||||||
assert(!HAS_PENDING_EXCEPTION, "Event handler should not throw any exceptions");
|
assert(!HAS_PENDING_EXCEPTION, "Event handler should not throw any exceptions");
|
||||||
|
|
||||||
|
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
|
||||||
|
if (osr_nm != NULL && bs_nm != NULL) {
|
||||||
|
if (!bs_nm->nmethod_osr_entry_barrier(osr_nm)) {
|
||||||
|
osr_nm = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (osr_nm != NULL) {
|
if (osr_nm != NULL) {
|
||||||
// We may need to do on-stack replacement which requires that no
|
// We may need to do on-stack replacement which requires that no
|
||||||
// monitors in the activation are biased because their
|
// monitors in the activation are biased because their
|
||||||
|
|
|
@ -974,68 +974,68 @@ void LinkResolver::resolve_field(fieldDescriptor& fd,
|
||||||
THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
|
THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!link_info.check_access())
|
// Access checking may be turned off when calling from within the VM.
|
||||||
// Access checking may be turned off when calling from within the VM.
|
|
||||||
return;
|
|
||||||
|
|
||||||
// check access
|
|
||||||
Klass* current_klass = link_info.current_klass();
|
Klass* current_klass = link_info.current_klass();
|
||||||
check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
|
if (link_info.check_access()) {
|
||||||
|
|
||||||
// check for errors
|
// check access
|
||||||
if (is_static != fd.is_static()) {
|
check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
|
||||||
ResourceMark rm(THREAD);
|
|
||||||
char msg[200];
|
|
||||||
jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string());
|
|
||||||
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A final field can be modified only
|
// check for errors
|
||||||
// (1) by methods declared in the class declaring the field and
|
if (is_static != fd.is_static()) {
|
||||||
// (2) by the <clinit> method (in case of a static field)
|
ResourceMark rm(THREAD);
|
||||||
// or by the <init> method (in case of an instance field).
|
char msg[200];
|
||||||
if (is_put && fd.access_flags().is_final()) {
|
jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string());
|
||||||
ResourceMark rm(THREAD);
|
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
|
||||||
stringStream ss;
|
|
||||||
|
|
||||||
if (sel_klass != current_klass) {
|
|
||||||
ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class",
|
|
||||||
is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
|
|
||||||
current_klass->external_name());
|
|
||||||
THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd.constants()->pool_holder()->major_version() >= 53) {
|
// A final field can be modified only
|
||||||
methodHandle m = link_info.current_method();
|
// (1) by methods declared in the class declaring the field and
|
||||||
assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
|
// (2) by the <clinit> method (in case of a static field)
|
||||||
bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
|
// or by the <init> method (in case of an instance field).
|
||||||
fd.is_static() &&
|
if (is_put && fd.access_flags().is_final()) {
|
||||||
!m()->is_static_initializer());
|
ResourceMark rm(THREAD);
|
||||||
bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
|
stringStream ss;
|
||||||
!fd.is_static() &&
|
|
||||||
!m->is_object_initializer());
|
|
||||||
|
|
||||||
if (is_initialized_static_final_update || is_initialized_instance_final_update) {
|
if (sel_klass != current_klass) {
|
||||||
ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ",
|
ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class",
|
||||||
is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
|
is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
|
||||||
m()->name()->as_C_string(),
|
current_klass->external_name());
|
||||||
is_static ? "<clinit>" : "<init>");
|
|
||||||
THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
|
THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fd.constants()->pool_holder()->major_version() >= 53) {
|
||||||
|
methodHandle m = link_info.current_method();
|
||||||
|
assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
|
||||||
|
bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
|
||||||
|
fd.is_static() &&
|
||||||
|
!m()->is_static_initializer());
|
||||||
|
bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
|
||||||
|
!fd.is_static() &&
|
||||||
|
!m->is_object_initializer());
|
||||||
|
|
||||||
|
if (is_initialized_static_final_update || is_initialized_instance_final_update) {
|
||||||
|
ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ",
|
||||||
|
is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
|
||||||
|
m()->name()->as_C_string(),
|
||||||
|
is_static ? "<clinit>" : "<init>");
|
||||||
|
THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize resolved_klass if necessary
|
||||||
|
// note 1: the klass which declared the field must be initialized (i.e, sel_klass)
|
||||||
|
// according to the newest JVM spec (5.5, p.170) - was bug (gri 7/28/99)
|
||||||
|
//
|
||||||
|
// note 2: we don't want to force initialization if we are just checking
|
||||||
|
// if the field access is legal; e.g., during compilation
|
||||||
|
if (is_static && initialize_class) {
|
||||||
|
sel_klass->initialize(CHECK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize resolved_klass if necessary
|
if ((sel_klass != current_klass) && (current_klass != NULL)) {
|
||||||
// note 1: the klass which declared the field must be initialized (i.e, sel_klass)
|
|
||||||
// according to the newest JVM spec (5.5, p.170) - was bug (gri 7/28/99)
|
|
||||||
//
|
|
||||||
// note 2: we don't want to force initialization if we are just checking
|
|
||||||
// if the field access is legal; e.g., during compilation
|
|
||||||
if (is_static && initialize_class) {
|
|
||||||
sel_klass->initialize(CHECK);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sel_klass != current_klass) {
|
|
||||||
check_field_loader_constraints(field, sig, current_klass, sel_klass, CHECK);
|
check_field_loader_constraints(field, sig, current_klass, sel_klass, CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ void RootSetClosure::process_roots(OopClosure* closure) {
|
||||||
SaveRestoreCLDClaimBits save_restore_cld_claim_bits;
|
SaveRestoreCLDClaimBits save_restore_cld_claim_bits;
|
||||||
RootSetClosureMarkScope mark_scope;
|
RootSetClosureMarkScope mark_scope;
|
||||||
|
|
||||||
CLDToOopClosure cldt_closure(closure);
|
CLDToOopClosure cldt_closure(closure, ClassLoaderData::_claim_strong);
|
||||||
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
|
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
|
||||||
CodeBlobToOopClosure blobs(closure, false);
|
CodeBlobToOopClosure blobs(closure, false);
|
||||||
Threads::oops_do(closure, &blobs);
|
Threads::oops_do(closure, &blobs);
|
||||||
|
|
|
@ -128,7 +128,7 @@ class ReferenceToRootClosure : public StackObj {
|
||||||
bool ReferenceToRootClosure::do_cldg_roots() {
|
bool ReferenceToRootClosure::do_cldg_roots() {
|
||||||
assert(!complete(), "invariant");
|
assert(!complete(), "invariant");
|
||||||
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_class_loader_data, OldObjectRoot::_type_undetermined, NULL);
|
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_class_loader_data, OldObjectRoot::_type_undetermined, NULL);
|
||||||
CLDToOopClosure cldt_closure(&rlc);
|
CLDToOopClosure cldt_closure(&rlc, ClassLoaderData::_claim_strong);
|
||||||
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
|
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
|
||||||
return rlc.complete();
|
return rlc.complete();
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,12 +69,12 @@ CLDClaimContext::CLDClaimContext() : _cld(NULL) {}
|
||||||
|
|
||||||
CLDClaimContext::CLDClaimContext(ClassLoaderData* cld) : _cld(cld) {
|
CLDClaimContext::CLDClaimContext(ClassLoaderData* cld) : _cld(cld) {
|
||||||
assert(_cld->claimed(), "invariant");
|
assert(_cld->claimed(), "invariant");
|
||||||
_cld->clear_claimed();
|
_cld->clear_claim();
|
||||||
}
|
}
|
||||||
|
|
||||||
CLDClaimContext::~CLDClaimContext() {
|
CLDClaimContext::~CLDClaimContext() {
|
||||||
if (_cld != NULL) {
|
if (_cld != NULL) {
|
||||||
_cld->claim();
|
_cld->try_claim(ClassLoaderData::_claim_strong);
|
||||||
assert(_cld->claimed(), "invariant");
|
assert(_cld->claimed(), "invariant");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,7 +323,7 @@ class name : AllStatic {
|
||||||
static void check(oop obj, const char* field_name, int offset); \
|
static void check(oop obj, const char* field_name, int offset); \
|
||||||
static void compute_offsets(TRAPS); \
|
static void compute_offsets(TRAPS); \
|
||||||
public: \
|
public: \
|
||||||
static InstanceKlass* klass() { return SystemDictionary::name##_klass(); }
|
static InstanceKlass* klass() { return SystemDictionary::name##_klass_is_loaded() ? SystemDictionary::name##_klass() : NULL; }
|
||||||
|
|
||||||
#define END_CLASS };
|
#define END_CLASS };
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -27,68 +27,68 @@
|
||||||
#if !INCLUDE_JVMCI
|
#if !INCLUDE_JVMCI
|
||||||
#define JVMCI_WK_KLASSES_DO(do_klass)
|
#define JVMCI_WK_KLASSES_DO(do_klass)
|
||||||
#else
|
#else
|
||||||
#define JVMCI_WK_KLASSES_DO(do_klass) \
|
#define JVMCI_WK_KLASSES_DO(do_klass) \
|
||||||
/* JVMCI classes. These are loaded on-demand. */ \
|
/* JVMCI classes. These are loaded on-demand. */ \
|
||||||
do_klass(JVMCI_klass, jdk_vm_ci_runtime_JVMCI, Jvmci) \
|
do_klass(JVMCI_klass, jdk_vm_ci_runtime_JVMCI ) \
|
||||||
do_klass(HotSpotCompiledCode_klass, jdk_vm_ci_hotspot_HotSpotCompiledCode, Jvmci) \
|
do_klass(HotSpotCompiledCode_klass, jdk_vm_ci_hotspot_HotSpotCompiledCode ) \
|
||||||
do_klass(HotSpotCompiledCode_Comment_klass, jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment, Jvmci) \
|
do_klass(HotSpotCompiledCode_Comment_klass, jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment ) \
|
||||||
do_klass(HotSpotCompiledNmethod_klass, jdk_vm_ci_hotspot_HotSpotCompiledNmethod, Jvmci) \
|
do_klass(HotSpotCompiledNmethod_klass, jdk_vm_ci_hotspot_HotSpotCompiledNmethod ) \
|
||||||
do_klass(HotSpotForeignCallTarget_klass, jdk_vm_ci_hotspot_HotSpotForeignCallTarget, Jvmci) \
|
do_klass(HotSpotForeignCallTarget_klass, jdk_vm_ci_hotspot_HotSpotForeignCallTarget ) \
|
||||||
do_klass(HotSpotReferenceMap_klass, jdk_vm_ci_hotspot_HotSpotReferenceMap, Jvmci) \
|
do_klass(HotSpotReferenceMap_klass, jdk_vm_ci_hotspot_HotSpotReferenceMap ) \
|
||||||
do_klass(HotSpotInstalledCode_klass, jdk_vm_ci_hotspot_HotSpotInstalledCode, Jvmci) \
|
do_klass(HotSpotInstalledCode_klass, jdk_vm_ci_hotspot_HotSpotInstalledCode ) \
|
||||||
do_klass(HotSpotNmethod_klass, jdk_vm_ci_hotspot_HotSpotNmethod, Jvmci) \
|
do_klass(HotSpotNmethod_klass, jdk_vm_ci_hotspot_HotSpotNmethod ) \
|
||||||
do_klass(HotSpotResolvedJavaMethodImpl_klass, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl, Jvmci) \
|
do_klass(HotSpotResolvedJavaMethodImpl_klass, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl ) \
|
||||||
do_klass(HotSpotResolvedObjectTypeImpl_klass, jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl, Jvmci) \
|
do_klass(HotSpotResolvedObjectTypeImpl_klass, jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl ) \
|
||||||
do_klass(HotSpotCompressedNullConstant_klass, jdk_vm_ci_hotspot_HotSpotCompressedNullConstant, Jvmci) \
|
do_klass(HotSpotCompressedNullConstant_klass, jdk_vm_ci_hotspot_HotSpotCompressedNullConstant ) \
|
||||||
do_klass(HotSpotObjectConstantImpl_klass, jdk_vm_ci_hotspot_HotSpotObjectConstantImpl, Jvmci) \
|
do_klass(HotSpotObjectConstantImpl_klass, jdk_vm_ci_hotspot_HotSpotObjectConstantImpl ) \
|
||||||
do_klass(HotSpotMetaspaceConstantImpl_klass, jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl, Jvmci) \
|
do_klass(HotSpotMetaspaceConstantImpl_klass, jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl ) \
|
||||||
do_klass(HotSpotSentinelConstant_klass, jdk_vm_ci_hotspot_HotSpotSentinelConstant, Jvmci) \
|
do_klass(HotSpotSentinelConstant_klass, jdk_vm_ci_hotspot_HotSpotSentinelConstant ) \
|
||||||
do_klass(HotSpotStackFrameReference_klass, jdk_vm_ci_hotspot_HotSpotStackFrameReference, Jvmci) \
|
do_klass(HotSpotStackFrameReference_klass, jdk_vm_ci_hotspot_HotSpotStackFrameReference ) \
|
||||||
do_klass(HotSpotMetaData_klass, jdk_vm_ci_hotspot_HotSpotMetaData, Jvmci) \
|
do_klass(HotSpotMetaData_klass, jdk_vm_ci_hotspot_HotSpotMetaData ) \
|
||||||
do_klass(HotSpotConstantPool_klass, jdk_vm_ci_hotspot_HotSpotConstantPool, Jvmci) \
|
do_klass(HotSpotConstantPool_klass, jdk_vm_ci_hotspot_HotSpotConstantPool ) \
|
||||||
do_klass(HotSpotJVMCIMetaAccessContext_klass, jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext, Jvmci) \
|
do_klass(HotSpotJVMCIMetaAccessContext_klass, jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext ) \
|
||||||
do_klass(HotSpotJVMCIRuntime_klass, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime, Jvmci) \
|
do_klass(HotSpotJVMCIRuntime_klass, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime ) \
|
||||||
do_klass(HotSpotSpeculationLog_klass, jdk_vm_ci_hotspot_HotSpotSpeculationLog, Jvmci) \
|
do_klass(HotSpotSpeculationLog_klass, jdk_vm_ci_hotspot_HotSpotSpeculationLog ) \
|
||||||
do_klass(HotSpotCompilationRequestResult_klass, jdk_vm_ci_hotspot_HotSpotCompilationRequestResult, Jvmci) \
|
do_klass(HotSpotCompilationRequestResult_klass, jdk_vm_ci_hotspot_HotSpotCompilationRequestResult) \
|
||||||
do_klass(VMField_klass, jdk_vm_ci_hotspot_VMField, Jvmci) \
|
do_klass(VMField_klass, jdk_vm_ci_hotspot_VMField ) \
|
||||||
do_klass(VMFlag_klass, jdk_vm_ci_hotspot_VMFlag, Jvmci) \
|
do_klass(VMFlag_klass, jdk_vm_ci_hotspot_VMFlag ) \
|
||||||
do_klass(VMIntrinsicMethod_klass, jdk_vm_ci_hotspot_VMIntrinsicMethod, Jvmci) \
|
do_klass(VMIntrinsicMethod_klass, jdk_vm_ci_hotspot_VMIntrinsicMethod ) \
|
||||||
do_klass(Assumptions_ConcreteMethod_klass, jdk_vm_ci_meta_Assumptions_ConcreteMethod, Jvmci) \
|
do_klass(Assumptions_ConcreteMethod_klass, jdk_vm_ci_meta_Assumptions_ConcreteMethod ) \
|
||||||
do_klass(Assumptions_NoFinalizableSubclass_klass, jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass, Jvmci) \
|
do_klass(Assumptions_NoFinalizableSubclass_klass, jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass ) \
|
||||||
do_klass(Assumptions_ConcreteSubtype_klass, jdk_vm_ci_meta_Assumptions_ConcreteSubtype, Jvmci) \
|
do_klass(Assumptions_ConcreteSubtype_klass, jdk_vm_ci_meta_Assumptions_ConcreteSubtype ) \
|
||||||
do_klass(Assumptions_LeafType_klass, jdk_vm_ci_meta_Assumptions_LeafType, Jvmci) \
|
do_klass(Assumptions_LeafType_klass, jdk_vm_ci_meta_Assumptions_LeafType ) \
|
||||||
do_klass(Assumptions_CallSiteTargetValue_klass, jdk_vm_ci_meta_Assumptions_CallSiteTargetValue, Jvmci) \
|
do_klass(Assumptions_CallSiteTargetValue_klass, jdk_vm_ci_meta_Assumptions_CallSiteTargetValue ) \
|
||||||
do_klass(Architecture_klass, jdk_vm_ci_code_Architecture, Jvmci) \
|
do_klass(Architecture_klass, jdk_vm_ci_code_Architecture ) \
|
||||||
do_klass(TargetDescription_klass, jdk_vm_ci_code_TargetDescription, Jvmci) \
|
do_klass(TargetDescription_klass, jdk_vm_ci_code_TargetDescription ) \
|
||||||
do_klass(BytecodePosition_klass, jdk_vm_ci_code_BytecodePosition, Jvmci) \
|
do_klass(BytecodePosition_klass, jdk_vm_ci_code_BytecodePosition ) \
|
||||||
do_klass(DebugInfo_klass, jdk_vm_ci_code_DebugInfo, Jvmci) \
|
do_klass(DebugInfo_klass, jdk_vm_ci_code_DebugInfo ) \
|
||||||
do_klass(RegisterSaveLayout_klass, jdk_vm_ci_code_RegisterSaveLayout, Jvmci) \
|
do_klass(RegisterSaveLayout_klass, jdk_vm_ci_code_RegisterSaveLayout ) \
|
||||||
do_klass(BytecodeFrame_klass, jdk_vm_ci_code_BytecodeFrame, Jvmci) \
|
do_klass(BytecodeFrame_klass, jdk_vm_ci_code_BytecodeFrame ) \
|
||||||
do_klass(InstalledCode_klass, jdk_vm_ci_code_InstalledCode, Jvmci) \
|
do_klass(InstalledCode_klass, jdk_vm_ci_code_InstalledCode ) \
|
||||||
do_klass(code_Location_klass, jdk_vm_ci_code_Location, Jvmci) \
|
do_klass(code_Location_klass, jdk_vm_ci_code_Location ) \
|
||||||
do_klass(code_Register_klass, jdk_vm_ci_code_Register, Jvmci) \
|
do_klass(code_Register_klass, jdk_vm_ci_code_Register ) \
|
||||||
do_klass(RegisterValue_klass, jdk_vm_ci_code_RegisterValue, Jvmci) \
|
do_klass(RegisterValue_klass, jdk_vm_ci_code_RegisterValue ) \
|
||||||
do_klass(StackSlot_klass, jdk_vm_ci_code_StackSlot, Jvmci) \
|
do_klass(StackSlot_klass, jdk_vm_ci_code_StackSlot ) \
|
||||||
do_klass(StackLockValue_klass, jdk_vm_ci_code_StackLockValue, Jvmci) \
|
do_klass(StackLockValue_klass, jdk_vm_ci_code_StackLockValue ) \
|
||||||
do_klass(VirtualObject_klass, jdk_vm_ci_code_VirtualObject, Jvmci) \
|
do_klass(VirtualObject_klass, jdk_vm_ci_code_VirtualObject ) \
|
||||||
do_klass(site_Call_klass, jdk_vm_ci_code_site_Call, Jvmci) \
|
do_klass(site_Call_klass, jdk_vm_ci_code_site_Call ) \
|
||||||
do_klass(site_ConstantReference_klass, jdk_vm_ci_code_site_ConstantReference, Jvmci) \
|
do_klass(site_ConstantReference_klass, jdk_vm_ci_code_site_ConstantReference ) \
|
||||||
do_klass(site_DataPatch_klass, jdk_vm_ci_code_site_DataPatch, Jvmci) \
|
do_klass(site_DataPatch_klass, jdk_vm_ci_code_site_DataPatch ) \
|
||||||
do_klass(site_DataSectionReference_klass, jdk_vm_ci_code_site_DataSectionReference, Jvmci) \
|
do_klass(site_DataSectionReference_klass, jdk_vm_ci_code_site_DataSectionReference ) \
|
||||||
do_klass(site_ExceptionHandler_klass, jdk_vm_ci_code_site_ExceptionHandler, Jvmci) \
|
do_klass(site_ExceptionHandler_klass, jdk_vm_ci_code_site_ExceptionHandler ) \
|
||||||
do_klass(site_Mark_klass, jdk_vm_ci_code_site_Mark, Jvmci) \
|
do_klass(site_Mark_klass, jdk_vm_ci_code_site_Mark ) \
|
||||||
do_klass(site_Infopoint_klass, jdk_vm_ci_code_site_Infopoint, Jvmci) \
|
do_klass(site_Infopoint_klass, jdk_vm_ci_code_site_Infopoint ) \
|
||||||
do_klass(site_Site_klass, jdk_vm_ci_code_site_Site, Jvmci) \
|
do_klass(site_Site_klass, jdk_vm_ci_code_site_Site ) \
|
||||||
do_klass(site_InfopointReason_klass, jdk_vm_ci_code_site_InfopointReason, Jvmci) \
|
do_klass(site_InfopointReason_klass, jdk_vm_ci_code_site_InfopointReason ) \
|
||||||
do_klass(InspectedFrameVisitor_klass, jdk_vm_ci_code_stack_InspectedFrameVisitor, Jvmci) \
|
do_klass(InspectedFrameVisitor_klass, jdk_vm_ci_code_stack_InspectedFrameVisitor ) \
|
||||||
do_klass(JavaConstant_klass, jdk_vm_ci_meta_JavaConstant, Jvmci) \
|
do_klass(JavaConstant_klass, jdk_vm_ci_meta_JavaConstant ) \
|
||||||
do_klass(PrimitiveConstant_klass, jdk_vm_ci_meta_PrimitiveConstant, Jvmci) \
|
do_klass(PrimitiveConstant_klass, jdk_vm_ci_meta_PrimitiveConstant ) \
|
||||||
do_klass(RawConstant_klass, jdk_vm_ci_meta_RawConstant, Jvmci) \
|
do_klass(RawConstant_klass, jdk_vm_ci_meta_RawConstant ) \
|
||||||
do_klass(NullConstant_klass, jdk_vm_ci_meta_NullConstant, Jvmci) \
|
do_klass(NullConstant_klass, jdk_vm_ci_meta_NullConstant ) \
|
||||||
do_klass(ExceptionHandler_klass, jdk_vm_ci_meta_ExceptionHandler, Jvmci) \
|
do_klass(ExceptionHandler_klass, jdk_vm_ci_meta_ExceptionHandler ) \
|
||||||
do_klass(JavaKind_klass, jdk_vm_ci_meta_JavaKind, Jvmci) \
|
do_klass(JavaKind_klass, jdk_vm_ci_meta_JavaKind ) \
|
||||||
do_klass(ValueKind_klass, jdk_vm_ci_meta_ValueKind, Jvmci) \
|
do_klass(ValueKind_klass, jdk_vm_ci_meta_ValueKind ) \
|
||||||
do_klass(Value_klass, jdk_vm_ci_meta_Value, Jvmci)
|
do_klass(Value_klass, jdk_vm_ci_meta_Value )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // SHARE_VM_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
|
#endif // SHARE_VM_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
DoNothingClosure do_nothing_cl;
|
DoNothingClosure do_nothing_cl;
|
||||||
|
|
||||||
void CLDToOopClosure::do_cld(ClassLoaderData* cld) {
|
void CLDToOopClosure::do_cld(ClassLoaderData* cld) {
|
||||||
cld->oops_do(_oop_closure, _must_claim_cld);
|
cld->oops_do(_oop_closure, _cld_claim);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectToOopClosure::do_object(oop obj) {
|
void ObjectToOopClosure::do_object(oop obj) {
|
||||||
|
|
|
@ -127,12 +127,13 @@ class CLDClosure : public Closure {
|
||||||
|
|
||||||
class CLDToOopClosure : public CLDClosure {
|
class CLDToOopClosure : public CLDClosure {
|
||||||
OopClosure* _oop_closure;
|
OopClosure* _oop_closure;
|
||||||
bool _must_claim_cld;
|
int _cld_claim;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CLDToOopClosure(OopClosure* oop_closure, bool must_claim_cld = true) :
|
CLDToOopClosure(OopClosure* oop_closure,
|
||||||
|
int cld_claim) :
|
||||||
_oop_closure(oop_closure),
|
_oop_closure(oop_closure),
|
||||||
_must_claim_cld(must_claim_cld) {}
|
_cld_claim(cld_claim) {}
|
||||||
|
|
||||||
void do_cld(ClassLoaderData* cld);
|
void do_cld(ClassLoaderData* cld);
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,8 +39,7 @@
|
||||||
#include "utilities/debug.hpp"
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
inline void MetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) {
|
inline void MetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) {
|
||||||
bool claim = true; // Must claim the class loader data before processing.
|
cld->oops_do(this, ClassLoaderData::_claim_strong);
|
||||||
cld->oops_do(this, claim);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void MetadataVisitingOopIterateClosure::do_klass(Klass* k) {
|
inline void MetadataVisitingOopIterateClosure::do_klass(Klass* k) {
|
||||||
|
|
|
@ -1195,7 +1195,7 @@ public:
|
||||||
|
|
||||||
// Iterate over all oop fields and metadata.
|
// Iterate over all oop fields and metadata.
|
||||||
template <typename T, class OopClosureType>
|
template <typename T, class OopClosureType>
|
||||||
inline int oop_oop_iterate(oop obj, OopClosureType* closure);
|
inline void oop_oop_iterate(oop obj, OopClosureType* closure);
|
||||||
|
|
||||||
// Iterate over all oop fields in one oop map.
|
// Iterate over all oop fields in one oop map.
|
||||||
template <typename T, class OopClosureType>
|
template <typename T, class OopClosureType>
|
||||||
|
@ -1205,7 +1205,7 @@ public:
|
||||||
// Reverse iteration
|
// Reverse iteration
|
||||||
// Iterate over all oop fields and metadata.
|
// Iterate over all oop fields and metadata.
|
||||||
template <typename T, class OopClosureType>
|
template <typename T, class OopClosureType>
|
||||||
inline int oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
|
inline void oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Iterate over all oop fields in the oop maps.
|
// Iterate over all oop fields in the oop maps.
|
||||||
|
@ -1225,7 +1225,7 @@ public:
|
||||||
|
|
||||||
// Iterate over all oop fields and metadata.
|
// Iterate over all oop fields and metadata.
|
||||||
template <typename T, class OopClosureType>
|
template <typename T, class OopClosureType>
|
||||||
inline int oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
|
inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Iterate over all oop fields in one oop map.
|
// Iterate over all oop fields in one oop map.
|
||||||
|
|
|
@ -130,28 +130,24 @@ ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_bounded(oop obj, OopCl
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class OopClosureType>
|
template <typename T, class OopClosureType>
|
||||||
ALWAYSINLINE int InstanceKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
|
ALWAYSINLINE void InstanceKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
|
||||||
if (Devirtualizer::do_metadata(closure)) {
|
if (Devirtualizer::do_metadata(closure)) {
|
||||||
Devirtualizer::do_klass(closure, this);
|
Devirtualizer::do_klass(closure, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
oop_oop_iterate_oop_maps<T>(obj, closure);
|
oop_oop_iterate_oop_maps<T>(obj, closure);
|
||||||
|
|
||||||
return size_helper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class OopClosureType>
|
template <typename T, class OopClosureType>
|
||||||
ALWAYSINLINE int InstanceKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
|
ALWAYSINLINE void InstanceKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
|
||||||
assert(!Devirtualizer::do_metadata(closure),
|
assert(!Devirtualizer::do_metadata(closure),
|
||||||
"Code to handle metadata is not implemented");
|
"Code to handle metadata is not implemented");
|
||||||
|
|
||||||
oop_oop_iterate_oop_maps_reverse<T>(obj, closure);
|
oop_oop_iterate_oop_maps_reverse<T>(obj, closure);
|
||||||
|
|
||||||
return size_helper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class OopClosureType>
|
template <typename T, class OopClosureType>
|
||||||
ALWAYSINLINE int InstanceKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
|
ALWAYSINLINE void InstanceKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
|
||||||
if (Devirtualizer::do_metadata(closure)) {
|
if (Devirtualizer::do_metadata(closure)) {
|
||||||
if (mr.contains(obj)) {
|
if (mr.contains(obj)) {
|
||||||
Devirtualizer::do_klass(closure, this);
|
Devirtualizer::do_klass(closure, this);
|
||||||
|
@ -159,8 +155,6 @@ ALWAYSINLINE int InstanceKlass::oop_oop_iterate_bounded(oop obj, OopClosureType*
|
||||||
}
|
}
|
||||||
|
|
||||||
oop_oop_iterate_oop_maps_bounded<T>(obj, closure, mr);
|
oop_oop_iterate_oop_maps_bounded<T>(obj, closure, mr);
|
||||||
|
|
||||||
return size_helper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SHARE_VM_OOPS_INSTANCEKLASS_INLINE_HPP
|
#endif // SHARE_VM_OOPS_INSTANCEKLASS_INLINE_HPP
|
||||||
|
|
|
@ -294,28 +294,20 @@ void Symbol::metaspace_pointers_do(MetaspaceClosure* it) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Symbol::print_on(outputStream* st) const {
|
void Symbol::print_on(outputStream* st) const {
|
||||||
if (this == NULL) {
|
st->print("Symbol: '");
|
||||||
st->print_cr("NULL");
|
print_symbol_on(st);
|
||||||
} else {
|
st->print("'");
|
||||||
st->print("Symbol: '");
|
st->print(" count %d", refcount());
|
||||||
print_symbol_on(st);
|
|
||||||
st->print("'");
|
|
||||||
st->print(" count %d", refcount());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The print_value functions are present in all builds, to support the
|
// The print_value functions are present in all builds, to support the
|
||||||
// disassembler and error reporting.
|
// disassembler and error reporting.
|
||||||
void Symbol::print_value_on(outputStream* st) const {
|
void Symbol::print_value_on(outputStream* st) const {
|
||||||
if (this == NULL) {
|
st->print("'");
|
||||||
st->print("NULL");
|
for (int i = 0; i < utf8_length(); i++) {
|
||||||
} else {
|
st->print("%c", char_at(i));
|
||||||
st->print("'");
|
|
||||||
for (int i = 0; i < utf8_length(); i++) {
|
|
||||||
st->print("%c", char_at(i));
|
|
||||||
}
|
|
||||||
st->print("'");
|
|
||||||
}
|
}
|
||||||
|
st->print("'");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Symbol::is_valid(Symbol* s) {
|
bool Symbol::is_valid(Symbol* s) {
|
||||||
|
|
|
@ -714,10 +714,151 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (can_reshape) {
|
||||||
|
modified |= optimize_trichotomy(phase->is_IterGVN());
|
||||||
|
}
|
||||||
|
|
||||||
return modified ? this : NULL;
|
return modified ? this : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------optimize_trichotomy--------------------------
|
||||||
|
// Optimize nested comparisons of the following kind:
|
||||||
|
//
|
||||||
|
// int compare(int a, int b) {
|
||||||
|
// return (a < b) ? -1 : (a == b) ? 0 : 1;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Shape 1:
|
||||||
|
// if (compare(a, b) == 1) { ... } -> if (a > b) { ... }
|
||||||
|
//
|
||||||
|
// Shape 2:
|
||||||
|
// if (compare(a, b) == 0) { ... } -> if (a == b) { ... }
|
||||||
|
//
|
||||||
|
// Above code leads to the following IR shapes where both Ifs compare the
|
||||||
|
// same value and two out of three region inputs idx1 and idx2 map to
|
||||||
|
// the same value and control flow.
|
||||||
|
//
|
||||||
|
// (1) If (2) If
|
||||||
|
// / \ / \
|
||||||
|
// Proj Proj Proj Proj
|
||||||
|
// | \ | \
|
||||||
|
// | If | If If
|
||||||
|
// | / \ | / \ / \
|
||||||
|
// | Proj Proj | Proj Proj ==> Proj Proj
|
||||||
|
// | / / \ | / | /
|
||||||
|
// Region / \ | / | /
|
||||||
|
// \ / \ | / | /
|
||||||
|
// Region Region Region
|
||||||
|
//
|
||||||
|
// The method returns true if 'this' is modified and false otherwise.
|
||||||
|
bool RegionNode::optimize_trichotomy(PhaseIterGVN* igvn) {
|
||||||
|
int idx1 = 1, idx2 = 2;
|
||||||
|
Node* region = NULL;
|
||||||
|
if (req() == 3 && in(1) != NULL && in(2) != NULL) {
|
||||||
|
// Shape 1: Check if one of the inputs is a region that merges two control
|
||||||
|
// inputs and has no other users (especially no Phi users).
|
||||||
|
region = in(1)->isa_Region() ? in(1) : in(2)->isa_Region();
|
||||||
|
if (region == NULL || region->outcnt() != 2 || region->req() != 3) {
|
||||||
|
return false; // No suitable region input found
|
||||||
|
}
|
||||||
|
} else if (req() == 4) {
|
||||||
|
// Shape 2: Check if two control inputs map to the same value of the unique phi
|
||||||
|
// user and treat these as if they would come from another region (shape (1)).
|
||||||
|
PhiNode* phi = has_unique_phi();
|
||||||
|
if (phi == NULL) {
|
||||||
|
return false; // No unique phi user
|
||||||
|
}
|
||||||
|
if (phi->in(idx1) != phi->in(idx2)) {
|
||||||
|
idx2 = 3;
|
||||||
|
if (phi->in(idx1) != phi->in(idx2)) {
|
||||||
|
idx1 = 2;
|
||||||
|
if (phi->in(idx1) != phi->in(idx2)) {
|
||||||
|
return false; // No equal phi inputs found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(phi->in(idx1) == phi->in(idx2), "must be"); // Region is merging same value
|
||||||
|
region = this;
|
||||||
|
}
|
||||||
|
if (region == NULL || region->in(idx1) == NULL || region->in(idx2) == NULL) {
|
||||||
|
return false; // Region does not merge two control inputs
|
||||||
|
}
|
||||||
|
// At this point we know that region->in(idx1) and region->(idx2) map to the same
|
||||||
|
// value and control flow. Now search for ifs that feed into these region inputs.
|
||||||
|
ProjNode* proj1 = region->in(idx1)->isa_Proj();
|
||||||
|
ProjNode* proj2 = region->in(idx2)->isa_Proj();
|
||||||
|
if (proj1 == NULL || proj1->outcnt() != 1 ||
|
||||||
|
proj2 == NULL || proj2->outcnt() != 1) {
|
||||||
|
return false; // No projection inputs with region as unique user found
|
||||||
|
}
|
||||||
|
assert(proj1 != proj2, "should be different projections");
|
||||||
|
IfNode* iff1 = proj1->in(0)->isa_If();
|
||||||
|
IfNode* iff2 = proj2->in(0)->isa_If();
|
||||||
|
if (iff1 == NULL || iff1->outcnt() != 2 ||
|
||||||
|
iff2 == NULL || iff2->outcnt() != 2) {
|
||||||
|
return false; // No ifs found
|
||||||
|
}
|
||||||
|
if (iff1 == iff2) {
|
||||||
|
igvn->add_users_to_worklist(iff1); // Make sure dead if is eliminated
|
||||||
|
igvn->replace_input_of(region, idx1, iff1->in(0));
|
||||||
|
igvn->replace_input_of(region, idx2, igvn->C->top());
|
||||||
|
return (region == this); // Remove useless if (both projections map to the same control/value)
|
||||||
|
}
|
||||||
|
BoolNode* bol1 = iff1->in(1)->isa_Bool();
|
||||||
|
BoolNode* bol2 = iff2->in(1)->isa_Bool();
|
||||||
|
if (bol1 == NULL || bol2 == NULL) {
|
||||||
|
return false; // No bool inputs found
|
||||||
|
}
|
||||||
|
Node* cmp1 = bol1->in(1);
|
||||||
|
Node* cmp2 = bol2->in(1);
|
||||||
|
bool commute = false;
|
||||||
|
if (!cmp1->is_Cmp() || !cmp2->is_Cmp()) {
|
||||||
|
return false; // No comparison
|
||||||
|
} else if (cmp1->Opcode() == Op_CmpF || cmp1->Opcode() == Op_CmpD ||
|
||||||
|
cmp2->Opcode() == Op_CmpF || cmp2->Opcode() == Op_CmpD ||
|
||||||
|
cmp1->Opcode() == Op_CmpP || cmp1->Opcode() == Op_CmpN ||
|
||||||
|
cmp2->Opcode() == Op_CmpP || cmp2->Opcode() == Op_CmpN) {
|
||||||
|
// Floats and pointers don't exactly obey trichotomy. To be on the safe side, don't transform their tests.
|
||||||
|
return false;
|
||||||
|
} else if (cmp1 != cmp2) {
|
||||||
|
if (cmp1->in(1) == cmp2->in(2) &&
|
||||||
|
cmp1->in(2) == cmp2->in(1)) {
|
||||||
|
commute = true; // Same but swapped inputs, commute the test
|
||||||
|
} else {
|
||||||
|
return false; // Ifs are not comparing the same values
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proj1 = proj1->other_if_proj();
|
||||||
|
proj2 = proj2->other_if_proj();
|
||||||
|
if (!((proj1->unique_ctrl_out() == iff2 &&
|
||||||
|
proj2->unique_ctrl_out() == this) ||
|
||||||
|
(proj2->unique_ctrl_out() == iff1 &&
|
||||||
|
proj1->unique_ctrl_out() == this))) {
|
||||||
|
return false; // Ifs are not connected through other projs
|
||||||
|
}
|
||||||
|
// Found 'iff -> proj -> iff -> proj -> this' shape where all other projs are merged
|
||||||
|
// through 'region' and map to the same value. Merge the boolean tests and replace
|
||||||
|
// the ifs by a single comparison.
|
||||||
|
BoolTest test1 = (proj1->_con == 1) ? bol1->_test : bol1->_test.negate();
|
||||||
|
BoolTest test2 = (proj2->_con == 1) ? bol2->_test : bol2->_test.negate();
|
||||||
|
test1 = commute ? test1.commute() : test1;
|
||||||
|
// After possibly commuting test1, if we can merge test1 & test2, then proj2/iff2/bol2 are the nodes to refine.
|
||||||
|
BoolTest::mask res = test1.merge(test2);
|
||||||
|
if (res == BoolTest::illegal) {
|
||||||
|
return false; // Unable to merge tests
|
||||||
|
}
|
||||||
|
// Adjust iff1 to always pass (only iff2 will remain)
|
||||||
|
igvn->replace_input_of(iff1, 1, igvn->intcon(proj1->_con));
|
||||||
|
if (res == BoolTest::never) {
|
||||||
|
// Merged test is always false, adjust iff2 to always fail
|
||||||
|
igvn->replace_input_of(iff2, 1, igvn->intcon(1 - proj2->_con));
|
||||||
|
} else {
|
||||||
|
// Replace bool input of iff2 with merged test
|
||||||
|
BoolNode* new_bol = new BoolNode(bol2->in(1), res);
|
||||||
|
igvn->replace_input_of(iff2, 1, igvn->transform((proj2->_con == 1) ? new_bol : new_bol->negate(igvn)));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const RegMask &RegionNode::out_RegMask() const {
|
const RegMask &RegionNode::out_RegMask() const {
|
||||||
return RegMask::Empty;
|
return RegMask::Empty;
|
||||||
|
|
|
@ -96,6 +96,7 @@ public:
|
||||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||||
virtual const RegMask &out_RegMask() const;
|
virtual const RegMask &out_RegMask() const;
|
||||||
bool try_clean_mem_phi(PhaseGVN *phase);
|
bool try_clean_mem_phi(PhaseGVN *phase);
|
||||||
|
bool optimize_trichotomy(PhaseIterGVN* igvn);
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------JProjNode--------------------------------------
|
//------------------------------JProjNode--------------------------------------
|
||||||
|
|
|
@ -899,6 +899,13 @@ Node* Node::uncast() const {
|
||||||
return (Node*) this;
|
return (Node*) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Node::eqv_uncast(const Node* n) const {
|
||||||
|
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
|
||||||
|
Node* obj1 = bs->step_over_gc_barrier(const_cast<Node*>(this));
|
||||||
|
Node* obj2 = bs->step_over_gc_barrier(const_cast<Node*>(n));
|
||||||
|
return (obj1->uncast() == obj2->uncast());
|
||||||
|
}
|
||||||
|
|
||||||
// Find out of current node that matches opcode.
|
// Find out of current node that matches opcode.
|
||||||
Node* Node::find_out_with(int opcode) {
|
Node* Node::find_out_with(int opcode) {
|
||||||
for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
|
for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
|
||||||
|
|
|
@ -457,10 +457,9 @@ protected:
|
||||||
|
|
||||||
// Strip away casting. (It is depth-limited.)
|
// Strip away casting. (It is depth-limited.)
|
||||||
Node* uncast() const;
|
Node* uncast() const;
|
||||||
// Return whether two Nodes are equivalent, after stripping casting.
|
// Return whether two Nodes are equivalent, after stripping casting
|
||||||
bool eqv_uncast(const Node* n) const {
|
// and GC barriers.
|
||||||
return (this->uncast() == n->uncast());
|
bool eqv_uncast(const Node* n) const;
|
||||||
}
|
|
||||||
|
|
||||||
// Find out of current node that matches opcode.
|
// Find out of current node that matches opcode.
|
||||||
Node* find_out_with(int opcode);
|
Node* find_out_with(int opcode);
|
||||||
|
|
|
@ -1252,6 +1252,24 @@ void BoolTest::dump_on(outputStream *st) const {
|
||||||
st->print("%s", msg[_test]);
|
st->print("%s", msg[_test]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the logical AND of two tests (or 'never' if both tests can never be true).
|
||||||
|
// For example, a test for 'le' followed by a test for 'lt' is equivalent with 'lt'.
|
||||||
|
BoolTest::mask BoolTest::merge(BoolTest other) const {
|
||||||
|
const mask res[illegal+1][illegal+1] = {
|
||||||
|
// eq, gt, of, lt, ne, le, nof, ge, never, illegal
|
||||||
|
{eq, never, illegal, never, never, eq, illegal, eq, never, illegal}, // eq
|
||||||
|
{never, gt, illegal, never, gt, never, illegal, gt, never, illegal}, // gt
|
||||||
|
{illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, never, illegal}, // of
|
||||||
|
{never, never, illegal, lt, lt, lt, illegal, never, never, illegal}, // lt
|
||||||
|
{never, gt, illegal, lt, ne, lt, illegal, gt, never, illegal}, // ne
|
||||||
|
{eq, never, illegal, lt, lt, le, illegal, eq, never, illegal}, // le
|
||||||
|
{illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, never, illegal}, // nof
|
||||||
|
{eq, gt, illegal, never, gt, eq, illegal, ge, never, illegal}, // ge
|
||||||
|
{never, never, never, never, never, never, never, never, never, illegal}, // never
|
||||||
|
{illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal}}; // illegal
|
||||||
|
return res[_test][other._test];
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
uint BoolNode::hash() const { return (Node::hash() << 3)|(_test._test+1); }
|
uint BoolNode::hash() const { return (Node::hash() << 3)|(_test._test+1); }
|
||||||
uint BoolNode::size_of() const { return sizeof(BoolNode); }
|
uint BoolNode::size_of() const { return sizeof(BoolNode); }
|
||||||
|
|
|
@ -280,7 +280,7 @@ public:
|
||||||
// We pick the values as 3 bits; the low order 2 bits we compare against the
|
// We pick the values as 3 bits; the low order 2 bits we compare against the
|
||||||
// condition codes, the high bit flips the sense of the result.
|
// condition codes, the high bit flips the sense of the result.
|
||||||
struct BoolTest {
|
struct BoolTest {
|
||||||
enum mask { eq = 0, ne = 4, le = 5, ge = 7, lt = 3, gt = 1, overflow = 2, no_overflow = 6, illegal = 8 };
|
enum mask { eq = 0, ne = 4, le = 5, ge = 7, lt = 3, gt = 1, overflow = 2, no_overflow = 6, never = 8, illegal = 9 };
|
||||||
mask _test;
|
mask _test;
|
||||||
BoolTest( mask btm ) : _test(btm) {}
|
BoolTest( mask btm ) : _test(btm) {}
|
||||||
const Type *cc2logical( const Type *CC ) const;
|
const Type *cc2logical( const Type *CC ) const;
|
||||||
|
@ -293,6 +293,7 @@ struct BoolTest {
|
||||||
bool is_less( ) const { return _test == BoolTest::lt || _test == BoolTest::le; }
|
bool is_less( ) const { return _test == BoolTest::lt || _test == BoolTest::le; }
|
||||||
bool is_greater( ) const { return _test == BoolTest::gt || _test == BoolTest::ge; }
|
bool is_greater( ) const { return _test == BoolTest::gt || _test == BoolTest::ge; }
|
||||||
void dump_on(outputStream *st) const;
|
void dump_on(outputStream *st) const;
|
||||||
|
mask merge(BoolTest other) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------BoolNode---------------------------------------
|
//------------------------------BoolNode---------------------------------------
|
||||||
|
|
|
@ -3736,8 +3736,8 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i
|
||||||
{
|
{
|
||||||
memset(info, 0, info_size);
|
memset(info, 0, info_size);
|
||||||
|
|
||||||
info->jvm_version = Abstract_VM_Version::jvm_version();
|
info->jvm_version = VM_Version::jvm_version();
|
||||||
info->patch_version = Abstract_VM_Version::vm_patch_version();
|
info->patch_version = VM_Version::vm_patch_version();
|
||||||
|
|
||||||
// when we add a new capability in the jvm_version_info struct, we should also
|
// when we add a new capability in the jvm_version_info struct, we should also
|
||||||
// consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat
|
// consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat
|
||||||
|
|
|
@ -919,7 +919,7 @@ JvmtiEnv::GetAllThreads(jint* threads_count_ptr, jthread** threads_ptr) {
|
||||||
thread_objs = NEW_RESOURCE_ARRAY(Handle, nthreads);
|
thread_objs = NEW_RESOURCE_ARRAY(Handle, nthreads);
|
||||||
NULL_CHECK(thread_objs, JVMTI_ERROR_OUT_OF_MEMORY);
|
NULL_CHECK(thread_objs, JVMTI_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
for (int i=0; i < nthreads; i++) {
|
for (int i = 0; i < nthreads; i++) {
|
||||||
thread_objs[i] = Handle(tle.get_threadObj(i));
|
thread_objs[i] = Handle(tle.get_threadObj(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1144,16 +1144,14 @@ JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) {
|
||||||
Handle context_class_loader;
|
Handle context_class_loader;
|
||||||
bool is_daemon;
|
bool is_daemon;
|
||||||
|
|
||||||
{ MutexLocker mu(Threads_lock);
|
name = Handle(current_thread, java_lang_Thread::name(thread_obj()));
|
||||||
|
priority = java_lang_Thread::priority(thread_obj());
|
||||||
|
thread_group = Handle(current_thread, java_lang_Thread::threadGroup(thread_obj()));
|
||||||
|
is_daemon = java_lang_Thread::is_daemon(thread_obj());
|
||||||
|
|
||||||
name = Handle(current_thread, java_lang_Thread::name(thread_obj()));
|
oop loader = java_lang_Thread::context_class_loader(thread_obj());
|
||||||
priority = java_lang_Thread::priority(thread_obj());
|
context_class_loader = Handle(current_thread, loader);
|
||||||
thread_group = Handle(current_thread, java_lang_Thread::threadGroup(thread_obj()));
|
|
||||||
is_daemon = java_lang_Thread::is_daemon(thread_obj());
|
|
||||||
|
|
||||||
oop loader = java_lang_Thread::context_class_loader(thread_obj());
|
|
||||||
context_class_loader = Handle(current_thread, loader);
|
|
||||||
}
|
|
||||||
{ const char *n;
|
{ const char *n;
|
||||||
|
|
||||||
if (name() != NULL) {
|
if (name() != NULL) {
|
||||||
|
@ -1402,13 +1400,10 @@ JvmtiEnv::GetThreadGroupInfo(jthreadGroup group, jvmtiThreadGroupInfo* info_ptr)
|
||||||
bool is_daemon;
|
bool is_daemon;
|
||||||
ThreadPriority max_priority;
|
ThreadPriority max_priority;
|
||||||
|
|
||||||
{ MutexLocker mu(Threads_lock);
|
name = java_lang_ThreadGroup::name(group_obj());
|
||||||
|
parent_group = Handle(current_thread, java_lang_ThreadGroup::parent(group_obj()));
|
||||||
name = java_lang_ThreadGroup::name(group_obj());
|
is_daemon = java_lang_ThreadGroup::is_daemon(group_obj());
|
||||||
parent_group = Handle(current_thread, java_lang_ThreadGroup::parent(group_obj()));
|
max_priority = java_lang_ThreadGroup::maxPriority(group_obj());
|
||||||
is_daemon = java_lang_ThreadGroup::is_daemon(group_obj());
|
|
||||||
max_priority = java_lang_ThreadGroup::maxPriority(group_obj());
|
|
||||||
}
|
|
||||||
|
|
||||||
info_ptr->is_daemon = is_daemon;
|
info_ptr->is_daemon = is_daemon;
|
||||||
info_ptr->max_priority = max_priority;
|
info_ptr->max_priority = max_priority;
|
||||||
|
@ -1448,7 +1443,7 @@ JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jth
|
||||||
Handle group_hdl(current_thread, group_obj);
|
Handle group_hdl(current_thread, group_obj);
|
||||||
|
|
||||||
{ // Cannot allow thread or group counts to change.
|
{ // Cannot allow thread or group counts to change.
|
||||||
MutexLocker mu(Threads_lock);
|
ObjectLocker ol(group_hdl, current_thread);
|
||||||
|
|
||||||
nthreads = java_lang_ThreadGroup::nthreads(group_hdl());
|
nthreads = java_lang_ThreadGroup::nthreads(group_hdl());
|
||||||
ngroups = java_lang_ThreadGroup::ngroups(group_hdl());
|
ngroups = java_lang_ThreadGroup::ngroups(group_hdl());
|
||||||
|
@ -1458,7 +1453,7 @@ JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jth
|
||||||
objArrayOop threads = java_lang_ThreadGroup::threads(group_hdl());
|
objArrayOop threads = java_lang_ThreadGroup::threads(group_hdl());
|
||||||
assert(nthreads <= threads->length(), "too many threads");
|
assert(nthreads <= threads->length(), "too many threads");
|
||||||
thread_objs = NEW_RESOURCE_ARRAY(Handle,nthreads);
|
thread_objs = NEW_RESOURCE_ARRAY(Handle,nthreads);
|
||||||
for (int i=0, j=0; i<nthreads; i++) {
|
for (int i = 0, j = 0; i < nthreads; i++) {
|
||||||
oop thread_obj = threads->obj_at(i);
|
oop thread_obj = threads->obj_at(i);
|
||||||
assert(thread_obj != NULL, "thread_obj is NULL");
|
assert(thread_obj != NULL, "thread_obj is NULL");
|
||||||
JavaThread *java_thread = NULL;
|
JavaThread *java_thread = NULL;
|
||||||
|
@ -1490,15 +1485,14 @@ JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jth
|
||||||
objArrayOop groups = java_lang_ThreadGroup::groups(group_hdl());
|
objArrayOop groups = java_lang_ThreadGroup::groups(group_hdl());
|
||||||
assert(ngroups <= groups->length(), "too many groups");
|
assert(ngroups <= groups->length(), "too many groups");
|
||||||
group_objs = NEW_RESOURCE_ARRAY(Handle,ngroups);
|
group_objs = NEW_RESOURCE_ARRAY(Handle,ngroups);
|
||||||
for (int i=0; i<ngroups; i++) {
|
for (int i = 0; i < ngroups; i++) {
|
||||||
oop group_obj = groups->obj_at(i);
|
oop group_obj = groups->obj_at(i);
|
||||||
assert(group_obj != NULL, "group_obj != NULL");
|
assert(group_obj != NULL, "group_obj != NULL");
|
||||||
group_objs[i] = Handle(current_thread, group_obj);
|
group_objs[i] = Handle(current_thread, group_obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // ThreadGroup unlocked here
|
||||||
|
|
||||||
// have to make global handles outside of Threads_lock
|
|
||||||
*group_count_ptr = ngroups;
|
*group_count_ptr = ngroups;
|
||||||
*thread_count_ptr = nthreads;
|
*thread_count_ptr = nthreads;
|
||||||
*threads_ptr = new_jthreadArray(nthreads, thread_objs);
|
*threads_ptr = new_jthreadArray(nthreads, thread_objs);
|
||||||
|
@ -3246,7 +3240,7 @@ JvmtiEnv::DestroyRawMonitor(JvmtiRawMonitor * rmonitor) {
|
||||||
// objects that are locked.
|
// objects that are locked.
|
||||||
int r;
|
int r;
|
||||||
intptr_t recursion = rmonitor->recursions();
|
intptr_t recursion = rmonitor->recursions();
|
||||||
for (intptr_t i=0; i <= recursion; i++) {
|
for (intptr_t i = 0; i <= recursion; i++) {
|
||||||
r = rmonitor->raw_exit(thread);
|
r = rmonitor->raw_exit(thread);
|
||||||
assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked");
|
assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked");
|
||||||
if (r != ObjectMonitor::OM_OK) { // robustness
|
if (r != ObjectMonitor::OM_OK) { // robustness
|
||||||
|
@ -3676,7 +3670,7 @@ JvmtiEnv::GetSystemProperties(jint* count_ptr, char*** property_ptr) {
|
||||||
strcpy(*tmp_value, key);
|
strcpy(*tmp_value, key);
|
||||||
} else {
|
} else {
|
||||||
// clean up previously allocated memory.
|
// clean up previously allocated memory.
|
||||||
for (int j=0; j<readable_count; j++) {
|
for (int j = 0; j < readable_count; j++) {
|
||||||
Deallocate((unsigned char*)*property_ptr+j);
|
Deallocate((unsigned char*)*property_ptr+j);
|
||||||
}
|
}
|
||||||
Deallocate((unsigned char*)property_ptr);
|
Deallocate((unsigned char*)property_ptr);
|
||||||
|
|
|
@ -1044,7 +1044,7 @@ class JvmtiObjectAllocEventMark : public JvmtiClassEventMark {
|
||||||
public:
|
public:
|
||||||
JvmtiObjectAllocEventMark(JavaThread *thread, oop obj) : JvmtiClassEventMark(thread, oop_to_klass(obj)) {
|
JvmtiObjectAllocEventMark(JavaThread *thread, oop obj) : JvmtiClassEventMark(thread, oop_to_klass(obj)) {
|
||||||
_jobj = (jobject)to_jobject(obj);
|
_jobj = (jobject)to_jobject(obj);
|
||||||
_size = obj->size() * wordSize;
|
_size = Universe::heap()->obj_size(obj) * wordSize;
|
||||||
};
|
};
|
||||||
jobject jni_jobject() { return _jobj; }
|
jobject jni_jobject() { return _jobj; }
|
||||||
jlong size() { return _size; }
|
jlong size() { return _size; }
|
||||||
|
|
|
@ -105,7 +105,7 @@ class JvmtiTagHashmapEntry : public CHeapObj<mtInternal> {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool equals(oop object) {
|
inline bool equals(oop object) {
|
||||||
return object == object_peek();
|
return oopDesc::equals(object, object_peek());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JvmtiTagHashmapEntry* next() const { return _next; }
|
inline JvmtiTagHashmapEntry* next() const { return _next; }
|
||||||
|
@ -186,6 +186,7 @@ class JvmtiTagHashmap : public CHeapObj<mtInternal> {
|
||||||
|
|
||||||
// shift right to get better distribution (as these bits will be zero
|
// shift right to get better distribution (as these bits will be zero
|
||||||
// with aligned addresses)
|
// with aligned addresses)
|
||||||
|
key = Access<>::resolve(key);
|
||||||
unsigned int addr = (unsigned int)(cast_from_oop<intptr_t>(key));
|
unsigned int addr = (unsigned int)(cast_from_oop<intptr_t>(key));
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
return (addr >> 3) % size;
|
return (addr >> 3) % size;
|
||||||
|
|
|
@ -106,6 +106,9 @@ char* Arguments::SharedArchivePath = NULL;
|
||||||
AgentLibraryList Arguments::_libraryList;
|
AgentLibraryList Arguments::_libraryList;
|
||||||
AgentLibraryList Arguments::_agentList;
|
AgentLibraryList Arguments::_agentList;
|
||||||
|
|
||||||
|
// These are not set by the JDK's built-in launchers, but they can be set by
|
||||||
|
// programs that embed the JVM using JNI_CreateJavaVM. See comments around
|
||||||
|
// JavaVMOption in jni.h.
|
||||||
abort_hook_t Arguments::_abort_hook = NULL;
|
abort_hook_t Arguments::_abort_hook = NULL;
|
||||||
exit_hook_t Arguments::_exit_hook = NULL;
|
exit_hook_t Arguments::_exit_hook = NULL;
|
||||||
vfprintf_hook_t Arguments::_vfprintf_hook = NULL;
|
vfprintf_hook_t Arguments::_vfprintf_hook = NULL;
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
// Arguments parses the command line and recognizes options
|
// Arguments parses the command line and recognizes options
|
||||||
|
|
||||||
// Invocation API hook typedefs (these should really be defined in jni.hpp)
|
// Invocation API hook typedefs (these should really be defined in jni.h)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
typedef void (JNICALL *abort_hook_t)(void);
|
typedef void (JNICALL *abort_hook_t)(void);
|
||||||
typedef void (JNICALL *exit_hook_t)(jint code);
|
typedef void (JNICALL *exit_hook_t)(jint code);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue