Merge
This commit is contained in:
commit
3e85467bc6
.hgtags
make
src/hotspot
cpu
aarch64/gc/shared
arm
ppc/gc/shared
s390/gc/shared
sparc/gc/shared
x86
c1_MacroAssembler_x86.cpp
gc/shared
macroAssembler_x86.cppmacroAssembler_x86.hppsharedRuntime_x86_64.cppstubGenerator_x86_64.cppstubRoutines_x86.hppstubRoutines_x86_64.cppx86_32.adx86_64.adzero/gc/shared
share
aot
ci
classfile
classLoader.cppclassLoaderData.cppclassLoaderData.hppclassLoaderDataGraph.cppsystemDictionary.cppsystemDictionary.hppverificationType.cpp
code
gc
cms
epsilon
g1
g1Arguments.cppg1FullGCAdjustTask.cppg1FullGCMarker.cppg1FullGCOopClosures.inline.hppg1HeapVerifier.cppg1OopClosures.cppg1OopClosures.hppg1ParScanThreadState.cppg1RootClosures.cppg1SharedClosures.hpp
parallel
serial
shared
z
interpreter
jfr/leakprofiler
jvmci
memory
oops
opto
prims
runtime
1
.hgtags
1
.hgtags
@ -518,3 +518,4 @@ f0f5d23449d31f1b3580c8a73313918cafeaefd7 jdk-12+11
|
||||
8897e41b327c0a5601c6ba2bba5d07f15a3ffc91 jdk-12+14
|
||||
6f04692c7d5137ee34a6bd94c0c8a6c9219cb127 jdk-12+14
|
||||
f8626bcc169813a4b2a15880386b952719d1d6d1 jdk-12+15
|
||||
199658d1ef860cdc17055b4fd3e94b057f292fe9 jdk-12+16
|
||||
|
@ -46,6 +46,7 @@ $(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
|
||||
SETUP := GENERATE_OLDBYTECODE, \
|
||||
SRC := $(BUILD_TOOLS_SRC_DIRS), \
|
||||
EXCLUDES := \
|
||||
build/tools/classlist \
|
||||
build/tools/deps \
|
||||
build/tools/docs \
|
||||
build/tools/jigsaw \
|
||||
|
@ -31,15 +31,17 @@ default: all
|
||||
|
||||
include $(SPEC)
|
||||
include MakeBase.gmk
|
||||
include JarArchive.gmk
|
||||
include SetupJavaCompilers.gmk
|
||||
|
||||
################################################################################
|
||||
# Create a jar with our generator class. Using a jar is intentional since it
|
||||
# will load more classes
|
||||
|
||||
$(eval $(call SetupJarArchive, CLASSLIST_JAR, \
|
||||
SRCS := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
|
||||
$(eval $(call SetupJavaCompilation, CLASSLIST_JAR, \
|
||||
SETUP := GENERATE_JDKBYTECODE, \
|
||||
SRC := $(TOPDIR)/make/jdk/src/classes, \
|
||||
INCLUDES := build/tools/classlist, \
|
||||
BIN := $(BUILDTOOLS_OUTPUTDIR)/classlist_classes, \
|
||||
JAR := $(SUPPORT_OUTPUTDIR)/classlist.jar, \
|
||||
))
|
||||
|
||||
|
@ -656,8 +656,11 @@ dups = \
|
||||
|
||||
# String equals
|
||||
equals = \
|
||||
$(and $(findstring $(strip $1),$(strip $2)),\
|
||||
$(findstring $(strip $2),$(strip $1)))
|
||||
$(if $(strip $1)$(strip $2),$(strip \
|
||||
$(and $(findstring $(strip $1),$(strip $2)),\
|
||||
$(findstring $(strip $2),$(strip $1)))), \
|
||||
true \
|
||||
)
|
||||
|
||||
# Remove a whole list of prefixes
|
||||
# $1 - List of prefixes
|
||||
|
@ -67,7 +67,6 @@ endef
|
||||
# Param 2: Working directory
|
||||
# Param 3: Source file
|
||||
# Param 4: Compile command
|
||||
# Param 5: Object name
|
||||
################################################################################
|
||||
define WriteCompileCommandsFragment
|
||||
$(call LogInfo, Creating compile commands fragment for $(notdir $3))
|
||||
@ -76,8 +75,7 @@ define WriteCompileCommandsFragment
|
||||
"directory": "$(strip $2)"$(COMMA) \
|
||||
"file": "$(strip $3)"$(COMMA) \
|
||||
"command": "$(strip $(subst $(DQUOTE),\$(DQUOTE),$(subst \,\\,\
|
||||
$(subst $(FIXPATH),,$4))))"$(COMMA) \
|
||||
"output": "$(strip $5)" \
|
||||
$(subst $(FIXPATH),,$4))))" \
|
||||
}$(COMMA), \
|
||||
$1)
|
||||
endef
|
||||
@ -331,7 +329,7 @@ define SetupCompileNativeFileBody
|
||||
|
||||
$$($1_OBJ_JSON): $$($1_OBJ_DEPS)
|
||||
$$(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)
|
||||
$$(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)
|
||||
$$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$<, \
|
||||
$$($1_PCH_COMMAND) $$< -o $$($1_PCH_FILE), $$($1_PCH_FILE))
|
||||
$$($1_PCH_COMMAND) $$< -o $$($1_PCH_FILE))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -66,6 +66,15 @@ public class HelloClasslist {
|
||||
Stream.of(helloWorld.split(","))
|
||||
.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(
|
||||
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; }
|
||||
// Override Abstract_VM_Version implementation
|
||||
static bool use_biased_locking();
|
||||
static const char* vm_info_string();
|
||||
|
||||
static bool has_vfp() { return (_features & vfp_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;
|
||||
}
|
||||
|
||||
#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_Runtime1.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
#include "gc/shared/barrierSetAssembler.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "interpreter/interpreter.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
|
||||
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 "gc/shared/barrierSet.hpp"
|
||||
#include "gc/shared/barrierSetAssembler.hpp"
|
||||
#include "gc/shared/barrierSetNMethod.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "interpreter/interp_masm.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);
|
||||
#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);
|
||||
|
||||
virtual void barrier_stubs_init() {}
|
||||
|
||||
virtual void nmethod_entry_barrier(MacroAssembler* masm);
|
||||
};
|
||||
|
||||
#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
|
||||
|
||||
// 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
|
||||
// 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
|
||||
|
||||
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
|
||||
|
@ -1588,7 +1588,7 @@ public:
|
||||
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.
|
||||
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';
|
||||
// if 'is_large' is set, do not try to produce short loop
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "code/vtableStubs.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "gc/shared/gcLocker.hpp"
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
#include "gc/shared/barrierSetAssembler.hpp"
|
||||
#include "interpreter/interpreter.hpp"
|
||||
#include "logging/log.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
|
||||
__ 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.
|
||||
int frame_complete = ((intptr_t)__ pc()) - start;
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "ci/ciUtilities.hpp"
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
#include "gc/shared/barrierSetAssembler.hpp"
|
||||
#include "gc/shared/barrierSetNMethod.hpp"
|
||||
#include "interpreter/interpreter.hpp"
|
||||
#include "nativeInst_x86.hpp"
|
||||
#include "oops/instanceOop.hpp"
|
||||
@ -5194,6 +5195,83 @@ address generate_cipherBlockChaining_decryptVectorAESCrypt() {
|
||||
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:
|
||||
*
|
||||
@ -5831,6 +5909,11 @@ address generate_cipherBlockChaining_decryptVectorAESCrypt() {
|
||||
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
|
||||
&StubRoutines::_safefetchN_fault_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
|
||||
if (UseMultiplyToLenIntrinsic) {
|
||||
StubRoutines::_multiplyToLen = generate_multiplyToLen();
|
||||
|
@ -55,8 +55,14 @@ class x86 {
|
||||
static address _double_sign_mask;
|
||||
static address _double_sign_flip;
|
||||
|
||||
static address _method_entry_barrier;
|
||||
|
||||
public:
|
||||
|
||||
static address method_entry_barrier() {
|
||||
return _method_entry_barrier;
|
||||
}
|
||||
|
||||
static address 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::_double_sign_mask = 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 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());
|
||||
|
||||
|
@ -890,6 +890,15 @@ void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
|
||||
st->print("# stack alignment check");
|
||||
#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();
|
||||
}
|
||||
#endif
|
||||
@ -901,7 +910,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
int framesize = C->frame_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());
|
||||
|
||||
|
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;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
const char pathSep = ';';
|
||||
#else
|
||||
const char pathSep = ':';
|
||||
#endif
|
||||
|
||||
// Scan the AOTLibrary option.
|
||||
if (AOTLibrary != NULL) {
|
||||
const int len = (int)strlen(AOTLibrary);
|
||||
@ -147,7 +153,7 @@ void AOTLoader::initialize() {
|
||||
char* end = cp + len;
|
||||
while (cp < end) {
|
||||
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++;
|
||||
load_library(name, true);
|
||||
|
@ -77,7 +77,7 @@
|
||||
|
||||
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)
|
||||
#undef WK_KLASS_DEFN
|
||||
|
||||
|
@ -82,7 +82,7 @@ private:
|
||||
// Distinguished instances of certain ciObjects..
|
||||
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)
|
||||
#undef WK_KLASS_DECL
|
||||
|
||||
@ -374,7 +374,7 @@ public:
|
||||
|
||||
|
||||
// Access to certain well known ciObjects.
|
||||
#define WK_KLASS_FUNC(name, ignore_s, ignore_o) \
|
||||
#define WK_KLASS_FUNC(name, ignore_s) \
|
||||
ciInstanceKlass* name() { \
|
||||
return _##name;\
|
||||
}
|
||||
|
@ -157,8 +157,8 @@ void ciObjectFactory::init_shared_objects() {
|
||||
ciEnv::_null_object_instance = new (_arena) ciNullObject();
|
||||
init_ident_of(ciEnv::_null_object_instance);
|
||||
|
||||
#define WK_KLASS_DEFN(name, ignore_s, opt) \
|
||||
if (SystemDictionary::name() != NULL) \
|
||||
#define WK_KLASS_DEFN(name, ignore_s) \
|
||||
if (SystemDictionary::name##_is_loaded()) \
|
||||
ciEnv::_##name = get_metadata(SystemDictionary::name())->as_instance_klass();
|
||||
|
||||
WK_KLASSES_DO(WK_KLASS_DEFN)
|
||||
|
@ -163,7 +163,7 @@ static const char* get_jimage_version_string() {
|
||||
static char version_string[10] = "";
|
||||
if (version_string[0] == '\0') {
|
||||
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;
|
||||
}
|
||||
|
@ -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.
|
||||
// The null-class-loader should always be kept alive.
|
||||
_keep_alive((is_unsafe_anonymous || h_class_loader.is_null()) ? 1 : 0),
|
||||
_claimed(0),
|
||||
_claim(0),
|
||||
_handles(),
|
||||
_klasses(NULL), _packages(NULL), _modules(NULL), _unnamed_module(NULL), _dictionary(NULL),
|
||||
_jmethod_ids(NULL),
|
||||
@ -268,12 +268,17 @@ bool ClassLoaderData::ChunkedHandleList::owner_of(oop* oop_handle) {
|
||||
}
|
||||
#endif // PRODUCT
|
||||
|
||||
bool ClassLoaderData::claim() {
|
||||
if (_claimed == 1) {
|
||||
return false;
|
||||
bool ClassLoaderData::try_claim(int claim) {
|
||||
for (;;) {
|
||||
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
|
||||
@ -295,8 +300,8 @@ void ClassLoaderData::dec_keep_alive() {
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoaderData::oops_do(OopClosure* f, bool must_claim, bool clear_mod_oops) {
|
||||
if (must_claim && !claim()) {
|
||||
void ClassLoaderData::oops_do(OopClosure* f, int claim_value, bool clear_mod_oops) {
|
||||
if (claim_value != ClassLoaderData::_claim_none && !try_claim(claim_value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -128,9 +128,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
// loader. _keep_alive does not need to be volatile or
|
||||
// atomic since there is one unique CLD per unsafe anonymous class.
|
||||
|
||||
volatile int _claimed; // true if claimed, for example during GC traces.
|
||||
// To avoid applying oop closure more than once.
|
||||
// Has to be an int because we cas it.
|
||||
volatile int _claim; // non-zero if claimed, for example during GC traces.
|
||||
// To avoid applying oop closure more than once.
|
||||
ChunkedHandleList _handles; // Handles to constant pool arrays, Modules, etc, which
|
||||
// have the same life cycle of the corresponding ClassLoader.
|
||||
|
||||
@ -200,11 +199,22 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
Dictionary* create_dictionary();
|
||||
|
||||
void initialize_name(Handle class_loader);
|
||||
|
||||
public:
|
||||
// GC interface.
|
||||
void clear_claimed() { _claimed = 0; }
|
||||
bool claimed() const { return _claimed == 1; }
|
||||
bool claim();
|
||||
|
||||
// The "claim" is typically used to check if oops_do needs to be applied on
|
||||
// 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
|
||||
// contexts.
|
||||
@ -264,7 +274,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
|
||||
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);
|
||||
Klass* klasses() { return _klasses; }
|
||||
|
@ -48,7 +48,7 @@ volatile size_t ClassLoaderDataGraph::_num_instance_classes = 0;
|
||||
|
||||
void ClassLoaderDataGraph::clear_claimed_marks() {
|
||||
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) {
|
||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
||||
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
|
||||
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
|
||||
cl->do_cld(cld);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// (CMS doesn't purge right away).
|
||||
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) {
|
||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
||||
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
|
||||
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) {
|
||||
CLDClosure* closure = cld->keep_alive() ? strong : weak;
|
||||
if (closure != NULL) {
|
||||
@ -258,7 +258,7 @@ void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
|
||||
}
|
||||
|
||||
void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) {
|
||||
assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
|
||||
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
|
||||
if (ClassUnloading) {
|
||||
roots_cld_do(cl, NULL);
|
||||
} else {
|
||||
|
@ -1963,41 +1963,30 @@ void SystemDictionary::initialize(TRAPS) {
|
||||
|
||||
// Compact table of directions on the initialization of klasses:
|
||||
static const short wk_init_info[] = {
|
||||
#define WK_KLASS_INIT_INFO(name, symbol, option) \
|
||||
( ((int)vmSymbols::VM_SYMBOL_ENUM_NAME(symbol) \
|
||||
<< SystemDictionary::CEIL_LG_OPTION_LIMIT) \
|
||||
| (int)SystemDictionary::option ),
|
||||
#define WK_KLASS_INIT_INFO(name, symbol) \
|
||||
((short)vmSymbols::VM_SYMBOL_ENUM_NAME(symbol)),
|
||||
|
||||
WK_KLASSES_DO(WK_KLASS_INIT_INFO)
|
||||
#undef WK_KLASS_INIT_INFO
|
||||
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");
|
||||
int info = wk_init_info[id - FIRST_WKID];
|
||||
int sid = (info >> CEIL_LG_OPTION_LIMIT);
|
||||
int sid = wk_init_info[id - FIRST_WKID];
|
||||
Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
|
||||
InstanceKlass** klassp = &_well_known_klasses[id];
|
||||
|
||||
bool must_load;
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
if (EnableJVMCI) {
|
||||
// If JVMCI is enabled we require its classes to be found.
|
||||
must_load = (init_opt < SystemDictionary::Opt) || (init_opt == SystemDictionary::Jvmci);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
must_load = (init_opt < SystemDictionary::Opt);
|
||||
if (id >= FIRST_JVMCI_WKID) {
|
||||
assert(EnableJVMCI, "resolve JVMCI classes only when EnableJVMCI is true");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((*klassp) == NULL) {
|
||||
Klass* k;
|
||||
if (must_load) {
|
||||
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);
|
||||
Klass* k = resolve_or_fail(symbol, true, CHECK_0);
|
||||
(*klassp) = InstanceKlass::cast(k);
|
||||
}
|
||||
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!");
|
||||
for (int id = (int)start_id; id < (int)limit_id; id++) {
|
||||
assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
|
||||
int info = wk_init_info[id - FIRST_WKID];
|
||||
int sid = (info >> CEIL_LG_OPTION_LIMIT);
|
||||
int opt = (info & right_n_bits(CEIL_LG_OPTION_LIMIT));
|
||||
|
||||
resolve_wk_klass((WKID)id, opt, CHECK);
|
||||
resolve_wk_klass((WKID)id, CHECK);
|
||||
}
|
||||
|
||||
// move the starting value forward to the limit:
|
||||
|
@ -94,127 +94,125 @@ class OopStorage;
|
||||
#define WK_KLASS_ENUM_NAME(kname) kname##_knum
|
||||
|
||||
// Each well-known class has a short klass name (like object_klass),
|
||||
// a vmSymbol name (like java_lang_Object), and a flag word
|
||||
// that makes some minor distinctions, like whether the klass
|
||||
// is preloaded, optional, release-specific, etc.
|
||||
// and a vmSymbol name (like java_lang_Object).
|
||||
// The order of these definitions is significant; it is the order in which
|
||||
// preloading is actually performed by resolve_preloaded_classes.
|
||||
|
||||
#define WK_KLASSES_DO(do_klass) \
|
||||
/* well-known classes */ \
|
||||
do_klass(Object_klass, java_lang_Object, Pre ) \
|
||||
do_klass(String_klass, java_lang_String, Pre ) \
|
||||
do_klass(Class_klass, java_lang_Class, Pre ) \
|
||||
do_klass(Cloneable_klass, java_lang_Cloneable, Pre ) \
|
||||
do_klass(ClassLoader_klass, java_lang_ClassLoader, Pre ) \
|
||||
do_klass(Serializable_klass, java_io_Serializable, Pre ) \
|
||||
do_klass(System_klass, java_lang_System, Pre ) \
|
||||
do_klass(Throwable_klass, java_lang_Throwable, Pre ) \
|
||||
do_klass(Error_klass, java_lang_Error, Pre ) \
|
||||
do_klass(ThreadDeath_klass, java_lang_ThreadDeath, Pre ) \
|
||||
do_klass(Exception_klass, java_lang_Exception, Pre ) \
|
||||
do_klass(RuntimeException_klass, java_lang_RuntimeException, Pre ) \
|
||||
do_klass(SecurityManager_klass, java_lang_SecurityManager, Pre ) \
|
||||
do_klass(ProtectionDomain_klass, java_security_ProtectionDomain, Pre ) \
|
||||
do_klass(AccessControlContext_klass, java_security_AccessControlContext, Pre ) \
|
||||
do_klass(SecureClassLoader_klass, java_security_SecureClassLoader, Pre ) \
|
||||
do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre ) \
|
||||
do_klass(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre ) \
|
||||
do_klass(LinkageError_klass, java_lang_LinkageError, Pre ) \
|
||||
do_klass(ClassCastException_klass, java_lang_ClassCastException, Pre ) \
|
||||
do_klass(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre ) \
|
||||
do_klass(VirtualMachineError_klass, java_lang_VirtualMachineError, Pre ) \
|
||||
do_klass(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre ) \
|
||||
do_klass(StackOverflowError_klass, java_lang_StackOverflowError, Pre ) \
|
||||
do_klass(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre ) \
|
||||
do_klass(Reference_klass, java_lang_ref_Reference, Pre ) \
|
||||
\
|
||||
/* Preload ref klasses and set reference types */ \
|
||||
do_klass(SoftReference_klass, java_lang_ref_SoftReference, Pre ) \
|
||||
do_klass(WeakReference_klass, java_lang_ref_WeakReference, Pre ) \
|
||||
do_klass(FinalReference_klass, java_lang_ref_FinalReference, Pre ) \
|
||||
do_klass(PhantomReference_klass, java_lang_ref_PhantomReference, Pre ) \
|
||||
do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \
|
||||
\
|
||||
do_klass(Thread_klass, java_lang_Thread, Pre ) \
|
||||
do_klass(ThreadGroup_klass, java_lang_ThreadGroup, Pre ) \
|
||||
do_klass(Properties_klass, java_util_Properties, Pre ) \
|
||||
do_klass(Module_klass, java_lang_Module, Pre ) \
|
||||
do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre ) \
|
||||
do_klass(reflect_Field_klass, java_lang_reflect_Field, Pre ) \
|
||||
do_klass(reflect_Parameter_klass, java_lang_reflect_Parameter, Opt ) \
|
||||
do_klass(reflect_Method_klass, java_lang_reflect_Method, Pre ) \
|
||||
do_klass(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre ) \
|
||||
\
|
||||
/* 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. */ \
|
||||
do_klass(reflect_MagicAccessorImpl_klass, reflect_MagicAccessorImpl, Opt ) \
|
||||
do_klass(reflect_MethodAccessorImpl_klass, reflect_MethodAccessorImpl, Pre ) \
|
||||
do_klass(reflect_ConstructorAccessorImpl_klass, reflect_ConstructorAccessorImpl, Pre ) \
|
||||
do_klass(reflect_DelegatingClassLoader_klass, reflect_DelegatingClassLoader, Opt ) \
|
||||
do_klass(reflect_ConstantPool_klass, reflect_ConstantPool, Opt ) \
|
||||
do_klass(reflect_UnsafeStaticFieldAccessorImpl_klass, reflect_UnsafeStaticFieldAccessorImpl, Opt ) \
|
||||
do_klass(reflect_CallerSensitive_klass, reflect_CallerSensitive, Opt ) \
|
||||
\
|
||||
/* 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(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre ) \
|
||||
do_klass(VarHandle_klass, java_lang_invoke_VarHandle, Pre ) \
|
||||
do_klass(MemberName_klass, java_lang_invoke_MemberName, Pre ) \
|
||||
do_klass(ResolvedMethodName_klass, java_lang_invoke_ResolvedMethodName, Pre ) \
|
||||
do_klass(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre ) \
|
||||
do_klass(LambdaForm_klass, java_lang_invoke_LambdaForm, Opt ) \
|
||||
do_klass(MethodType_klass, java_lang_invoke_MethodType, Pre ) \
|
||||
do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre ) \
|
||||
do_klass(CallSite_klass, java_lang_invoke_CallSite, Pre ) \
|
||||
do_klass(Context_klass, java_lang_invoke_MethodHandleNatives_CallSiteContext, Pre ) \
|
||||
do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre ) \
|
||||
do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre ) \
|
||||
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre ) \
|
||||
/* Note: MethodHandle must be first, and VolatileCallSite last in group */ \
|
||||
\
|
||||
do_klass(AssertionStatusDirectives_klass, java_lang_AssertionStatusDirectives, Pre ) \
|
||||
do_klass(StringBuffer_klass, java_lang_StringBuffer, Pre ) \
|
||||
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
|
||||
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe, Pre ) \
|
||||
do_klass(module_Modules_klass, jdk_internal_module_Modules, Pre ) \
|
||||
\
|
||||
/* support for CDS */ \
|
||||
do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream, Pre ) \
|
||||
do_klass(URL_klass, java_net_URL, Pre ) \
|
||||
do_klass(Jar_Manifest_klass, java_util_jar_Manifest, Pre ) \
|
||||
do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders, Pre ) \
|
||||
do_klass(jdk_internal_loader_ClassLoaders_AppClassLoader_klass, jdk_internal_loader_ClassLoaders_AppClassLoader, Pre ) \
|
||||
do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader, Pre ) \
|
||||
do_klass(CodeSource_klass, java_security_CodeSource, Pre ) \
|
||||
\
|
||||
do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \
|
||||
\
|
||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||
do_klass(nio_Buffer_klass, java_nio_Buffer, Opt ) \
|
||||
\
|
||||
/* Stack Walking */ \
|
||||
do_klass(StackWalker_klass, java_lang_StackWalker, Opt ) \
|
||||
do_klass(AbstractStackWalker_klass, java_lang_StackStreamFactory_AbstractStackWalker, Opt ) \
|
||||
do_klass(StackFrameInfo_klass, java_lang_StackFrameInfo, Opt ) \
|
||||
do_klass(LiveStackFrameInfo_klass, java_lang_LiveStackFrameInfo, Opt ) \
|
||||
\
|
||||
/* support for stack dump lock analysis */ \
|
||||
do_klass(java_util_concurrent_locks_AbstractOwnableSynchronizer_klass, java_util_concurrent_locks_AbstractOwnableSynchronizer, Pre ) \
|
||||
\
|
||||
/* Preload boxing klasses */ \
|
||||
do_klass(Boolean_klass, java_lang_Boolean, Pre ) \
|
||||
do_klass(Character_klass, java_lang_Character, Pre ) \
|
||||
do_klass(Float_klass, java_lang_Float, Pre ) \
|
||||
do_klass(Double_klass, java_lang_Double, Pre ) \
|
||||
do_klass(Byte_klass, java_lang_Byte, Pre ) \
|
||||
do_klass(Short_klass, java_lang_Short, Pre ) \
|
||||
do_klass(Integer_klass, java_lang_Integer, Pre ) \
|
||||
do_klass(Long_klass, java_lang_Long, Pre ) \
|
||||
\
|
||||
/* JVMCI classes. These are loaded on-demand. */ \
|
||||
JVMCI_WK_KLASSES_DO(do_klass) \
|
||||
\
|
||||
#define WK_KLASSES_DO(do_klass) \
|
||||
/* well-known classes */ \
|
||||
do_klass(Object_klass, java_lang_Object ) \
|
||||
do_klass(String_klass, java_lang_String ) \
|
||||
do_klass(Class_klass, java_lang_Class ) \
|
||||
do_klass(Cloneable_klass, java_lang_Cloneable ) \
|
||||
do_klass(ClassLoader_klass, java_lang_ClassLoader ) \
|
||||
do_klass(Serializable_klass, java_io_Serializable ) \
|
||||
do_klass(System_klass, java_lang_System ) \
|
||||
do_klass(Throwable_klass, java_lang_Throwable ) \
|
||||
do_klass(Error_klass, java_lang_Error ) \
|
||||
do_klass(ThreadDeath_klass, java_lang_ThreadDeath ) \
|
||||
do_klass(Exception_klass, java_lang_Exception ) \
|
||||
do_klass(RuntimeException_klass, java_lang_RuntimeException ) \
|
||||
do_klass(SecurityManager_klass, java_lang_SecurityManager ) \
|
||||
do_klass(ProtectionDomain_klass, java_security_ProtectionDomain ) \
|
||||
do_klass(AccessControlContext_klass, java_security_AccessControlContext ) \
|
||||
do_klass(SecureClassLoader_klass, java_security_SecureClassLoader ) \
|
||||
do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException ) \
|
||||
do_klass(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError ) \
|
||||
do_klass(LinkageError_klass, java_lang_LinkageError ) \
|
||||
do_klass(ClassCastException_klass, java_lang_ClassCastException ) \
|
||||
do_klass(ArrayStoreException_klass, java_lang_ArrayStoreException ) \
|
||||
do_klass(VirtualMachineError_klass, java_lang_VirtualMachineError ) \
|
||||
do_klass(OutOfMemoryError_klass, java_lang_OutOfMemoryError ) \
|
||||
do_klass(StackOverflowError_klass, java_lang_StackOverflowError ) \
|
||||
do_klass(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException ) \
|
||||
do_klass(Reference_klass, java_lang_ref_Reference ) \
|
||||
\
|
||||
/* Preload ref klasses and set reference types */ \
|
||||
do_klass(SoftReference_klass, java_lang_ref_SoftReference ) \
|
||||
do_klass(WeakReference_klass, java_lang_ref_WeakReference ) \
|
||||
do_klass(FinalReference_klass, java_lang_ref_FinalReference ) \
|
||||
do_klass(PhantomReference_klass, java_lang_ref_PhantomReference ) \
|
||||
do_klass(Finalizer_klass, java_lang_ref_Finalizer ) \
|
||||
\
|
||||
do_klass(Thread_klass, java_lang_Thread ) \
|
||||
do_klass(ThreadGroup_klass, java_lang_ThreadGroup ) \
|
||||
do_klass(Properties_klass, java_util_Properties ) \
|
||||
do_klass(Module_klass, java_lang_Module ) \
|
||||
do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject ) \
|
||||
do_klass(reflect_Field_klass, java_lang_reflect_Field ) \
|
||||
do_klass(reflect_Parameter_klass, java_lang_reflect_Parameter ) \
|
||||
do_klass(reflect_Method_klass, java_lang_reflect_Method ) \
|
||||
do_klass(reflect_Constructor_klass, java_lang_reflect_Constructor ) \
|
||||
\
|
||||
/* 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. */ \
|
||||
do_klass(reflect_MagicAccessorImpl_klass, reflect_MagicAccessorImpl ) \
|
||||
do_klass(reflect_MethodAccessorImpl_klass, reflect_MethodAccessorImpl ) \
|
||||
do_klass(reflect_ConstructorAccessorImpl_klass, reflect_ConstructorAccessorImpl ) \
|
||||
do_klass(reflect_DelegatingClassLoader_klass, reflect_DelegatingClassLoader ) \
|
||||
do_klass(reflect_ConstantPool_klass, reflect_ConstantPool ) \
|
||||
do_klass(reflect_UnsafeStaticFieldAccessorImpl_klass, reflect_UnsafeStaticFieldAccessorImpl ) \
|
||||
do_klass(reflect_CallerSensitive_klass, reflect_CallerSensitive ) \
|
||||
\
|
||||
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
|
||||
do_klass(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle ) \
|
||||
do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle ) \
|
||||
do_klass(VarHandle_klass, java_lang_invoke_VarHandle ) \
|
||||
do_klass(MemberName_klass, java_lang_invoke_MemberName ) \
|
||||
do_klass(ResolvedMethodName_klass, java_lang_invoke_ResolvedMethodName ) \
|
||||
do_klass(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives ) \
|
||||
do_klass(LambdaForm_klass, java_lang_invoke_LambdaForm ) \
|
||||
do_klass(MethodType_klass, java_lang_invoke_MethodType ) \
|
||||
do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError ) \
|
||||
do_klass(CallSite_klass, java_lang_invoke_CallSite ) \
|
||||
do_klass(Context_klass, java_lang_invoke_MethodHandleNatives_CallSiteContext ) \
|
||||
do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite ) \
|
||||
do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite ) \
|
||||
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite ) \
|
||||
/* Note: MethodHandle must be first, and VolatileCallSite last in group */ \
|
||||
\
|
||||
do_klass(AssertionStatusDirectives_klass, java_lang_AssertionStatusDirectives ) \
|
||||
do_klass(StringBuffer_klass, java_lang_StringBuffer ) \
|
||||
do_klass(StringBuilder_klass, java_lang_StringBuilder ) \
|
||||
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe ) \
|
||||
do_klass(module_Modules_klass, jdk_internal_module_Modules ) \
|
||||
\
|
||||
/* support for CDS */ \
|
||||
do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream ) \
|
||||
do_klass(URL_klass, java_net_URL ) \
|
||||
do_klass(Jar_Manifest_klass, java_util_jar_Manifest ) \
|
||||
do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders ) \
|
||||
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) \
|
||||
do_klass(CodeSource_klass, java_security_CodeSource ) \
|
||||
\
|
||||
do_klass(StackTraceElement_klass, java_lang_StackTraceElement ) \
|
||||
\
|
||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||
do_klass(nio_Buffer_klass, java_nio_Buffer ) \
|
||||
\
|
||||
/* Stack Walking */ \
|
||||
do_klass(StackWalker_klass, java_lang_StackWalker ) \
|
||||
do_klass(AbstractStackWalker_klass, java_lang_StackStreamFactory_AbstractStackWalker ) \
|
||||
do_klass(StackFrameInfo_klass, java_lang_StackFrameInfo ) \
|
||||
do_klass(LiveStackFrameInfo_klass, java_lang_LiveStackFrameInfo ) \
|
||||
\
|
||||
/* support for stack dump lock analysis */ \
|
||||
do_klass(java_util_concurrent_locks_AbstractOwnableSynchronizer_klass, java_util_concurrent_locks_AbstractOwnableSynchronizer) \
|
||||
\
|
||||
/* Preload boxing klasses */ \
|
||||
do_klass(Boolean_klass, java_lang_Boolean ) \
|
||||
do_klass(Character_klass, java_lang_Character ) \
|
||||
do_klass(Float_klass, java_lang_Float ) \
|
||||
do_klass(Double_klass, java_lang_Double ) \
|
||||
do_klass(Byte_klass, java_lang_Byte ) \
|
||||
do_klass(Short_klass, java_lang_Short ) \
|
||||
do_klass(Integer_klass, java_lang_Integer ) \
|
||||
do_klass(Long_klass, java_lang_Long ) \
|
||||
\
|
||||
/* JVMCI classes. These are loaded on-demand. */ \
|
||||
JVMCI_WK_KLASSES_DO(do_klass) \
|
||||
\
|
||||
/*end*/
|
||||
|
||||
|
||||
@ -226,7 +224,7 @@ class SystemDictionary : AllStatic {
|
||||
enum WKID {
|
||||
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)
|
||||
#undef WK_KLASS_ENUM
|
||||
|
||||
@ -240,21 +238,6 @@ class SystemDictionary : AllStatic {
|
||||
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
|
||||
// class if needed. If not found a NoClassDefFoundError or a
|
||||
// ClassNotFoundException is thrown, depending on the value on the
|
||||
@ -414,12 +397,7 @@ public:
|
||||
return k;
|
||||
}
|
||||
|
||||
static InstanceKlass* check_klass_Pre(InstanceKlass* k) { return check_klass(k); }
|
||||
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 bool resolve_wk_klass(WKID 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) {
|
||||
int limit = (int)end_id + 1;
|
||||
@ -427,10 +405,13 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
#define WK_KLASS_DECLARE(name, symbol, option) \
|
||||
static InstanceKlass* name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \
|
||||
static InstanceKlass** name##_addr() { \
|
||||
return &SystemDictionary::_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \
|
||||
#define WK_KLASS_DECLARE(name, symbol) \
|
||||
static InstanceKlass* name() { return check_klass(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \
|
||||
static InstanceKlass** name##_addr() { \
|
||||
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);
|
||||
#undef WK_KLASS_DECLARE
|
||||
|
@ -172,7 +172,11 @@ void VerificationType::print_on(outputStream* st) const {
|
||||
} else if (is_uninitialized()) {
|
||||
st->print("uninitialized %d", bci());
|
||||
} 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 is_frame_complete_at(address addr) const { return _frame_complete_offset != CodeOffsets::frame_never_safe &&
|
||||
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
|
||||
// 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.
|
||||
* 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");
|
||||
|
||||
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");
|
||||
} else if (ParallelGCThreads == 0) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
|
@ -41,8 +41,7 @@ inline void MetadataVisitingOopsInGenClosure::do_klass(Klass* k) {
|
||||
}
|
||||
|
||||
inline void MetadataVisitingOopsInGenClosure::do_cld(ClassLoaderData* cld) {
|
||||
bool claim = true; // Must claim the class loader data before processing.
|
||||
cld->oops_do(this, claim);
|
||||
cld->oops_do(this, ClassLoaderData::_claim_strong);
|
||||
}
|
||||
|
||||
// Decode the oop and call do_oop on it.
|
||||
|
@ -2398,7 +2398,7 @@ class VerifyCLDOopsCLDClosure : public CLDClosure {
|
||||
public:
|
||||
VerifyCLDOopsCLDClosure(CMSBitMap* bitmap) : _oop_closure(bitmap) {}
|
||||
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
|
||||
MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(),
|
||||
markBitMap());
|
||||
CLDToOopClosure cld_closure(¬Older, true);
|
||||
CLDToOopClosure cld_closure(¬Older, ClassLoaderData::_claim_strong);
|
||||
|
||||
heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||
|
||||
@ -2886,7 +2886,7 @@ void CMSCollector::checkpointRootsInitialWork() {
|
||||
}
|
||||
} else {
|
||||
// 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.
|
||||
|
||||
StrongRootsScope srs(1);
|
||||
@ -4269,7 +4269,7 @@ void CMSParInitialMarkTask::work(uint worker_id) {
|
||||
_timer.reset();
|
||||
_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,
|
||||
false, // yg was scanned above
|
||||
@ -4331,7 +4331,7 @@ class CMSParRemarkTask: public CMSParMarkTask {
|
||||
class RemarkCLDClosure : public CLDClosure {
|
||||
CLDToOopClosure _cm_closure;
|
||||
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) {
|
||||
// Check if we have modified any oops in the CLD during the concurrent marking.
|
||||
if (cld->has_accumulated_modified_oops()) {
|
||||
|
@ -40,6 +40,7 @@ EpsilonBarrierSet::EpsilonBarrierSet() : BarrierSet(
|
||||
make_barrier_set_assembler<BarrierSetAssembler>(),
|
||||
make_barrier_set_c1<BarrierSetC1>(),
|
||||
make_barrier_set_c2<BarrierSetC2>(),
|
||||
NULL /* barrier_set_nmethod */,
|
||||
BarrierSet::FakeRtti(BarrierSet::EpsilonBarrierSet)) {};
|
||||
|
||||
void EpsilonBarrierSet::on_thread_create(Thread *thread) {
|
||||
|
@ -47,7 +47,7 @@ jint EpsilonHeap::initialize() {
|
||||
_space->initialize(committed_region, /* clear_space = */ true, /* mangle_space = */ true);
|
||||
|
||||
// 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_heap_print = (EpsilonPrintHeapSteps == 0) ? SIZE_MAX : (max_byte_size / EpsilonPrintHeapSteps);
|
||||
_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
|
||||
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)) {
|
||||
ResourceMark rm;
|
||||
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() {
|
||||
GCArguments::initialize();
|
||||
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) {
|
||||
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);
|
||||
|
@ -108,7 +108,7 @@ void G1FullGCAdjustTask::work(uint worker_id) {
|
||||
AlwaysTrueClosure always_alive;
|
||||
_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);
|
||||
_root_processor.process_all_roots(
|
||||
&_adjust,
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderData.hpp"
|
||||
#include "gc/g1/g1FullGCMarker.inline.hpp"
|
||||
#include "gc/shared/referenceProcessor.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()),
|
||||
_verify_closure(VerifyOption_G1UseFullMarking),
|
||||
_stack_closure(this),
|
||||
_cld_closure(mark_closure()) {
|
||||
_cld_closure(mark_closure(), ClassLoaderData::_claim_strong) {
|
||||
_oop_stack.initialize();
|
||||
_objarray_stack.initialize();
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef 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/g1FullGCMarker.inline.hpp"
|
||||
#include "gc/g1/g1FullGCOopClosures.hpp"
|
||||
|
@ -24,14 +24,12 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/g1/g1Allocator.inline.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||
#include "gc/g1/g1ConcurrentMarkThread.hpp"
|
||||
#include "gc/g1/g1HeapVerifier.hpp"
|
||||
#include "gc/g1/g1Policy.hpp"
|
||||
#include "gc/g1/g1RemSet.hpp"
|
||||
#include "gc/g1/g1RootProcessor.hpp"
|
||||
#include "gc/g1/heapRegion.hpp"
|
||||
#include "gc/g1/heapRegion.inline.hpp"
|
||||
#include "gc/g1/heapRegionRemSet.hpp"
|
||||
#include "gc/g1/g1StringDedup.hpp"
|
||||
@ -170,10 +168,10 @@ class VerifyCLDClosure: public CLDClosure {
|
||||
public:
|
||||
VerifyCLDClosure(G1CollectedHeap* g1h, OopClosure* cl) : _young_ref_counter_closure(g1h), _oop_closure(cl) {}
|
||||
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();
|
||||
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) {
|
||||
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.
|
||||
// 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);
|
||||
|
||||
|
@ -160,12 +160,12 @@ public:
|
||||
class G1CLDScanClosure : public CLDClosure {
|
||||
G1ParCopyHelper* _closure;
|
||||
bool _process_only_dirty;
|
||||
bool _must_claim;
|
||||
int _claim;
|
||||
int _count;
|
||||
public:
|
||||
G1CLDScanClosure(G1ParCopyHelper* closure,
|
||||
bool process_only_dirty, bool must_claim)
|
||||
: _closure(closure), _process_only_dirty(process_only_dirty), _must_claim(must_claim), _count(0) {}
|
||||
bool process_only_dirty, int claim_value)
|
||||
: _closure(closure), _process_only_dirty(process_only_dirty), _claim(claim_value), _count(0) {}
|
||||
void do_cld(ClassLoaderData* cld);
|
||||
};
|
||||
|
||||
|
@ -201,11 +201,11 @@ void G1ParScanThreadState::report_promotion_event(InCSetState const dest_state,
|
||||
HeapWord * const obj_ptr) const {
|
||||
PLAB* alloc_buf = _plab_allocator->alloc_buffer(dest_state);
|
||||
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,
|
||||
alloc_buf->word_sz());
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
G1EvacuationClosures(G1CollectedHeap* g1h,
|
||||
G1ParScanThreadState* pss,
|
||||
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* strong_oops() { return &_closures._oops; }
|
||||
@ -73,8 +73,8 @@ class G1InitialMarkClosures : public G1EvacuationRootClosures {
|
||||
public:
|
||||
G1InitialMarkClosures(G1CollectedHeap* g1h,
|
||||
G1ParScanThreadState* pss) :
|
||||
_strong(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true),
|
||||
_weak(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, /* cld_claim */ ClassLoaderData::_claim_strong) {}
|
||||
|
||||
OopClosure* weak_oops() { return &_weak._oops; }
|
||||
OopClosure* strong_oops() { return &_strong._oops; }
|
||||
|
@ -39,9 +39,9 @@ public:
|
||||
G1CLDScanClosure _clds;
|
||||
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_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) {}
|
||||
};
|
||||
|
@ -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.
|
||||
* 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
|
||||
// of the physical memory, up to a maximum of 1GB.
|
||||
FLAG_SET_DEFAULT(ParallelGCThreads,
|
||||
Abstract_VM_Version::parallel_worker_threads());
|
||||
VM_Version::parallel_worker_threads());
|
||||
if (ParallelGCThreads == 0) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"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;
|
||||
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
@ -2213,7 +2213,7 @@ void PSParallelCompact::adjust_roots(ParCompactionManager* cm) {
|
||||
Management::oops_do(&oop_closure);
|
||||
JvmtiExport::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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
@ -58,9 +58,9 @@ SerialOldTracer* MarkSweep::_gc_tracer = NULL;
|
||||
|
||||
MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
|
||||
|
||||
MarkAndPushClosure MarkSweep::mark_and_push_closure;
|
||||
CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure);
|
||||
CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure);
|
||||
MarkAndPushClosure MarkSweep::mark_and_push_closure;
|
||||
CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_strong);
|
||||
CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure, ClassLoaderData::_claim_strong);
|
||||
|
||||
template <class T> inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) {
|
||||
mark_and_push(p);
|
||||
|
@ -36,6 +36,7 @@
|
||||
class BarrierSetAssembler;
|
||||
class BarrierSetC1;
|
||||
class BarrierSetC2;
|
||||
class BarrierSetNMethod;
|
||||
class JavaThread;
|
||||
|
||||
// This class provides the interface between a barrier implementation and
|
||||
@ -72,6 +73,7 @@ private:
|
||||
BarrierSetAssembler* _barrier_set_assembler;
|
||||
BarrierSetC1* _barrier_set_c1;
|
||||
BarrierSetC2* _barrier_set_c2;
|
||||
BarrierSetNMethod* _barrier_set_nmethod;
|
||||
|
||||
public:
|
||||
// Metafunction mapping a class derived from BarrierSet to the
|
||||
@ -95,11 +97,13 @@ protected:
|
||||
BarrierSet(BarrierSetAssembler* barrier_set_assembler,
|
||||
BarrierSetC1* barrier_set_c1,
|
||||
BarrierSetC2* barrier_set_c2,
|
||||
BarrierSetNMethod* barrier_set_nmethod,
|
||||
const FakeRtti& fake_rtti) :
|
||||
_fake_rtti(fake_rtti),
|
||||
_barrier_set_assembler(barrier_set_assembler),
|
||||
_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() { }
|
||||
|
||||
template <class BarrierSetAssemblerT>
|
||||
@ -156,6 +160,10 @@ public:
|
||||
return _barrier_set_c2;
|
||||
}
|
||||
|
||||
BarrierSetNMethod* barrier_set_nmethod() {
|
||||
return _barrier_set_nmethod;
|
||||
}
|
||||
|
||||
// The AccessBarrier of a BarrierSet subclass is called by the Access API
|
||||
// (cf. oops/access.hpp) to perform decorated accesses. GC implementations
|
||||
// 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,
|
||||
barrier_set_c1,
|
||||
barrier_set_c2,
|
||||
NULL /* barrier_set_nmethod */,
|
||||
fake_rtti.add_tag(BarrierSet::ModRef)) { }
|
||||
~ModRefBarrierSet() { }
|
||||
|
||||
|
@ -43,6 +43,7 @@ ZBarrierSet::ZBarrierSet() :
|
||||
BarrierSet(make_barrier_set_assembler<ZBarrierSetAssembler>(),
|
||||
make_barrier_set_c1<ZBarrierSetC1>(),
|
||||
make_barrier_set_c2<ZBarrierSetC2>(),
|
||||
NULL /* barrier_set_nmethod */,
|
||||
BarrierSet::FakeRtti(BarrierSet::ZBarrierSet)) {}
|
||||
|
||||
ZBarrierSetAssembler* ZBarrierSet::assembler() {
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/shared/gcHeapSummary.hpp"
|
||||
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||
#include "gc/z/zCollectedHeap.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zHeap.inline.hpp"
|
||||
@ -295,6 +296,14 @@ VirtualSpaceSummary ZCollectedHeap::create_heap_space_summary() {
|
||||
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() {
|
||||
// Does nothing
|
||||
}
|
||||
|
@ -117,6 +117,9 @@ public:
|
||||
|
||||
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_error(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
|
||||
{
|
||||
ZStatTimer timer(ZPhaseConcurrentMark);
|
||||
ZHeap::heap()->mark();
|
||||
ZHeap::heap()->mark(true /* initial */);
|
||||
}
|
||||
|
||||
// Phase 3: Pause Mark End
|
||||
@ -345,7 +345,7 @@ void ZDriver::run_gc_cycle(GCCause::Cause cause) {
|
||||
while (!vm_operation(&cl)) {
|
||||
// Phase 3.5: Concurrent Mark Continue
|
||||
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());
|
||||
}
|
||||
|
||||
void ZHeap::mark() {
|
||||
_mark.mark();
|
||||
void ZHeap::mark(bool initial) {
|
||||
_mark.mark(initial);
|
||||
}
|
||||
|
||||
void ZHeap::mark_flush_and_free(Thread* thread) {
|
||||
|
@ -133,7 +133,7 @@ public:
|
||||
bool is_object_strongly_live(uintptr_t addr) const;
|
||||
template <bool finalizable, bool publish> void mark_object(uintptr_t addr);
|
||||
void mark_start();
|
||||
void mark();
|
||||
void mark(bool initial);
|
||||
void mark_flush_and_free(Thread* thread);
|
||||
bool mark_end();
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "gc/z/zOop.inline.hpp"
|
||||
#include "gc/z/zRootsIterator.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "utilities/bitMap.inline.hpp"
|
||||
#include "utilities/stack.inline.hpp"
|
||||
|
||||
@ -54,19 +53,18 @@ public:
|
||||
class ZHeapIteratorRootOopClosure : public ZRootsIteratorClosure {
|
||||
private:
|
||||
ZHeapIterator* const _iter;
|
||||
ObjectClosure* const _cl;
|
||||
|
||||
public:
|
||||
ZHeapIteratorRootOopClosure(ZHeapIterator* iter, ObjectClosure* cl) :
|
||||
_iter(iter),
|
||||
_cl(cl) {}
|
||||
ZHeapIteratorRootOopClosure(ZHeapIterator* iter) :
|
||||
_iter(iter) {}
|
||||
|
||||
virtual void do_oop(oop* p) {
|
||||
// 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);
|
||||
_iter->push(obj);
|
||||
_iter->drain(_cl);
|
||||
}
|
||||
|
||||
virtual void do_oop(narrowOop* p) {
|
||||
@ -74,19 +72,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ZHeapIteratorPushOopClosure : public BasicOopIterateClosure {
|
||||
class ZHeapIteratorOopClosure : public BasicOopIterateClosure {
|
||||
private:
|
||||
ZHeapIterator* const _iter;
|
||||
const oop _base;
|
||||
const bool _visit_referents;
|
||||
|
||||
public:
|
||||
ZHeapIteratorPushOopClosure(ZHeapIterator* iter, oop base) :
|
||||
_iter(iter),
|
||||
_base(base),
|
||||
_visit_referents(iter->visit_referents()) {}
|
||||
|
||||
oop load_oop(oop* p) {
|
||||
oop load_oop(oop* p) const {
|
||||
if (_visit_referents) {
|
||||
return HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(_base, _base->field_offset(p));
|
||||
} 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() {
|
||||
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;
|
||||
}
|
||||
|
||||
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 offset = ZAddress::offset(addr);
|
||||
const uintptr_t mask = (1 << ZPageSizeMinShift) - 1;
|
||||
@ -165,7 +163,22 @@ void ZHeapIterator::push(oop 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()) {
|
||||
const oop obj = _visit_stack.pop();
|
||||
|
||||
@ -173,23 +186,7 @@ void ZHeapIterator::drain(ObjectClosure* cl) {
|
||||
cl->do_object(obj);
|
||||
|
||||
// Push members to visit
|
||||
ZHeapIteratorPushOopClosure push_cl(this, obj);
|
||||
ZHeapIteratorOopClosure push_cl(this, obj, _visit_referents);
|
||||
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 {
|
||||
friend class ZHeapIteratorRootOopClosure;
|
||||
friend class ZHeapIteratorPushOopClosure;
|
||||
friend class ZHeapIteratorOopClosure;
|
||||
|
||||
private:
|
||||
typedef ZAddressRangeMap<ZHeapIteratorBitMap*, ZPageSizeMinShift> ZVisitMap;
|
||||
@ -44,14 +44,8 @@ private:
|
||||
ZVisitMap _visit_map;
|
||||
const bool _visit_referents;
|
||||
|
||||
size_t object_index_max() const;
|
||||
size_t object_index(oop obj) const;
|
||||
ZHeapIteratorBitMap* object_map(oop obj);
|
||||
|
||||
void push(oop obj);
|
||||
void drain(ObjectClosure* cl);
|
||||
|
||||
bool visit_referents() const;
|
||||
|
||||
public:
|
||||
ZHeapIterator(bool visit_referents);
|
||||
|
@ -38,8 +38,8 @@
|
||||
ZInitialize::ZInitialize(ZBarrierSet* barrier_set) {
|
||||
log_info(gc, init)("Initializing %s", ZGCName);
|
||||
log_info(gc, init)("Version: %s (%s)",
|
||||
Abstract_VM_Version::vm_release(),
|
||||
Abstract_VM_Version::jdk_debug_level());
|
||||
VM_Version::vm_release(),
|
||||
VM_Version::jdk_debug_level());
|
||||
|
||||
// Early initialization
|
||||
ZAddressMasks::initialize();
|
||||
|
@ -615,6 +615,34 @@ void ZMark::work(uint64_t timeout_in_millis) {
|
||||
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 {
|
||||
private:
|
||||
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);
|
||||
_workers->run_concurrent(&task);
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ public:
|
||||
template <bool finalizable, bool publish> void mark_object(uintptr_t addr);
|
||||
|
||||
void start();
|
||||
void mark();
|
||||
void mark(bool initial);
|
||||
bool end();
|
||||
|
||||
void flush_and_free();
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "code/codeCache.hpp"
|
||||
#include "compiler/oopMap.hpp"
|
||||
#include "gc/shared/oopStorageParState.inline.hpp"
|
||||
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zNMethodTable.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 ZSubPhasePauseRootsTeardown("Pause Roots Teardown");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsUniverse("Pause Roots Universe");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsJNIHandles("Pause Roots JNIHandles");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsObjectSynchronizer("Pause Roots ObjectSynchronizer");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsManagement("Pause Roots Management");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsJVMTIExport("Pause Roots JVMTIExport");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsJVMTIWeakExport("Pause Roots JVMTIWeakExport");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsSystemDictionary("Pause Roots SystemDictionary");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsClassLoaderDataGraph("Pause Roots ClassLoaderDataGraph");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsThreads("Pause Roots Threads");
|
||||
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 ZSubPhasePauseWeakRoots("Pause Weak Roots");
|
||||
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() :
|
||||
_jni_handles_iter(JNIHandles::global_handles()),
|
||||
_universe(this),
|
||||
_object_synchronizer(this),
|
||||
_management(this),
|
||||
_jvmti_export(this),
|
||||
_jvmti_weak_export(this),
|
||||
_system_dictionary(this),
|
||||
_jni_handles(this),
|
||||
_class_loader_data_graph(this),
|
||||
_threads(this),
|
||||
_code_cache(this) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
|
||||
ZStatTimer timer(ZSubPhasePauseRootsSetup);
|
||||
Threads::change_thread_claim_parity();
|
||||
ClassLoaderDataGraph::clear_claimed_marks();
|
||||
COMPILER2_PRESENT(DerivedPointerTable::clear());
|
||||
CodeCache::gc_prologue();
|
||||
ZNMethodTable::gc_prologue();
|
||||
@ -163,11 +164,6 @@ void ZRootsIterator::do_universe(ZRootsIteratorClosure* 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) {
|
||||
ZStatTimer timer(ZSubPhasePauseRootsObjectSynchronizer);
|
||||
ObjectSynchronizer::oops_do(cl);
|
||||
@ -194,12 +190,6 @@ void ZRootsIterator::do_system_dictionary(ZRootsIteratorClosure* 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) {
|
||||
ZStatTimer timer(ZSubPhasePauseRootsThreads);
|
||||
ResourceMark rm;
|
||||
@ -218,8 +208,6 @@ void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl, bool visit_jvmti_weak_ex
|
||||
_management.oops_do(cl);
|
||||
_jvmti_export.oops_do(cl);
|
||||
_system_dictionary.oops_do(cl);
|
||||
_jni_handles.oops_do(cl);
|
||||
_class_loader_data_graph.oops_do(cl);
|
||||
_threads.oops_do(cl);
|
||||
_code_cache.oops_do(cl);
|
||||
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() :
|
||||
_jvmti_weak_export(this),
|
||||
_jfr_weak(this) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define SHARE_GC_Z_ZROOTSITERATOR_HPP
|
||||
|
||||
#include "gc/shared/oopStorageParState.hpp"
|
||||
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/iterator.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 */> ZConcurrentOopStorageIterator;
|
||||
typedef OopStorage::ParState<true /* concurrent */, false /* is_const */> ZOopStorageIterator;
|
||||
|
||||
template <typename T, void (T::*F)(ZRootsIteratorClosure*)>
|
||||
class ZSerialOopsDo {
|
||||
@ -86,29 +86,23 @@ public:
|
||||
|
||||
class ZRootsIterator {
|
||||
private:
|
||||
ZOopStorageIterator _jni_handles_iter;
|
||||
|
||||
void do_universe(ZRootsIteratorClosure* cl);
|
||||
void do_jni_handles(ZRootsIteratorClosure* cl);
|
||||
void do_object_synchronizer(ZRootsIteratorClosure* cl);
|
||||
void do_management(ZRootsIteratorClosure* cl);
|
||||
void do_jvmti_export(ZRootsIteratorClosure* cl);
|
||||
void do_jvmti_weak_export(ZRootsIteratorClosure* cl);
|
||||
void do_system_dictionary(ZRootsIteratorClosure* cl);
|
||||
void do_class_loader_data_graph(ZRootsIteratorClosure* cl);
|
||||
void do_threads(ZRootsIteratorClosure* cl);
|
||||
void do_code_cache(ZRootsIteratorClosure* cl);
|
||||
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_universe> _universe;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_object_synchronizer> _object_synchronizer;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_management> _management;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_export> _jvmti_export;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_weak_export> _jvmti_weak_export;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_system_dictionary> _system_dictionary;
|
||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_jni_handles> _jni_handles;
|
||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_class_loader_data_graph> _class_loader_data_graph;
|
||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_threads> _threads;
|
||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_code_cache> _code_cache;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_universe> _universe;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_object_synchronizer> _object_synchronizer;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_management> _management;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_export> _jvmti_export;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_weak_export> _jvmti_weak_export;
|
||||
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_system_dictionary> _system_dictionary;
|
||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_threads> _threads;
|
||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_code_cache> _code_cache;
|
||||
|
||||
public:
|
||||
ZRootsIterator();
|
||||
@ -117,6 +111,25 @@ public:
|
||||
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 {
|
||||
private:
|
||||
void do_jvmti_weak_export(BoolObjectClosure* is_alive, ZRootsIteratorClosure* cl);
|
||||
@ -135,9 +148,9 @@ public:
|
||||
|
||||
class ZConcurrentWeakRootsIterator {
|
||||
private:
|
||||
ZConcurrentOopStorageIterator _vm_weak_handles_iter;
|
||||
ZConcurrentOopStorageIterator _jni_weak_handles_iter;
|
||||
ZConcurrentOopStorageIterator _string_table_iter;
|
||||
ZOopStorageIterator _vm_weak_handles_iter;
|
||||
ZOopStorageIterator _jni_weak_handles_iter;
|
||||
ZOopStorageIterator _string_table_iter;
|
||||
|
||||
void do_vm_weak_handles(ZRootsIteratorClosure* cl);
|
||||
void do_jni_weak_handles(ZRootsIteratorClosure* cl);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "code/codeCache.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/disassembler.hpp"
|
||||
#include "gc/shared/barrierSetNMethod.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "interpreter/interpreter.hpp"
|
||||
#include "interpreter/interpreterRuntime.hpp"
|
||||
@ -1045,6 +1046,13 @@ nmethod* InterpreterRuntime::frequency_counter_overflow(JavaThread* thread, addr
|
||||
Method* method = last_frame.method();
|
||||
int bci = method->bci_from(last_frame.bcp());
|
||||
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()) {
|
||||
// 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);
|
||||
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) {
|
||||
// We may need to do on-stack replacement which requires that no
|
||||
// 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());
|
||||
}
|
||||
|
||||
if (!link_info.check_access())
|
||||
// Access checking may be turned off when calling from within the VM.
|
||||
return;
|
||||
|
||||
// check access
|
||||
// Access checking may be turned off when calling from within the VM.
|
||||
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
|
||||
if (is_static != fd.is_static()) {
|
||||
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);
|
||||
}
|
||||
// check access
|
||||
check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
|
||||
|
||||
// A final field can be modified only
|
||||
// (1) by methods declared in the class declaring the field and
|
||||
// (2) by the <clinit> method (in case of a static field)
|
||||
// or by the <init> method (in case of an instance field).
|
||||
if (is_put && fd.access_flags().is_final()) {
|
||||
ResourceMark rm(THREAD);
|
||||
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());
|
||||
// check for errors
|
||||
if (is_static != fd.is_static()) {
|
||||
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);
|
||||
}
|
||||
|
||||
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());
|
||||
// A final field can be modified only
|
||||
// (1) by methods declared in the class declaring the field and
|
||||
// (2) by the <clinit> method (in case of a static field)
|
||||
// or by the <init> method (in case of an instance field).
|
||||
if (is_put && fd.access_flags().is_final()) {
|
||||
ResourceMark rm(THREAD);
|
||||
stringStream ss;
|
||||
|
||||
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 ",
|
||||
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(),
|
||||
m()->name()->as_C_string(),
|
||||
is_static ? "<clinit>" : "<init>");
|
||||
current_klass->external_name());
|
||||
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
|
||||
// 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) {
|
||||
if ((sel_klass != current_klass) && (current_klass != NULL)) {
|
||||
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;
|
||||
RootSetClosureMarkScope mark_scope;
|
||||
|
||||
CLDToOopClosure cldt_closure(closure);
|
||||
CLDToOopClosure cldt_closure(closure, ClassLoaderData::_claim_strong);
|
||||
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
|
||||
CodeBlobToOopClosure blobs(closure, false);
|
||||
Threads::oops_do(closure, &blobs);
|
||||
|
@ -128,7 +128,7 @@ class ReferenceToRootClosure : public StackObj {
|
||||
bool ReferenceToRootClosure::do_cldg_roots() {
|
||||
assert(!complete(), "invariant");
|
||||
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);
|
||||
return rlc.complete();
|
||||
}
|
||||
|
@ -69,12 +69,12 @@ CLDClaimContext::CLDClaimContext() : _cld(NULL) {}
|
||||
|
||||
CLDClaimContext::CLDClaimContext(ClassLoaderData* cld) : _cld(cld) {
|
||||
assert(_cld->claimed(), "invariant");
|
||||
_cld->clear_claimed();
|
||||
_cld->clear_claim();
|
||||
}
|
||||
|
||||
CLDClaimContext::~CLDClaimContext() {
|
||||
if (_cld != NULL) {
|
||||
_cld->claim();
|
||||
_cld->try_claim(ClassLoaderData::_claim_strong);
|
||||
assert(_cld->claimed(), "invariant");
|
||||
}
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ class name : AllStatic {
|
||||
static void check(oop obj, const char* field_name, int offset); \
|
||||
static void compute_offsets(TRAPS); \
|
||||
public: \
|
||||
static InstanceKlass* klass() { return SystemDictionary::name##_klass(); }
|
||||
static InstanceKlass* klass() { return SystemDictionary::name##_klass_is_loaded() ? SystemDictionary::name##_klass() : NULL; }
|
||||
|
||||
#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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,68 +27,68 @@
|
||||
#if !INCLUDE_JVMCI
|
||||
#define JVMCI_WK_KLASSES_DO(do_klass)
|
||||
#else
|
||||
#define JVMCI_WK_KLASSES_DO(do_klass) \
|
||||
/* JVMCI classes. These are loaded on-demand. */ \
|
||||
do_klass(JVMCI_klass, jdk_vm_ci_runtime_JVMCI, Jvmci) \
|
||||
do_klass(HotSpotCompiledCode_klass, jdk_vm_ci_hotspot_HotSpotCompiledCode, Jvmci) \
|
||||
do_klass(HotSpotCompiledCode_Comment_klass, jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment, Jvmci) \
|
||||
do_klass(HotSpotCompiledNmethod_klass, jdk_vm_ci_hotspot_HotSpotCompiledNmethod, Jvmci) \
|
||||
do_klass(HotSpotForeignCallTarget_klass, jdk_vm_ci_hotspot_HotSpotForeignCallTarget, Jvmci) \
|
||||
do_klass(HotSpotReferenceMap_klass, jdk_vm_ci_hotspot_HotSpotReferenceMap, Jvmci) \
|
||||
do_klass(HotSpotInstalledCode_klass, jdk_vm_ci_hotspot_HotSpotInstalledCode, Jvmci) \
|
||||
do_klass(HotSpotNmethod_klass, jdk_vm_ci_hotspot_HotSpotNmethod, Jvmci) \
|
||||
do_klass(HotSpotResolvedJavaMethodImpl_klass, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl, Jvmci) \
|
||||
do_klass(HotSpotResolvedObjectTypeImpl_klass, jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl, Jvmci) \
|
||||
do_klass(HotSpotCompressedNullConstant_klass, jdk_vm_ci_hotspot_HotSpotCompressedNullConstant, Jvmci) \
|
||||
do_klass(HotSpotObjectConstantImpl_klass, jdk_vm_ci_hotspot_HotSpotObjectConstantImpl, Jvmci) \
|
||||
do_klass(HotSpotMetaspaceConstantImpl_klass, jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl, Jvmci) \
|
||||
do_klass(HotSpotSentinelConstant_klass, jdk_vm_ci_hotspot_HotSpotSentinelConstant, Jvmci) \
|
||||
do_klass(HotSpotStackFrameReference_klass, jdk_vm_ci_hotspot_HotSpotStackFrameReference, Jvmci) \
|
||||
do_klass(HotSpotMetaData_klass, jdk_vm_ci_hotspot_HotSpotMetaData, Jvmci) \
|
||||
do_klass(HotSpotConstantPool_klass, jdk_vm_ci_hotspot_HotSpotConstantPool, Jvmci) \
|
||||
do_klass(HotSpotJVMCIMetaAccessContext_klass, jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext, Jvmci) \
|
||||
do_klass(HotSpotJVMCIRuntime_klass, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime, Jvmci) \
|
||||
do_klass(HotSpotSpeculationLog_klass, jdk_vm_ci_hotspot_HotSpotSpeculationLog, Jvmci) \
|
||||
do_klass(HotSpotCompilationRequestResult_klass, jdk_vm_ci_hotspot_HotSpotCompilationRequestResult, Jvmci) \
|
||||
do_klass(VMField_klass, jdk_vm_ci_hotspot_VMField, Jvmci) \
|
||||
do_klass(VMFlag_klass, jdk_vm_ci_hotspot_VMFlag, Jvmci) \
|
||||
do_klass(VMIntrinsicMethod_klass, jdk_vm_ci_hotspot_VMIntrinsicMethod, Jvmci) \
|
||||
do_klass(Assumptions_ConcreteMethod_klass, jdk_vm_ci_meta_Assumptions_ConcreteMethod, Jvmci) \
|
||||
do_klass(Assumptions_NoFinalizableSubclass_klass, jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass, Jvmci) \
|
||||
do_klass(Assumptions_ConcreteSubtype_klass, jdk_vm_ci_meta_Assumptions_ConcreteSubtype, Jvmci) \
|
||||
do_klass(Assumptions_LeafType_klass, jdk_vm_ci_meta_Assumptions_LeafType, Jvmci) \
|
||||
do_klass(Assumptions_CallSiteTargetValue_klass, jdk_vm_ci_meta_Assumptions_CallSiteTargetValue, Jvmci) \
|
||||
do_klass(Architecture_klass, jdk_vm_ci_code_Architecture, Jvmci) \
|
||||
do_klass(TargetDescription_klass, jdk_vm_ci_code_TargetDescription, Jvmci) \
|
||||
do_klass(BytecodePosition_klass, jdk_vm_ci_code_BytecodePosition, Jvmci) \
|
||||
do_klass(DebugInfo_klass, jdk_vm_ci_code_DebugInfo, Jvmci) \
|
||||
do_klass(RegisterSaveLayout_klass, jdk_vm_ci_code_RegisterSaveLayout, Jvmci) \
|
||||
do_klass(BytecodeFrame_klass, jdk_vm_ci_code_BytecodeFrame, Jvmci) \
|
||||
do_klass(InstalledCode_klass, jdk_vm_ci_code_InstalledCode, Jvmci) \
|
||||
do_klass(code_Location_klass, jdk_vm_ci_code_Location, Jvmci) \
|
||||
do_klass(code_Register_klass, jdk_vm_ci_code_Register, Jvmci) \
|
||||
do_klass(RegisterValue_klass, jdk_vm_ci_code_RegisterValue, Jvmci) \
|
||||
do_klass(StackSlot_klass, jdk_vm_ci_code_StackSlot, Jvmci) \
|
||||
do_klass(StackLockValue_klass, jdk_vm_ci_code_StackLockValue, Jvmci) \
|
||||
do_klass(VirtualObject_klass, jdk_vm_ci_code_VirtualObject, Jvmci) \
|
||||
do_klass(site_Call_klass, jdk_vm_ci_code_site_Call, Jvmci) \
|
||||
do_klass(site_ConstantReference_klass, jdk_vm_ci_code_site_ConstantReference, Jvmci) \
|
||||
do_klass(site_DataPatch_klass, jdk_vm_ci_code_site_DataPatch, Jvmci) \
|
||||
do_klass(site_DataSectionReference_klass, jdk_vm_ci_code_site_DataSectionReference, Jvmci) \
|
||||
do_klass(site_ExceptionHandler_klass, jdk_vm_ci_code_site_ExceptionHandler, Jvmci) \
|
||||
do_klass(site_Mark_klass, jdk_vm_ci_code_site_Mark, Jvmci) \
|
||||
do_klass(site_Infopoint_klass, jdk_vm_ci_code_site_Infopoint, Jvmci) \
|
||||
do_klass(site_Site_klass, jdk_vm_ci_code_site_Site, Jvmci) \
|
||||
do_klass(site_InfopointReason_klass, jdk_vm_ci_code_site_InfopointReason, Jvmci) \
|
||||
do_klass(InspectedFrameVisitor_klass, jdk_vm_ci_code_stack_InspectedFrameVisitor, Jvmci) \
|
||||
do_klass(JavaConstant_klass, jdk_vm_ci_meta_JavaConstant, Jvmci) \
|
||||
do_klass(PrimitiveConstant_klass, jdk_vm_ci_meta_PrimitiveConstant, Jvmci) \
|
||||
do_klass(RawConstant_klass, jdk_vm_ci_meta_RawConstant, Jvmci) \
|
||||
do_klass(NullConstant_klass, jdk_vm_ci_meta_NullConstant, Jvmci) \
|
||||
do_klass(ExceptionHandler_klass, jdk_vm_ci_meta_ExceptionHandler, Jvmci) \
|
||||
do_klass(JavaKind_klass, jdk_vm_ci_meta_JavaKind, Jvmci) \
|
||||
do_klass(ValueKind_klass, jdk_vm_ci_meta_ValueKind, Jvmci) \
|
||||
do_klass(Value_klass, jdk_vm_ci_meta_Value, Jvmci)
|
||||
#define JVMCI_WK_KLASSES_DO(do_klass) \
|
||||
/* JVMCI classes. These are loaded on-demand. */ \
|
||||
do_klass(JVMCI_klass, jdk_vm_ci_runtime_JVMCI ) \
|
||||
do_klass(HotSpotCompiledCode_klass, jdk_vm_ci_hotspot_HotSpotCompiledCode ) \
|
||||
do_klass(HotSpotCompiledCode_Comment_klass, jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment ) \
|
||||
do_klass(HotSpotCompiledNmethod_klass, jdk_vm_ci_hotspot_HotSpotCompiledNmethod ) \
|
||||
do_klass(HotSpotForeignCallTarget_klass, jdk_vm_ci_hotspot_HotSpotForeignCallTarget ) \
|
||||
do_klass(HotSpotReferenceMap_klass, jdk_vm_ci_hotspot_HotSpotReferenceMap ) \
|
||||
do_klass(HotSpotInstalledCode_klass, jdk_vm_ci_hotspot_HotSpotInstalledCode ) \
|
||||
do_klass(HotSpotNmethod_klass, jdk_vm_ci_hotspot_HotSpotNmethod ) \
|
||||
do_klass(HotSpotResolvedJavaMethodImpl_klass, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl ) \
|
||||
do_klass(HotSpotResolvedObjectTypeImpl_klass, jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl ) \
|
||||
do_klass(HotSpotCompressedNullConstant_klass, jdk_vm_ci_hotspot_HotSpotCompressedNullConstant ) \
|
||||
do_klass(HotSpotObjectConstantImpl_klass, jdk_vm_ci_hotspot_HotSpotObjectConstantImpl ) \
|
||||
do_klass(HotSpotMetaspaceConstantImpl_klass, jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl ) \
|
||||
do_klass(HotSpotSentinelConstant_klass, jdk_vm_ci_hotspot_HotSpotSentinelConstant ) \
|
||||
do_klass(HotSpotStackFrameReference_klass, jdk_vm_ci_hotspot_HotSpotStackFrameReference ) \
|
||||
do_klass(HotSpotMetaData_klass, jdk_vm_ci_hotspot_HotSpotMetaData ) \
|
||||
do_klass(HotSpotConstantPool_klass, jdk_vm_ci_hotspot_HotSpotConstantPool ) \
|
||||
do_klass(HotSpotJVMCIMetaAccessContext_klass, jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext ) \
|
||||
do_klass(HotSpotJVMCIRuntime_klass, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime ) \
|
||||
do_klass(HotSpotSpeculationLog_klass, jdk_vm_ci_hotspot_HotSpotSpeculationLog ) \
|
||||
do_klass(HotSpotCompilationRequestResult_klass, jdk_vm_ci_hotspot_HotSpotCompilationRequestResult) \
|
||||
do_klass(VMField_klass, jdk_vm_ci_hotspot_VMField ) \
|
||||
do_klass(VMFlag_klass, jdk_vm_ci_hotspot_VMFlag ) \
|
||||
do_klass(VMIntrinsicMethod_klass, jdk_vm_ci_hotspot_VMIntrinsicMethod ) \
|
||||
do_klass(Assumptions_ConcreteMethod_klass, jdk_vm_ci_meta_Assumptions_ConcreteMethod ) \
|
||||
do_klass(Assumptions_NoFinalizableSubclass_klass, jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass ) \
|
||||
do_klass(Assumptions_ConcreteSubtype_klass, jdk_vm_ci_meta_Assumptions_ConcreteSubtype ) \
|
||||
do_klass(Assumptions_LeafType_klass, jdk_vm_ci_meta_Assumptions_LeafType ) \
|
||||
do_klass(Assumptions_CallSiteTargetValue_klass, jdk_vm_ci_meta_Assumptions_CallSiteTargetValue ) \
|
||||
do_klass(Architecture_klass, jdk_vm_ci_code_Architecture ) \
|
||||
do_klass(TargetDescription_klass, jdk_vm_ci_code_TargetDescription ) \
|
||||
do_klass(BytecodePosition_klass, jdk_vm_ci_code_BytecodePosition ) \
|
||||
do_klass(DebugInfo_klass, jdk_vm_ci_code_DebugInfo ) \
|
||||
do_klass(RegisterSaveLayout_klass, jdk_vm_ci_code_RegisterSaveLayout ) \
|
||||
do_klass(BytecodeFrame_klass, jdk_vm_ci_code_BytecodeFrame ) \
|
||||
do_klass(InstalledCode_klass, jdk_vm_ci_code_InstalledCode ) \
|
||||
do_klass(code_Location_klass, jdk_vm_ci_code_Location ) \
|
||||
do_klass(code_Register_klass, jdk_vm_ci_code_Register ) \
|
||||
do_klass(RegisterValue_klass, jdk_vm_ci_code_RegisterValue ) \
|
||||
do_klass(StackSlot_klass, jdk_vm_ci_code_StackSlot ) \
|
||||
do_klass(StackLockValue_klass, jdk_vm_ci_code_StackLockValue ) \
|
||||
do_klass(VirtualObject_klass, jdk_vm_ci_code_VirtualObject ) \
|
||||
do_klass(site_Call_klass, jdk_vm_ci_code_site_Call ) \
|
||||
do_klass(site_ConstantReference_klass, jdk_vm_ci_code_site_ConstantReference ) \
|
||||
do_klass(site_DataPatch_klass, jdk_vm_ci_code_site_DataPatch ) \
|
||||
do_klass(site_DataSectionReference_klass, jdk_vm_ci_code_site_DataSectionReference ) \
|
||||
do_klass(site_ExceptionHandler_klass, jdk_vm_ci_code_site_ExceptionHandler ) \
|
||||
do_klass(site_Mark_klass, jdk_vm_ci_code_site_Mark ) \
|
||||
do_klass(site_Infopoint_klass, jdk_vm_ci_code_site_Infopoint ) \
|
||||
do_klass(site_Site_klass, jdk_vm_ci_code_site_Site ) \
|
||||
do_klass(site_InfopointReason_klass, jdk_vm_ci_code_site_InfopointReason ) \
|
||||
do_klass(InspectedFrameVisitor_klass, jdk_vm_ci_code_stack_InspectedFrameVisitor ) \
|
||||
do_klass(JavaConstant_klass, jdk_vm_ci_meta_JavaConstant ) \
|
||||
do_klass(PrimitiveConstant_klass, jdk_vm_ci_meta_PrimitiveConstant ) \
|
||||
do_klass(RawConstant_klass, jdk_vm_ci_meta_RawConstant ) \
|
||||
do_klass(NullConstant_klass, jdk_vm_ci_meta_NullConstant ) \
|
||||
do_klass(ExceptionHandler_klass, jdk_vm_ci_meta_ExceptionHandler ) \
|
||||
do_klass(JavaKind_klass, jdk_vm_ci_meta_JavaKind ) \
|
||||
do_klass(ValueKind_klass, jdk_vm_ci_meta_ValueKind ) \
|
||||
do_klass(Value_klass, jdk_vm_ci_meta_Value )
|
||||
#endif
|
||||
|
||||
#endif // SHARE_VM_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
|
||||
|
@ -32,7 +32,7 @@
|
||||
DoNothingClosure do_nothing_cl;
|
||||
|
||||
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) {
|
||||
|
@ -127,12 +127,13 @@ class CLDClosure : public Closure {
|
||||
|
||||
class CLDToOopClosure : public CLDClosure {
|
||||
OopClosure* _oop_closure;
|
||||
bool _must_claim_cld;
|
||||
int _cld_claim;
|
||||
|
||||
public:
|
||||
CLDToOopClosure(OopClosure* oop_closure, bool must_claim_cld = true) :
|
||||
CLDToOopClosure(OopClosure* oop_closure,
|
||||
int cld_claim) :
|
||||
_oop_closure(oop_closure),
|
||||
_must_claim_cld(must_claim_cld) {}
|
||||
_cld_claim(cld_claim) {}
|
||||
|
||||
void do_cld(ClassLoaderData* cld);
|
||||
};
|
||||
|
@ -39,8 +39,7 @@
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
inline void MetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) {
|
||||
bool claim = true; // Must claim the class loader data before processing.
|
||||
cld->oops_do(this, claim);
|
||||
cld->oops_do(this, ClassLoaderData::_claim_strong);
|
||||
}
|
||||
|
||||
inline void MetadataVisitingOopIterateClosure::do_klass(Klass* k) {
|
||||
|
@ -1195,7 +1195,7 @@ public:
|
||||
|
||||
// Iterate over all oop fields and metadata.
|
||||
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.
|
||||
template <typename T, class OopClosureType>
|
||||
@ -1205,7 +1205,7 @@ public:
|
||||
// Reverse iteration
|
||||
// Iterate over all oop fields and metadata.
|
||||
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:
|
||||
// Iterate over all oop fields in the oop maps.
|
||||
@ -1225,7 +1225,7 @@ public:
|
||||
|
||||
// Iterate over all oop fields and metadata.
|
||||
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:
|
||||
// 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>
|
||||
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)) {
|
||||
Devirtualizer::do_klass(closure, this);
|
||||
}
|
||||
|
||||
oop_oop_iterate_oop_maps<T>(obj, closure);
|
||||
|
||||
return size_helper();
|
||||
}
|
||||
|
||||
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),
|
||||
"Code to handle metadata is not implemented");
|
||||
|
||||
oop_oop_iterate_oop_maps_reverse<T>(obj, closure);
|
||||
|
||||
return size_helper();
|
||||
}
|
||||
|
||||
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 (mr.contains(obj)) {
|
||||
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);
|
||||
|
||||
return size_helper();
|
||||
}
|
||||
|
||||
#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 {
|
||||
if (this == NULL) {
|
||||
st->print_cr("NULL");
|
||||
} else {
|
||||
st->print("Symbol: '");
|
||||
print_symbol_on(st);
|
||||
st->print("'");
|
||||
st->print(" count %d", refcount());
|
||||
}
|
||||
st->print("Symbol: '");
|
||||
print_symbol_on(st);
|
||||
st->print("'");
|
||||
st->print(" count %d", refcount());
|
||||
}
|
||||
|
||||
// The print_value functions are present in all builds, to support the
|
||||
// disassembler and error reporting.
|
||||
void Symbol::print_value_on(outputStream* st) const {
|
||||
if (this == NULL) {
|
||||
st->print("NULL");
|
||||
} else {
|
||||
st->print("'");
|
||||
for (int i = 0; i < utf8_length(); i++) {
|
||||
st->print("%c", char_at(i));
|
||||
}
|
||||
st->print("'");
|
||||
st->print("'");
|
||||
for (int i = 0; i < utf8_length(); i++) {
|
||||
st->print("%c", char_at(i));
|
||||
}
|
||||
st->print("'");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------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 {
|
||||
return RegMask::Empty;
|
||||
|
@ -96,6 +96,7 @@ public:
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
virtual const RegMask &out_RegMask() const;
|
||||
bool try_clean_mem_phi(PhaseGVN *phase);
|
||||
bool optimize_trichotomy(PhaseIterGVN* igvn);
|
||||
};
|
||||
|
||||
//------------------------------JProjNode--------------------------------------
|
||||
|
@ -899,6 +899,13 @@ Node* Node::uncast() const {
|
||||
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.
|
||||
Node* Node::find_out_with(int opcode) {
|
||||
for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
|
||||
|
@ -457,10 +457,9 @@ protected:
|
||||
|
||||
// Strip away casting. (It is depth-limited.)
|
||||
Node* uncast() const;
|
||||
// Return whether two Nodes are equivalent, after stripping casting.
|
||||
bool eqv_uncast(const Node* n) const {
|
||||
return (this->uncast() == n->uncast());
|
||||
}
|
||||
// Return whether two Nodes are equivalent, after stripping casting
|
||||
// and GC barriers.
|
||||
bool eqv_uncast(const Node* n) const;
|
||||
|
||||
// Find out of current node that matches opcode.
|
||||
Node* find_out_with(int opcode);
|
||||
|
@ -1252,6 +1252,24 @@ void BoolTest::dump_on(outputStream *st) const {
|
||||
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::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
|
||||
// condition codes, the high bit flips the sense of the result.
|
||||
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;
|
||||
BoolTest( mask btm ) : _test(btm) {}
|
||||
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_greater( ) const { return _test == BoolTest::gt || _test == BoolTest::ge; }
|
||||
void dump_on(outputStream *st) const;
|
||||
mask merge(BoolTest other) const;
|
||||
};
|
||||
|
||||
//------------------------------BoolNode---------------------------------------
|
||||
|
@ -3736,8 +3736,8 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i
|
||||
{
|
||||
memset(info, 0, info_size);
|
||||
|
||||
info->jvm_version = Abstract_VM_Version::jvm_version();
|
||||
info->patch_version = Abstract_VM_Version::vm_patch_version();
|
||||
info->jvm_version = VM_Version::jvm_version();
|
||||
info->patch_version = VM_Version::vm_patch_version();
|
||||
|
||||
// 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
|
||||
|
@ -919,7 +919,7 @@ JvmtiEnv::GetAllThreads(jint* threads_count_ptr, jthread** threads_ptr) {
|
||||
thread_objs = NEW_RESOURCE_ARRAY(Handle, nthreads);
|
||||
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));
|
||||
}
|
||||
|
||||
@ -1144,16 +1144,14 @@ JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) {
|
||||
Handle context_class_loader;
|
||||
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()));
|
||||
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());
|
||||
oop loader = java_lang_Thread::context_class_loader(thread_obj());
|
||||
context_class_loader = Handle(current_thread, loader);
|
||||
|
||||
oop loader = java_lang_Thread::context_class_loader(thread_obj());
|
||||
context_class_loader = Handle(current_thread, loader);
|
||||
}
|
||||
{ const char *n;
|
||||
|
||||
if (name() != NULL) {
|
||||
@ -1402,13 +1400,10 @@ JvmtiEnv::GetThreadGroupInfo(jthreadGroup group, jvmtiThreadGroupInfo* info_ptr)
|
||||
bool is_daemon;
|
||||
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()));
|
||||
is_daemon = java_lang_ThreadGroup::is_daemon(group_obj());
|
||||
max_priority = java_lang_ThreadGroup::maxPriority(group_obj());
|
||||
}
|
||||
name = java_lang_ThreadGroup::name(group_obj());
|
||||
parent_group = Handle(current_thread, java_lang_ThreadGroup::parent(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->max_priority = max_priority;
|
||||
@ -1448,7 +1443,7 @@ JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jth
|
||||
Handle group_hdl(current_thread, group_obj);
|
||||
|
||||
{ // 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());
|
||||
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());
|
||||
assert(nthreads <= threads->length(), "too many threads");
|
||||
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);
|
||||
assert(thread_obj != NULL, "thread_obj is 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());
|
||||
assert(ngroups <= groups->length(), "too many groups");
|
||||
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);
|
||||
assert(group_obj != NULL, "group_obj != NULL");
|
||||
group_objs[i] = Handle(current_thread, group_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // ThreadGroup unlocked here
|
||||
|
||||
// have to make global handles outside of Threads_lock
|
||||
*group_count_ptr = ngroups;
|
||||
*thread_count_ptr = nthreads;
|
||||
*threads_ptr = new_jthreadArray(nthreads, thread_objs);
|
||||
@ -3246,7 +3240,7 @@ JvmtiEnv::DestroyRawMonitor(JvmtiRawMonitor * rmonitor) {
|
||||
// objects that are locked.
|
||||
int r;
|
||||
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);
|
||||
assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked");
|
||||
if (r != ObjectMonitor::OM_OK) { // robustness
|
||||
@ -3676,7 +3670,7 @@ JvmtiEnv::GetSystemProperties(jint* count_ptr, char*** property_ptr) {
|
||||
strcpy(*tmp_value, key);
|
||||
} else {
|
||||
// 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);
|
||||
|
@ -1044,7 +1044,7 @@ class JvmtiObjectAllocEventMark : public JvmtiClassEventMark {
|
||||
public:
|
||||
JvmtiObjectAllocEventMark(JavaThread *thread, oop obj) : JvmtiClassEventMark(thread, oop_to_klass(obj)) {
|
||||
_jobj = (jobject)to_jobject(obj);
|
||||
_size = obj->size() * wordSize;
|
||||
_size = Universe::heap()->obj_size(obj) * wordSize;
|
||||
};
|
||||
jobject jni_jobject() { return _jobj; }
|
||||
jlong size() { return _size; }
|
||||
|
@ -105,7 +105,7 @@ class JvmtiTagHashmapEntry : public CHeapObj<mtInternal> {
|
||||
}
|
||||
|
||||
inline bool equals(oop object) {
|
||||
return object == object_peek();
|
||||
return oopDesc::equals(object, object_peek());
|
||||
}
|
||||
|
||||
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
|
||||
// with aligned addresses)
|
||||
key = Access<>::resolve(key);
|
||||
unsigned int addr = (unsigned int)(cast_from_oop<intptr_t>(key));
|
||||
#ifdef _LP64
|
||||
return (addr >> 3) % size;
|
||||
|
@ -106,6 +106,9 @@ char* Arguments::SharedArchivePath = NULL;
|
||||
AgentLibraryList Arguments::_libraryList;
|
||||
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;
|
||||
exit_hook_t Arguments::_exit_hook = NULL;
|
||||
vfprintf_hook_t Arguments::_vfprintf_hook = NULL;
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
// 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" {
|
||||
typedef void (JNICALL *abort_hook_t)(void);
|
||||
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…
x
Reference in New Issue
Block a user