This commit is contained in:
J. Duke 2017-09-09 14:36:25 +02:00
commit 354e0fd809
148 changed files with 2295 additions and 3691 deletions

View File

@ -446,3 +446,4 @@ d2982a786f53814367698e63efe6349c9128e1db jdk-9+180
b656dea9398ef601f7fc08d1a5157a560e0ccbe0 jdk-9+181
682e2a6df836f4731f92eb2ddcd467075047f6ea jdk-10+20
90cdfe56f1543267a8005e638bd1b44551fda189 jdk-10+21
8625e8491887bfd4310b2cfc2b84bac26312ba20 jdk-10+22

View File

@ -209,6 +209,7 @@ JDKOPT_SETUP_CODE_COVERAGE
# Need toolchain to setup dtrace
HOTSPOT_SETUP_DTRACE
HOTSPOT_ENABLE_DISABLE_AOT
HOTSPOT_ENABLE_DISABLE_CDS
HOTSPOT_ENABLE_DISABLE_GTEST
###############################################################################

View File

@ -702,6 +702,7 @@ LIBCXX
FIXPATH_DETACH_FLAG
FIXPATH
BUILD_GTEST
ENABLE_CDS
ENABLE_AOT
GCOV_ENABLED
ZIP_EXTERNAL_DEBUG_SYMBOLS
@ -1191,6 +1192,7 @@ enable_zip_debug_info
enable_native_coverage
enable_dtrace
enable_aot
enable_cds
enable_hotspot_gtest
with_stdc__lib
with_msvcr_dll
@ -1999,6 +2001,8 @@ Optional Features:
enable ahead of time compilation feature. Default is
auto, where aot is enabled if all dependencies are
present.
--enable-cds[=yes/no] enable class data sharing feature in non-minimal VM.
Default is yes.
--disable-hotspot-gtest Disables building of the Hotspot unit tests
--disable-freetype-bundling
disable bundling of the freetype library with the
@ -2016,7 +2020,8 @@ Optional Features:
--disable-generate-classlist
forces enabling or disabling of the generation of a
CDS classlist at build time. Default is to generate
it when either the server or client JVMs are built.
it when either the server or client JVMs are built
and enable-cds is true.
--enable-sjavac use sjavac to do fast incremental compiles
[disabled]
--disable-javac-server disable javac server [enabled]
@ -4295,7 +4300,7 @@ pkgadd_help() {
# All valid JVM features, regardless of platform
VALID_JVM_FEATURES="compiler1 compiler2 zero shark minimal dtrace jvmti jvmci \
graal fprof vm-structs jni-check services management all-gcs nmt cds \
graal vm-structs jni-check services management all-gcs nmt cds \
static-build link-time-opt aot"
# All valid JVM variants
@ -4345,6 +4350,11 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom"
#
################################################################################
# Allow to disable CDS
#
###############################################################################
# Set up all JVM features for each JVM variant.
#
@ -5151,7 +5161,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
DATE_WHEN_GENERATED=1504187184
DATE_WHEN_GENERATED=1504441177
###############################################################################
#
@ -54216,6 +54226,23 @@ $as_echo "no, forced" >&6; }
# Check whether --enable-cds was given.
if test "${enable_cds+set}" = set; then :
enableval=$enable_cds;
fi
if test "x$enable_cds" = "x" || test "x$enable_cds" = "xyes"; then
ENABLE_CDS="true"
elif test "x$enable_cds" = "xno"; then
ENABLE_CDS="false"
else
as_fn_error $? "Invalid value for --enable-cds: $enable_cds" "$LINENO" 5
fi
# Check whether --enable-hotspot-gtest was given.
if test "${enable_hotspot_gtest+set}" = set; then :
enableval=$enable_hotspot_gtest;
@ -65810,8 +65837,12 @@ $as_echo "yes, forced" >&6; }
fi
INCLUDE_GRAAL="true"
else
# By default enable graal build where AOT is available
if test "x$ENABLE_AOT" = "xtrue"; then
# By default enable graal build on linux-x64 or where AOT is available.
# graal build requires jvmci.
if test "x$JVM_FEATURES_jvmci" = "xjvmci" && \
(test "x$OPENJDK_TARGET_CPU" = "xx86_64" && \
test "x$OPENJDK_TARGET_OS" = "xlinux" || \
test "x$ENABLE_AOT" = "xtrue") ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
JVM_FEATURES_graal="graal"
@ -65856,7 +65887,10 @@ $as_echo "no" >&6; }
fi
# All variants but minimal (and custom) get these features
NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti fprof vm-structs jni-check services management all-gcs nmt cds"
NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti vm-structs jni-check services management all-gcs nmt"
if test "x$ENABLE_CDS" = "xtrue"; then
NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cds"
fi
# Enable features depending on variant.
JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci $JVM_FEATURES_aot $JVM_FEATURES_graal"
@ -65960,7 +65994,7 @@ fi
# Check if it's likely that it's possible to generate the classlist. Depending
# on exact jvm configuration it could be possible anyway.
if [[ " $JVM_VARIANTS " =~ " server " ]] || [[ " $JVM_VARIANTS " =~ " client " ]] ; then
if test "x$ENABLE_CDS" = "xtrue" && ( [[ " $JVM_VARIANTS " =~ " server " ]] || [[ " $JVM_VARIANTS " =~ " client " ]] ); then
ENABLE_GENERATE_CLASSLIST_POSSIBLE="true"
else
ENABLE_GENERATE_CLASSLIST_POSSIBLE="false"
@ -65973,8 +66007,8 @@ $as_echo_n "checking if the CDS classlist generation should be enabled... " >&6;
$as_echo "yes, forced" >&6; }
ENABLE_GENERATE_CLASSLIST="true"
if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xfalse"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS" >&5
$as_echo "$as_me: WARNING: Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS and enable-cds=$ENABLE_CDS" >&5
$as_echo "$as_me: WARNING: Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS and enable-cds=$ENABLE_CDS" >&2;}
fi
elif test "x$enable_generate_classlist" = "xno"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5

View File

@ -25,7 +25,7 @@
# All valid JVM features, regardless of platform
VALID_JVM_FEATURES="compiler1 compiler2 zero shark minimal dtrace jvmti jvmci \
graal fprof vm-structs jni-check services management all-gcs nmt cds \
graal vm-structs jni-check services management all-gcs nmt cds \
static-build link-time-opt aot"
# All valid JVM variants
@ -240,6 +240,25 @@ AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_AOT],
AC_SUBST(ENABLE_AOT)
])
################################################################################
# Allow to disable CDS
#
AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_CDS],
[
AC_ARG_ENABLE([cds], [AS_HELP_STRING([--enable-cds@<:@=yes/no@:>@],
[enable class data sharing feature in non-minimal VM. Default is yes.])])
if test "x$enable_cds" = "x" || test "x$enable_cds" = "xyes"; then
ENABLE_CDS="true"
elif test "x$enable_cds" = "xno"; then
ENABLE_CDS="false"
else
AC_MSG_ERROR([Invalid value for --enable-cds: $enable_cds])
fi
AC_SUBST(ENABLE_CDS)
])
###############################################################################
# Set up all JVM features for each JVM variant.
#
@ -335,8 +354,12 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
fi
INCLUDE_GRAAL="true"
else
# By default enable graal build where AOT is available
if test "x$ENABLE_AOT" = "xtrue"; then
# By default enable graal build on linux-x64 or where AOT is available.
# graal build requires jvmci.
if test "x$JVM_FEATURES_jvmci" = "xjvmci" && \
(test "x$OPENJDK_TARGET_CPU" = "xx86_64" && \
test "x$OPENJDK_TARGET_OS" = "xlinux" || \
test "x$ENABLE_AOT" = "xtrue") ; then
AC_MSG_RESULT([yes])
JVM_FEATURES_graal="graal"
INCLUDE_GRAAL="true"
@ -374,7 +397,10 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
fi
# All variants but minimal (and custom) get these features
NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti fprof vm-structs jni-check services management all-gcs nmt cds"
NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti vm-structs jni-check services management all-gcs nmt"
if test "x$ENABLE_CDS" = "xtrue"; then
NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cds"
fi
# Enable features depending on variant.
JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci $JVM_FEATURES_aot $JVM_FEATURES_graal"

View File

@ -496,11 +496,12 @@ AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST],
[
AC_ARG_ENABLE([generate-classlist], [AS_HELP_STRING([--disable-generate-classlist],
[forces enabling or disabling of the generation of a CDS classlist at build time.
Default is to generate it when either the server or client JVMs are built.])])
Default is to generate it when either the server or client JVMs are built and
enable-cds is true.])])
# Check if it's likely that it's possible to generate the classlist. Depending
# on exact jvm configuration it could be possible anyway.
if HOTSPOT_CHECK_JVM_VARIANT(server) || HOTSPOT_CHECK_JVM_VARIANT(client); then
if test "x$ENABLE_CDS" = "xtrue" && (HOTSPOT_CHECK_JVM_VARIANT(server) || HOTSPOT_CHECK_JVM_VARIANT(client)); then
ENABLE_GENERATE_CLASSLIST_POSSIBLE="true"
else
ENABLE_GENERATE_CLASSLIST_POSSIBLE="false"
@ -511,7 +512,7 @@ AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST],
AC_MSG_RESULT([yes, forced])
ENABLE_GENERATE_CLASSLIST="true"
if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xfalse"; then
AC_MSG_WARN([Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS])
AC_MSG_WARN([Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS and enable-cds=$ENABLE_CDS])
fi
elif test "x$enable_generate_classlist" = "xno"; then
AC_MSG_RESULT([no, forced])

View File

@ -818,6 +818,49 @@ var getJibProfilesProfiles = function (input, common, data) {
}
},
"macosx-x64-open": {
artifacts: {
jdk: {
local: "bundles/\\(jdk.*bin.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/osx-x64/jdk-" + data.version
+ "_osx-x64_bin.tar.gz",
"bundles/openjdk/GPL/osx-x64/\\1"
],
subdir: "jdk-" + data.version
},
jre: {
local: "bundles/\\(jre.*bin.tar.gz\\)",
remote: "bundles/openjdk/GPL/osx-x64/\\1",
},
test: {
local: "bundles/\\(jdk.*bin-tests.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/osx-x64/jdk-" + data.version
+ "_osx-x64_bin-tests.tar.gz",
"bundles/openjdk/GPL/osx-x64/\\1"
]
},
jdk_symbols: {
local: "bundles/\\(jdk.*bin-symbols.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/osx-x64/jdk-" + data.version
+ "_osx-x64_bin-symbols.tar.gz",
"bundles/openjdk/GPL/osx-x64/\\1"
],
subdir: "jdk-" + data.version
},
jre_symbols: {
local: "bundles/\\(jre.*bin-symbols.tar.gz\\)",
remote: "bundles/openjdk/GPL/osx-x64/\\1",
},
doc_api_spec: {
local: "bundles/\\(jdk.*doc-api-spec.tar.gz\\)",
remote: "bundles/openjdk/GPL/osx-x64/\\1",
},
}
},
"windows-x86-open": {
artifacts: {
jdk: {
@ -884,10 +927,11 @@ var getJibProfilesProfiles = function (input, common, data) {
profiles["linux-x64-ri"] = clone(profiles["linux-x64-open"]);
profiles["linux-x86-ri"] = clone(profiles["linux-x86-open"]);
profiles["linux-x86-ri-debug"] = clone(profiles["linux-x86-open-debug"]);
profiles["macosx-x64-ri"] = clone(profiles["macosx-x64-open"]);
profiles["windows-x86-ri"] = clone(profiles["windows-x86-open"]);
// Generate artifacts for ri profiles
[ "linux-x64-ri", "linux-x86-ri", "linux-x86-ri-debug", "windows-x86-ri" ]
[ "linux-x64-ri", "linux-x86-ri", "linux-x86-ri-debug", "macosx-x64-ri", "windows-x86-ri" ]
.forEach(function (name) {
// Rewrite all remote dirs to "bundles/openjdk/BCL/..."
for (artifactName in profiles[name].artifacts) {

View File

@ -606,3 +606,4 @@ d7baadc223e790c08bc69bf7e553bce65b4e7e40 jdk-9+180
4a443796f6f57842d6a0434ac27ca3d1033ccc20 jdk-9+181
e93ed1a092409351c90b3a76d80b9aa8b44d5e6a jdk-10+20
bdb2dbc43ff065b74c2121bdfb0d6e1fa8684b73 jdk-10+21
71337910df60ff2b62daf10357f553def25e2d0b jdk-10+22

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2013, 2017, 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
@ -88,11 +88,6 @@ ifneq ($(call check-jvm-feature, jvmci), true)
JVM_EXCLUDE_FILES += jvmciCodeInstaller_$(HOTSPOT_TARGET_CPU_ARCH).cpp
endif
ifneq ($(call check-jvm-feature, fprof), true)
JVM_CFLAGS_FEATURES += -DINCLUDE_FPROF=0
JVM_EXCLUDE_FILES += fprofiler.cpp
endif
ifneq ($(call check-jvm-feature, vm-structs), true)
JVM_CFLAGS_FEATURES += -DINCLUDE_VM_STRUCTS=0
JVM_EXCLUDE_FILES += vmStructs.cpp

View File

@ -12614,7 +12614,7 @@ instruct ubfxwI(iRegINoSp dst, iRegIorL2I src, immI rshift, immI_bitmask mask)
match(Set dst (AndI (URShiftI src rshift) mask));
ins_cost(INSN_COST);
format %{ "ubfxw $dst, $src, $mask" %}
format %{ "ubfxw $dst, $src, $rshift, $mask" %}
ins_encode %{
int rshift = $rshift$$constant;
long mask = $mask$$constant;
@ -12629,7 +12629,7 @@ instruct ubfxL(iRegLNoSp dst, iRegL src, immI rshift, immL_bitmask mask)
match(Set dst (AndL (URShiftL src rshift) mask));
ins_cost(INSN_COST);
format %{ "ubfx $dst, $src, $mask" %}
format %{ "ubfx $dst, $src, $rshift, $mask" %}
ins_encode %{
int rshift = $rshift$$constant;
long mask = $mask$$constant;
@ -12647,7 +12647,7 @@ instruct ubfxIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI rshift, immI_bitmask m
match(Set dst (ConvI2L (AndI (URShiftI src rshift) mask)));
ins_cost(INSN_COST * 2);
format %{ "ubfx $dst, $src, $mask" %}
format %{ "ubfx $dst, $src, $rshift, $mask" %}
ins_encode %{
int rshift = $rshift$$constant;
long mask = $mask$$constant;

View File

@ -183,7 +183,7 @@ define(`BFX_INSN',
match(Set dst (And$1 ($2$1 src rshift) mask));
ins_cost(INSN_COST);
format %{ "$3 $dst, $src, $mask" %}
format %{ "$3 $dst, $src, $rshift, $mask" %}
ins_encode %{
int rshift = $rshift$$constant;
long mask = $mask$$constant;
@ -203,7 +203,7 @@ instruct ubfxIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI rshift, immI_bitmask m
match(Set dst (ConvI2L (AndI (URShiftI src rshift) mask)));
ins_cost(INSN_COST * 2);
format %{ "ubfx $dst, $src, $mask" %}
format %{ "ubfx $dst, $src, $rshift, $mask" %}
ins_encode %{
int rshift = $rshift$$constant;
long mask = $mask$$constant;

View File

@ -3630,6 +3630,12 @@ void MacroAssembler::store_heap_oop_null(Address dst) {
}
#if INCLUDE_ALL_GCS
/*
* g1_write_barrier_pre -- G1GC pre-write barrier for store of new_val at
* store_addr.
*
* Allocates rscratch1
*/
void MacroAssembler::g1_write_barrier_pre(Register obj,
Register pre_val,
Register thread,
@ -3645,10 +3651,8 @@ void MacroAssembler::g1_write_barrier_pre(Register obj,
Label done;
Label runtime;
assert(pre_val != noreg, "check this code");
if (obj != noreg)
assert_different_registers(obj, pre_val, tmp);
assert_different_registers(obj, pre_val, tmp, rscratch1);
assert(pre_val != noreg && tmp != noreg, "expecting a register");
Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_active()));
@ -3722,12 +3726,22 @@ void MacroAssembler::g1_write_barrier_pre(Register obj,
bind(done);
}
/*
* g1_write_barrier_post -- G1GC post-write barrier for store of new_val at
* store_addr
*
* Allocates rscratch1
*/
void MacroAssembler::g1_write_barrier_post(Register store_addr,
Register new_val,
Register thread,
Register tmp,
Register tmp2) {
assert(thread == rthread, "must be");
assert_different_registers(store_addr, new_val, thread, tmp, tmp2,
rscratch1);
assert(store_addr != noreg && new_val != noreg && tmp != noreg
&& tmp2 != noreg, "expecting a register");
Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
DirtyCardQueue::byte_offset_of_index()));

View File

@ -2067,7 +2067,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ g1_write_barrier_pre(noreg /* obj */,
r0 /* pre_val */,
rthread /* thread */,
rscratch1 /* tmp */,
rscratch2 /* tmp */,
true /* tosca_live */,
true /* expand_call */);
}

View File

@ -170,7 +170,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm,
// G1 barrier needs uncompressed oop for region cross check.
Register new_val = val;
if (UseCompressedOops) {
new_val = rscratch1;
new_val = rscratch2;
__ mov(new_val, val);
}
__ store_heap_oop(Address(r3, 0), val);

View File

@ -292,7 +292,7 @@ void MacroAssembler::verify_thread() {
if (VerifyThread) {
// NOTE: this chops off the heads of the 64-bit O registers.
// make sure G2_thread contains the right value
save_frame_and_mov(0, Lmethod, Lmethod); // to avoid clobbering O0 (and propagate Lmethod for -Xprof)
save_frame_and_mov(0, Lmethod, Lmethod); // to avoid clobbering O0 (and propagate Lmethod)
mov(G1, L1); // avoid clobbering G1
// G2 saved below
mov(G3, L3); // avoid clobbering G3
@ -398,7 +398,7 @@ void MacroAssembler::reset_last_Java_frame(void) {
#ifdef ASSERT
// check that it WAS previously set
save_frame_and_mov(0, Lmethod, Lmethod); // Propagate Lmethod to helper frame for -Xprof
save_frame_and_mov(0, Lmethod, Lmethod); // Propagate Lmethod to helper frame
ld_ptr(sp_addr, L0);
tst(L0);
breakpoint_trap(Assembler::zero, Assembler::ptr_cc);
@ -618,7 +618,7 @@ void MacroAssembler::set_vm_result(Register oop_result) {
# ifdef ASSERT
// Check that we are not overwriting any other oop.
save_frame_and_mov(0, Lmethod, Lmethod); // Propagate Lmethod for -Xprof
save_frame_and_mov(0, Lmethod, Lmethod); // Propagate Lmethod
ld_ptr(vm_result_addr, L0);
tst(L0);
restore();

View File

@ -2928,7 +2928,7 @@ void TemplateTable::invokevirtual(int byte_no) {
__ br(Assembler::zero, false, Assembler::pt, notFinal);
__ delayed()->and3(Rret, 0xFF, G4_scratch); // gets number of parameters
if (RewriteBytecodes && !UseSharedSpaces) {
if (RewriteBytecodes && !UseSharedSpaces && !DumpSharedSpaces) {
patch_bytecode(Bytecodes::_fast_invokevfinal, Rscratch, Rtemp);
}

View File

@ -187,11 +187,10 @@ public final class BinaryContainer implements SymbolTable {
{"StubRoutines::_arrayof_oop_disjoint_arraycopy", "_aot_stub_routines_arrayof_oop_disjoint_arraycopy"},
{"StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit", "_aot_stub_routines_arrayof_oop_disjoint_arraycopy_uninit"},
{"StubRoutines::_unsafe_arraycopy", "_aot_stub_routines_unsafe_arraycopy"},
{"StubRoutines::_checkcast_arraycopy", "_aot_stub_routines_checkcast_arraycopy"},
{"StubRoutines::_aescrypt_encryptBlock", "_aot_stub_routines_aescrypt_encryptBlock"},
{"StubRoutines::_aescrypt_decryptBlock", "_aot_stub_routines_aescrypt_decryptBlock"},
{"StubRoutines::_cipherBlockChaining_encryptAESCrypt", "_aot_stub_routines_cipherBlockChaining_encryptAESCrypt"},
@ -478,8 +477,8 @@ public final class BinaryContainer implements SymbolTable {
}
/**
* Creates a global symbol of the form {@code "A" + container name}.
* Note, linker on Windows does not allow names which start with '.'
* Creates a global symbol of the form {@code "A" + container name}. Note, linker on Windows
* does not allow names which start with '.'
*
* @param container container to create a symbol for
*/
@ -685,7 +684,8 @@ public final class BinaryContainer implements SymbolTable {
}
/**
* Add oop symbol by as follows. Extend the oop.got section with another slot for the VM to patch.
* Add oop symbol by as follows. Extend the oop.got section with another slot for the VM to
* patch.
*
* @param oopName name of the oop symbol
*/
@ -728,10 +728,9 @@ public final class BinaryContainer implements SymbolTable {
}
/**
* Add klass symbol by as follows.
* - Adding the symbol name to the metaspace.names section
* - Add the offset of the name in metaspace.names to metaspace.offsets
* - Extend the klasses.got section with another slot for the VM to patch
* Add klass symbol by as follows. - Adding the symbol name to the metaspace.names section - Add
* the offset of the name in metaspace.names to metaspace.offsets - Extend the klasses.got
* section with another slot for the VM to patch
*
* @param klassName name of the metaspace symbol
* @return the got offset in the klasses.got of the metaspace symbol

View File

@ -27,6 +27,8 @@ import java.util.ListIterator;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.GraalCompiler;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.CompilationIdentifier.Verbosity;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.hotspot.HotSpotBackend;
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
@ -127,7 +129,13 @@ final class AOTBackend {
ProfilingInfo profilingInfo = DefaultProfilingInfo.get(TriState.FALSE);
final boolean isImmutablePIC = true;
CompilationResult compilationResult = new CompilationResult(resolvedMethod.getName(), isImmutablePIC);
CompilationIdentifier id = new CompilationIdentifier() {
@Override
public String toString(Verbosity verbosity) {
return resolvedMethod.getName();
}
};
CompilationResult compilationResult = new CompilationResult(id, isImmutablePIC);
return GraalCompiler.compileGraph(graph, resolvedMethod, providers, backend, graphBuilderSuite, OptimisticOptimizations.ALL, profilingInfo, getSuites(), getLirSuites(),
compilationResult, CompilationResultBuilderFactory.Default);

View File

@ -57,7 +57,9 @@ public @interface ClassSubstitution {
/**
* Determines if the substitutions are for classes that may not be part of the runtime.
* Substitutions for such classes are omitted if the original classes cannot be found.
* Substitutions for such classes are omitted if the original classes cannot be found. If
* multiple classes are specified using {@link #className()} and {@link #optional()} is false,
* then at least one of the classes is required to be reachable.
*/
boolean optional() default false;
}

View File

@ -90,7 +90,7 @@ public abstract class AssemblerTest extends GraalTest {
StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build();
CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention();
CompilationResult compResult = new CompilationResult();
CompilationResult compResult = new CompilationResult(graph.compilationId());
byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
compResult.setTargetCode(targetCode, targetCode.length);
compResult.setTotalFrameSize(0);

View File

@ -33,6 +33,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.util.EconomicSet;
@ -190,6 +191,8 @@ public class CompilationResult {
private final String name;
private final CompilationIdentifier compilationId;
/**
* The buffer containing the emitted machine code.
*/
@ -222,21 +225,26 @@ public class CompilationResult {
private boolean isImmutablePIC;
public CompilationResult() {
this(null, false);
public CompilationResult(CompilationIdentifier compilationId) {
this(compilationId, compilationId.toString(CompilationIdentifier.Verbosity.NAME), false);
}
public CompilationResult(CompilationIdentifier compilationId, String name) {
this(compilationId, name, false);
}
public CompilationResult(CompilationIdentifier compilationId, boolean isImmutablePIC) {
this(compilationId, null, isImmutablePIC);
}
public CompilationResult(CompilationIdentifier compilationId, String name, boolean isImmutablePIC) {
this.compilationId = compilationId;
this.name = name;
this.isImmutablePIC = isImmutablePIC;
}
public CompilationResult(String name) {
this(name, false);
}
public CompilationResult(boolean isImmutablePIC) {
this(null, isImmutablePIC);
}
public CompilationResult(String name, boolean isImmutablePIC) {
this.name = name;
this.isImmutablePIC = isImmutablePIC;
this(null, name);
}
@Override
@ -266,6 +274,7 @@ public class CompilationResult {
this.totalFrameSize == that.totalFrameSize &&
this.targetCodeSize == that.targetCodeSize &&
Objects.equals(this.name, that.name) &&
Objects.equals(this.compilationId, that.compilationId) &&
Objects.equals(this.annotations, that.annotations) &&
Objects.equals(this.dataSection, that.dataSection) &&
Objects.equals(this.exceptionHandlers, that.exceptionHandlers) &&
@ -670,6 +679,10 @@ public class CompilationResult {
return name;
}
public CompilationIdentifier getCompilationId() {
return compilationId;
}
public void setHasUnsafeAccess(boolean hasUnsafeAccess) {
checkOpen();
this.hasUnsafeAccess = hasUnsafeAccess;

View File

@ -949,7 +949,7 @@ public abstract class GraalCompilerTest extends GraalTest {
try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) {
CompilationPrinter printer = CompilationPrinter.begin(options, id, installedCodeOwner, INVOCATION_ENTRY_BCI);
CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(), id, options);
CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(graphToCompile.compilationId()), id, options);
printer.finish(compResult);
try (DebugContext.Scope s = debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult);
@ -1019,17 +1019,19 @@ public abstract class GraalCompilerTest extends GraalTest {
*/
protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) {
OptionValues options = graph == null ? getInitialOptions() : graph.getOptions();
return compile(installedCodeOwner, graph, new CompilationResult(), getOrCreateCompilationId(installedCodeOwner, graph), options);
CompilationIdentifier compilationId = getOrCreateCompilationId(installedCodeOwner, graph);
return compile(installedCodeOwner, graph, new CompilationResult(compilationId), compilationId, options);
}
protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationIdentifier compilationId) {
OptionValues options = graph == null ? getInitialOptions() : graph.getOptions();
return compile(installedCodeOwner, graph, new CompilationResult(), compilationId, options);
return compile(installedCodeOwner, graph, new CompilationResult(compilationId), compilationId, options);
}
protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, OptionValues options) {
assert graph == null || graph.getOptions() == options;
return compile(installedCodeOwner, graph, new CompilationResult(), getOrCreateCompilationId(installedCodeOwner, graph), options);
CompilationIdentifier compilationId = getOrCreateCompilationId(installedCodeOwner, graph);
return compile(installedCodeOwner, graph, new CompilationResult(compilationId), compilationId, options);
}
/**

View File

@ -64,7 +64,7 @@ public class InfopointReasonTest extends GraalCompilerTest {
final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod");
final StructuredGraph graph = parseEager(method, AllowAssumptions.YES);
final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(),
createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default);
createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default);
for (Infopoint sp : cr.getInfopoints()) {
assertNotNull(sp.reason);
if (sp instanceof Call) {
@ -86,7 +86,7 @@ public class InfopointReasonTest extends GraalCompilerTest {
assertTrue(graphLineSPs > 0);
PhaseSuite<HighTierContext> graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true));
final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(),
createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default);
createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default);
int lineSPs = 0;
for (Infopoint sp : cr.getInfopoints()) {
assertNotNull(sp.reason);

View File

@ -123,7 +123,7 @@ public class InvokeGraal {
ProfilingInfo profilingInfo = graph.getProfilingInfo(method);
/* The default class and configuration for compilation results. */
CompilationResult compilationResult = new CompilationResult();
CompilationResult compilationResult = new CompilationResult(graph.compilationId());
CompilationResultBuilderFactory factory = CompilationResultBuilderFactory.Default;
/* Invoke the whole Graal compilation pipeline. */

View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.graph.test;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeBitMap;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.options.OptionValues;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class NodeBitMapTest extends GraphTest {
@NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
static final class TestNode extends Node {
public static final NodeClass<TestNode> TYPE = NodeClass.create(TestNode.class);
protected TestNode() {
super(TYPE);
}
}
private Graph graph;
private TestNode[] nodes = new TestNode[100];
private NodeBitMap map;
@Before
public void before() {
// Need to initialize HotSpotGraalRuntime before any Node class is initialized.
Graal.getRuntime();
OptionValues options = getOptions();
graph = new Graph(options, getDebug(options));
for (int i = 0; i < nodes.length; i++) {
nodes[i] = graph.add(new TestNode());
}
map = graph.createNodeBitMap();
}
@Test
public void iterateEmpty() {
for (Node n : map) {
Assert.fail("no elements expected: " + n);
}
}
@Test
public void iterateMarkedNodes() {
map.mark(nodes[99]);
map.mark(nodes[0]);
map.mark(nodes[7]);
map.mark(nodes[1]);
map.mark(nodes[53]);
Iterator<Node> iter = map.iterator();
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[0], iter.next());
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[1], iter.next());
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[7], iter.next());
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[53], iter.next());
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[99], iter.next());
Assert.assertFalse(iter.hasNext());
}
@Test
public void deleteNodeWhileIterating() {
map.mark(nodes[99]);
map.mark(nodes[0]);
map.mark(nodes[7]);
map.mark(nodes[1]);
map.mark(nodes[53]);
Iterator<Node> iter = map.iterator();
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[0], iter.next());
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[1], iter.next());
nodes[7].markDeleted();
nodes[53].markDeleted();
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[99], iter.next());
Assert.assertFalse(iter.hasNext());
}
@Test
public void deleteAllNodesBeforeIterating() {
for (int i = 0; i < nodes.length; i++) {
map.mark(nodes[i]);
nodes[i].markDeleted();
}
Iterator<Node> iter = map.iterator();
Assert.assertFalse(iter.hasNext());
}
@Test
public void multipleHasNextInvocations() {
map.mark(nodes[7]);
Iterator<Node> iter = map.iterator();
Assert.assertTrue(iter.hasNext());
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[7], iter.next());
Assert.assertFalse(iter.hasNext());
}
@Test(expected = NoSuchElementException.class)
public void noSuchElement() {
map.iterator().next();
}
@Test(expected = ConcurrentModificationException.class)
public void concurrentModification() {
map.mark(nodes[7]);
map.mark(nodes[99]);
map.mark(nodes[0]);
map.mark(nodes[7]);
map.mark(nodes[1]);
map.mark(nodes[53]);
Iterator<Node> iter = map.iterator();
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[0], iter.next());
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[1], iter.next());
Assert.assertTrue(iter.hasNext());
nodes[7].markDeleted();
iter.next();
}
@Test
public void nextWithoutHasNext() {
map.mark(nodes[99]);
map.mark(nodes[0]);
map.mark(nodes[7]);
map.mark(nodes[1]);
map.mark(nodes[53]);
Iterator<Node> iter = map.iterator();
Assert.assertEquals(nodes[0], iter.next());
Assert.assertEquals(nodes[1], iter.next());
Assert.assertEquals(nodes[7], iter.next());
Assert.assertEquals(nodes[53], iter.next());
Assert.assertEquals(nodes[99], iter.next());
Assert.assertFalse(iter.hasNext());
}
@Test
public void markWhileIterating() {
map.mark(nodes[0]);
Iterator<Node> iter = map.iterator();
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[0], iter.next());
map.mark(nodes[7]);
Assert.assertTrue(iter.hasNext());
map.mark(nodes[1]);
Assert.assertEquals(nodes[7], iter.next());
map.mark(nodes[99]);
map.mark(nodes[53]);
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[53], iter.next());
Assert.assertTrue(iter.hasNext());
Assert.assertEquals(nodes[99], iter.next());
Assert.assertFalse(iter.hasNext());
}
}

View File

@ -23,22 +23,23 @@
package org.graalvm.compiler.graph;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.graalvm.compiler.graph.iterators.NodeIterable;
public final class NodeBitMap implements NodeIterable<Node> {
public final class NodeBitMap extends NodeIdAccessor implements NodeIterable<Node> {
private static final int SHIFT = 6;
private long[] bits;
private int nodeCount;
private int counter;
private final Graph graph;
public NodeBitMap(Graph graph) {
super(graph);
this.nodeCount = graph.nodeIdCount();
this.bits = new long[sizeForNodeCount(nodeCount)];
this.graph = graph;
}
private static int sizeForNodeCount(int nodeCount) {
@ -50,9 +51,9 @@ public final class NodeBitMap implements NodeIterable<Node> {
}
private NodeBitMap(NodeBitMap other) {
super(other.graph);
this.bits = other.bits.clone();
this.nodeCount = other.nodeCount;
this.graph = other.graph;
}
public Graph graph() {
@ -60,12 +61,12 @@ public final class NodeBitMap implements NodeIterable<Node> {
}
public boolean isNew(Node node) {
return node.id() >= nodeCount;
return getNodeId(node) >= nodeCount;
}
public boolean isMarked(Node node) {
assert check(node, false);
return isMarked(node.id());
return isMarked(getNodeId(node));
}
public boolean checkAndMarkInc(Node node) {
@ -84,33 +85,33 @@ public final class NodeBitMap implements NodeIterable<Node> {
public boolean isMarkedAndGrow(Node node) {
assert check(node, true);
int id = node.id();
int id = getNodeId(node);
checkGrow(id);
return isMarked(id);
}
public void mark(Node node) {
assert check(node, false);
int id = node.id();
int id = getNodeId(node);
bits[id >> SHIFT] |= (1L << id);
}
public void markAndGrow(Node node) {
assert check(node, true);
int id = node.id();
int id = getNodeId(node);
checkGrow(id);
bits[id >> SHIFT] |= (1L << id);
}
public void clear(Node node) {
assert check(node, false);
int id = node.id();
int id = getNodeId(node);
bits[id >> SHIFT] &= ~(1L << id);
}
public void clearAndGrow(Node node) {
assert check(node, true);
int id = node.id();
int id = getNodeId(node);
checkGrow(id);
bits[id >> SHIFT] &= ~(1L << id);
}
@ -181,15 +182,30 @@ public final class NodeBitMap implements NodeIterable<Node> {
}
}
protected int nextMarkedNodeId(int fromNodeId) {
protected Node nextMarkedNode(int fromNodeId) {
assert fromNodeId >= 0;
int wordIndex = fromNodeId >> SHIFT;
int wordsInUse = bits.length;
if (wordIndex < wordsInUse) {
long word = bits[wordIndex] & (0xFFFFFFFFFFFFFFFFL << fromNodeId);
long word = getPartOfWord(bits[wordIndex], fromNodeId);
while (true) {
if (word != 0) {
return wordIndex * Long.SIZE + Long.numberOfTrailingZeros(word);
while (word != 0) {
int bitIndex = Long.numberOfTrailingZeros(word);
int nodeId = wordIndex * Long.SIZE + bitIndex;
Node result = graph.getNode(nodeId);
if (result == null) {
// node was deleted -> clear the bit and continue searching
bits[wordIndex] = bits[wordIndex] & ~(1 << bitIndex);
int nextNodeId = nodeId + 1;
if ((nextNodeId & (Long.SIZE - 1)) == 0) {
// we reached the end of this word
break;
} else {
word = getPartOfWord(word, nextNodeId);
}
} else {
return result;
}
}
if (++wordIndex == wordsInUse) {
break;
@ -197,30 +213,56 @@ public final class NodeBitMap implements NodeIterable<Node> {
word = bits[wordIndex];
}
}
return -2;
return null;
}
private static long getPartOfWord(long word, int firstNodeIdToInclude) {
return word & (0xFFFFFFFFFFFFFFFFL << firstNodeIdToInclude);
}
/**
* This iterator only returns nodes that are marked in the {@link NodeBitMap} and are alive in
* the corresponding {@link Graph}.
*/
private class MarkedNodeIterator implements Iterator<Node> {
private int nextNodeId;
private int currentNodeId;
private Node currentNode;
MarkedNodeIterator() {
nextNodeId = -1;
currentNodeId = -1;
forward();
}
private void forward() {
nextNodeId = NodeBitMap.this.nextMarkedNodeId(nextNodeId + 1);
assert currentNode == null;
currentNode = NodeBitMap.this.nextMarkedNode(currentNodeId + 1);
if (currentNode != null) {
assert currentNode.isAlive();
currentNodeId = getNodeId(currentNode);
} else {
currentNodeId = -1;
}
}
@Override
public boolean hasNext() {
return nextNodeId >= 0;
if (currentNode == null && currentNodeId >= 0) {
forward();
}
return currentNodeId >= 0;
}
@Override
public Node next() {
Node result = graph.getNode(nextNodeId);
forward();
if (!hasNext()) {
throw new NoSuchElementException();
}
if (!currentNode.isAlive()) {
throw new ConcurrentModificationException("NodeBitMap was modified between the calls to hasNext() and next()");
}
Node result = currentNode;
currentNode = null;
return result;
}

View File

@ -1,117 +0,0 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.aarch64;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN;
import org.graalvm.compiler.core.aarch64.AArch64NodeLIRBuilder;
import org.graalvm.compiler.core.common.type.RawPointerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Value;
@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = SIZE_UNKNOWN)
public final class AArch64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable {
public static final NodeClass<AArch64RawNativeCallNode> TYPE = NodeClass.create(AArch64RawNativeCallNode.class);
protected final JavaConstant functionPointer;
@Input NodeInputList<ValueNode> args;
public AArch64RawNativeCallNode(JavaKind returnType, JavaConstant functionPointer, ValueNode[] args) {
super(TYPE, StampFactory.forKind(returnType));
this.functionPointer = functionPointer;
this.args = new NodeInputList<>(this, args);
}
private static class PointerType implements JavaType {
@Override
public String getName() {
return "void*";
}
@Override
public JavaType getComponentType() {
return null;
}
@Override
public JavaType getArrayClass() {
return null;
}
@Override
public JavaKind getJavaKind() {
// native pointers and java objects use the same registers in the calling convention
return JavaKind.Object;
}
@Override
public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
return null;
}
}
private static JavaType toJavaType(Stamp stamp, MetaAccessProvider metaAccess) {
if (stamp instanceof RawPointerStamp) {
return new PointerType();
} else {
return stamp.javaType(metaAccess);
}
}
@Override
public void generate(NodeLIRBuilderTool generator) {
AArch64NodeLIRBuilder gen = (AArch64NodeLIRBuilder) generator;
Value[] parameter = new Value[args.count()];
JavaType[] parameterTypes = new JavaType[args.count()];
for (int i = 0; i < args.count(); i++) {
parameter[i] = generator.operand(args.get(i));
parameterTypes[i] = toJavaType(args.get(i).stamp(), gen.getLIRGeneratorTool().getMetaAccess());
}
JavaType returnType = toJavaType(stamp(), gen.getLIRGeneratorTool().getMetaAccess());
CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.NativeCall, returnType, parameterTypes,
generator.getLIRGeneratorTool());
gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter);
if (this.getStackKind() != JavaKind.Void) {
generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn()));
}
}
}

View File

@ -1,130 +0,0 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
import org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder;
import org.graalvm.compiler.core.common.type.RawPointerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodeinfo.NodeSize;
import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Value;
@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = NodeSize.SIZE_UNKNOWN)
public final class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable {
public static final NodeClass<AMD64RawNativeCallNode> TYPE = NodeClass.create(AMD64RawNativeCallNode.class);
protected final JavaConstant functionPointer;
@Input NodeInputList<ValueNode> args;
public AMD64RawNativeCallNode(JavaKind returnType, JavaConstant functionPointer, ValueNode[] args) {
super(TYPE, StampFactory.forKind(returnType));
this.functionPointer = functionPointer;
this.args = new NodeInputList<>(this, args);
}
private static class PointerType implements JavaType {
@Override
public String getName() {
return "void*";
}
@Override
public JavaType getComponentType() {
return null;
}
@Override
public JavaType getArrayClass() {
return null;
}
@Override
public JavaKind getJavaKind() {
// native pointers and java objects use the same registers in the calling convention
return JavaKind.Object;
}
@Override
public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
return null;
}
}
private static JavaType toJavaType(Stamp stamp, MetaAccessProvider metaAccess) {
if (stamp instanceof RawPointerStamp) {
return new PointerType();
} else {
return stamp.javaType(metaAccess);
}
}
@Override
public void generate(NodeLIRBuilderTool generator) {
AMD64NodeLIRBuilder gen = (AMD64NodeLIRBuilder) generator;
Value[] parameter = new Value[args.count()];
JavaType[] parameterTypes = new JavaType[args.count()];
for (int i = 0; i < args.count(); i++) {
parameter[i] = generator.operand(args.get(i));
parameterTypes[i] = toJavaType(args.get(i).stamp(), gen.getLIRGeneratorTool().getMetaAccess());
}
JavaType returnType = toJavaType(stamp(), gen.getLIRGeneratorTool().getMetaAccess());
CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.NativeCall, returnType, parameterTypes,
generator.getLIRGeneratorTool());
gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args));
if (this.getStackKind() != JavaKind.Void) {
generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn()));
}
}
private static int countFloatingTypeArguments(NodeInputList<ValueNode> args) {
int count = 0;
for (ValueNode n : args) {
if (n.getStackKind() == JavaKind.Double || n.getStackKind() == JavaKind.Float) {
count++;
}
}
if (count > 8) {
return 8;
}
return count;
}
}

View File

@ -207,7 +207,6 @@ public class CheckGraalIntrinsics extends GraalTest {
"oracle/jrockit/jfr/Timing.counterTime()J",
"oracle/jrockit/jfr/VMJFR.classID0(Ljava/lang/Class;)J",
"oracle/jrockit/jfr/VMJFR.threadID()I",
"sun/misc/Unsafe.copyMemory(Ljava/lang/Object;JLjava/lang/Object;JJ)V",
"sun/nio/cs/ISO_8859_1$Encoder.encodeISOArray([CI[BII)I",
"sun/security/provider/DigestBase.implCompressMultiBlock([BII)I",
"sun/security/provider/SHA.implCompress([BI)V",
@ -273,7 +272,6 @@ public class CheckGraalIntrinsics extends GraalTest {
"jdk/internal/misc/Unsafe.compareAndExchangeShortRelease(Ljava/lang/Object;JSS)S",
"jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z",
"jdk/internal/misc/Unsafe.compareAndSetShort(Ljava/lang/Object;JSS)Z",
"jdk/internal/misc/Unsafe.copyMemory0(Ljava/lang/Object;JLjava/lang/Object;JJ)V",
"jdk/internal/misc/Unsafe.getAndAddByte(Ljava/lang/Object;JB)B",
"jdk/internal/misc/Unsafe.getAndAddShort(Ljava/lang/Object;JS)S",
"jdk/internal/misc/Unsafe.getAndSetByte(Ljava/lang/Object;JB)B",

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.test;
import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
import org.junit.Test;
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import sun.misc.Unsafe;
/**
* Tests the VM independent intrinsification of {@link Unsafe} methods.
*/
public class HotSpotUnsafeSubstitutionTest extends MethodSubstitutionTest {
public void testSubstitution(String testMethodName, Class<?> holder, String methodName, Class<?>[] parameterTypes, Object receiver, Object[] args1, Object[] args2) {
ResolvedJavaMethod testMethod = getResolvedJavaMethod(testMethodName);
ResolvedJavaMethod originalMethod = getResolvedJavaMethod(holder, methodName, parameterTypes);
// Force compilation
InstalledCode code = getCode(testMethod);
assert code != null;
// Verify that the original method and the substitution produce the same value
Object expected = invokeSafe(originalMethod, receiver, args1);
Object actual = invokeSafe(testMethod, null, args2);
assertDeepEquals(expected, actual);
// Verify that the generated code and the original produce the same value
expected = invokeSafe(originalMethod, receiver, args1);
actual = executeVarargsSafe(code, args2);
assertDeepEquals(expected, actual);
}
@Test
public void testUnsafeSubstitutions() throws Exception {
testGraph("unsafeCopyMemory");
}
public void unsafeCopyMemory(Object srcBase, long srcOffset, Object dstBase, long dstOffset, long bytes) {
UNSAFE.copyMemory(srcBase, srcOffset, dstBase, dstOffset, bytes);
}
public byte[] testCopyMemorySnippet(long src, int bytes) {
byte[] result = new byte[bytes];
UNSAFE.copyMemory(null, src, result, Unsafe.ARRAY_BYTE_BASE_OFFSET, bytes);
return result;
}
@Test
public void testCopyMemory() {
int size = 128;
long src = UNSAFE.allocateMemory(size);
for (int i = 0; i < size; i++) {
UNSAFE.putByte(null, src + i, (byte) i);
}
test("testCopyMemorySnippet", src, size);
}
}

View File

@ -64,9 +64,9 @@ import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.SuitesProvider;
import org.graalvm.compiler.word.Word;
import org.graalvm.util.Equivalence;
import org.graalvm.util.EconomicMap;
import org.graalvm.util.EconomicSet;
import org.graalvm.util.Equivalence;
import org.graalvm.util.MapCursor;
import org.graalvm.word.Pointer;
@ -257,6 +257,18 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
@NodeIntrinsic(ForeignCallNode.class)
private static native void sha5ImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state);
/**
* @see org.graalvm.compiler.hotspot.meta.HotSpotUnsafeSubstitutions#copyMemory
*/
public static final ForeignCallDescriptor UNSAFE_ARRAYCOPY = new ForeignCallDescriptor("unsafe_arraycopy", void.class, Word.class, Word.class, Word.class);
public static void unsafeArraycopy(Word srcAddr, Word dstAddr, Word size) {
unsafeArraycopyStub(HotSpotBackend.UNSAFE_ARRAYCOPY, srcAddr, dstAddr, size);
}
@NodeIntrinsic(ForeignCallNode.class)
private static native void unsafeArraycopyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word size);
/**
* @see VMErrorNode
*/

View File

@ -198,7 +198,7 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler {
public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug);
CompilationResult result = new CompilationResult();
CompilationResult result = new CompilationResult(compilationId);
return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, options);
}

View File

@ -111,6 +111,7 @@ import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import sun.misc.Unsafe;
/**
* Defines the {@link Plugins} used when running on HotSpot.
@ -202,6 +203,7 @@ public class HotSpotGraphBuilderPlugins {
registerCRC32Plugins(invocationPlugins, config, replacementBytecodeProvider);
registerBigIntegerPlugins(invocationPlugins, config, replacementBytecodeProvider);
registerSHAPlugins(invocationPlugins, config, replacementBytecodeProvider);
registerUnsafePlugins(invocationPlugins, replacementBytecodeProvider);
StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, snippetReflection, invocationPlugins, replacementBytecodeProvider, true);
for (NodeIntrinsicPluginFactory factory : GraalServices.load(NodeIntrinsicPluginFactory.class)) {
@ -313,6 +315,17 @@ public class HotSpotGraphBuilderPlugins {
r.registerMethodSubstitution(ReflectionSubstitutions.class, "getClassAccessFlags", Class.class);
}
private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementBytecodeProvider) {
Registration r;
if (Java8OrEarlier) {
r = new Registration(plugins, Unsafe.class, replacementBytecodeProvider);
} else {
r = new Registration(plugins, "jdk.internal.misc.Unsafe", replacementBytecodeProvider);
}
r.registerMethodSubstitution(HotSpotUnsafeSubstitutions.class, HotSpotUnsafeSubstitutions.copyMemoryName, "copyMemory", Receiver.class, Object.class, long.class, Object.class, long.class,
long.class);
}
private static final LocationIdentity INSTANCE_KLASS_CONSTANTS = NamedLocationIdentity.immutable("InstanceKlass::_constants");
private static final LocationIdentity CONSTANT_POOL_LENGTH = NamedLocationIdentity.immutable("ConstantPool::_length");

View File

@ -51,6 +51,7 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA2_IMPL_COMPRESS;
import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA5_IMPL_COMPRESS;
import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA_IMPL_COMPRESS;
import static org.graalvm.compiler.hotspot.HotSpotBackend.SQUARE_TO_LEN;
import static org.graalvm.compiler.hotspot.HotSpotBackend.UNSAFE_ARRAYCOPY;
import static org.graalvm.compiler.hotspot.HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER;
import static org.graalvm.compiler.hotspot.HotSpotBackend.VM_ERROR;
import static org.graalvm.compiler.hotspot.HotSpotBackend.WRONG_METHOD_HANDLER;
@ -330,6 +331,8 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall
registerCheckcastArraycopyDescriptor(true, c.checkcastArraycopyUninit);
registerCheckcastArraycopyDescriptor(false, c.checkcastArraycopy);
registerForeignCall(UNSAFE_ARRAYCOPY, c.unsafeArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.any());
if (c.useMultiplyToLenIntrinsic()) {
registerForeignCall(MULTIPLY_TO_LEN, c.multiplyToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.meta;
import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
import org.graalvm.compiler.hotspot.HotSpotBackend;
import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode;
import org.graalvm.compiler.word.Word;
import org.graalvm.word.WordFactory;
@ClassSubstitution(className = {"jdk.internal.misc.Unsafe", "sun.misc.Unsafe"})
public class HotSpotUnsafeSubstitutions {
public static final String copyMemoryName = Java8OrEarlier ? "copyMemory" : "copyMemory0";
@SuppressWarnings("unused")
@MethodSubstitution(isStatic = false)
static void copyMemory(Object receiver, Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes) {
Word srcAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(srcBase, srcOffset));
Word dstAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(destBase, destOffset));
Word size = Word.signed(bytes);
HotSpotBackend.unsafeArraycopy(srcAddr, dstAddr, size);
}
}

View File

@ -216,8 +216,9 @@ public abstract class Stub {
@SuppressWarnings("try")
private CompilationResult buildCompilationResult(DebugContext debug, final Backend backend) {
CompilationResult compResult = new CompilationResult(toString(), GeneratePIC.getValue(options));
final StructuredGraph graph = getGraph(debug, getStubCompilationId());
CompilationIdentifier compilationId = getStubCompilationId();
final StructuredGraph graph = getGraph(debug, compilationId);
CompilationResult compResult = new CompilationResult(compilationId, toString(), GeneratePIC.getValue(options));
// Stubs cannot be recompiled so they cannot be compiled with assumptions
assert graph.getAssumptions() == null;

View File

@ -365,10 +365,6 @@ final class TraceInterval extends IntervalHint {
return intTo;
}
int numUsePositions() {
return numUsePos();
}
public void setLocationHint(IntervalHint interval) {
locationHint = interval;
}
@ -452,6 +448,10 @@ final class TraceInterval extends IntervalHint {
return spillSt == SpillState.StartInMemory || (spillSt == SpillState.SpillStore && opId > spillDefinitionPos() && !canMaterialize());
}
public boolean preSpilledAllocated() {
return spillState() == SpillState.StartInMemory && numUsePos() == 0 && !hasHint();
}
// test intersection
boolean intersects(TraceInterval i) {
return intersectsAt(i) != -1;

View File

@ -541,16 +541,23 @@ public final class TraceLinearScanLifetimeAnalysisPhase extends TraceLinearScanA
assert instructionIndex == 0 : "not at start?" + instructionIndex;
handleTraceBegin(blocks[0]);
// fix spill state for phi/incoming intervals
for (TraceInterval interval : allocator.intervals()) {
if (interval != null && interval.spillState().equals(SpillState.NoDefinitionFound) && interval.spillDefinitionPos() != -1) {
// there was a definition in a phi/incoming
interval.setSpillState(SpillState.NoSpillStore);
}
}
if (TraceRAuseInterTraceHints.getValue(allocator.getLIR().getOptions())) {
addInterTraceHints();
}
// fix spill state for phi/incoming intervals
for (TraceInterval interval : allocator.intervals()) {
if (interval != null) {
if (interval.spillState().equals(SpillState.NoDefinitionFound) && interval.spillDefinitionPos() != -1) {
// there was a definition in a phi/incoming
interval.setSpillState(SpillState.NoSpillStore);
}
if (interval.preSpilledAllocated()) {
// pre-spill unused, start in memory intervals
allocator.assignSpillSlot(interval);
}
}
}
for (FixedInterval interval1 : allocator.fixedIntervals()) {
if (interval1 != null) {
/* We use [-1, 0] to avoid intersection with incoming values. */

View File

@ -153,7 +153,7 @@ public final class TraceLinearScanPhase extends TraceAllocationPhase<TraceAlloca
@Override
public boolean apply(TraceInterval i) {
// all TraceIntervals are variable intervals
return true;
return !i.preSpilledAllocated();
}
};
private static final Comparator<TraceInterval> SORT_BY_FROM_COMP = new Comparator<TraceInterval>() {

View File

@ -319,7 +319,7 @@ public abstract class GraalCompilerState {
assert !graph.isFrozen();
ResolvedJavaMethod installedCodeOwner = graph.method();
request = new Request<>(graph, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL,
graph.getProfilingInfo(), createSuites(getOptions()), createLIRSuites(getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default);
graph.getProfilingInfo(), createSuites(getOptions()), createLIRSuites(getOptions()), new CompilationResult(graph.compilationId()), CompilationResultBuilderFactory.Default);
}
/**

View File

@ -209,7 +209,6 @@ public class GraphEncoder {
int nodeCount = nodeOrder.nextOrderId;
assert nodeOrder.orderIds.get(graph.start()) == START_NODE_ORDER_ID;
assert nodeOrder.orderIds.get(graph.start().next()) == FIRST_NODE_ORDER_ID;
assert nodeCount == graph.getNodeCount() + 1;
long[] nodeStartOffsets = new long[nodeCount];
UnmodifiableMapCursor<Node, Integer> cursor = nodeOrder.orderIds.getEntries();
@ -218,6 +217,7 @@ public class GraphEncoder {
Integer orderId = cursor.getValue();
assert !(node instanceof AbstractBeginNode) || nodeOrder.orderIds.get(((AbstractBeginNode) node).next()) == orderId + BEGIN_NEXT_ORDER_ID_OFFSET;
assert nodeStartOffsets[orderId] == 0;
nodeStartOffsets[orderId] = writer.getBytesWritten();
/* Write out the type, properties, and edges. */
@ -284,7 +284,6 @@ public class GraphEncoder {
writer.putUV(nodeOrder.maxFixedNodeOrderId);
writer.putUV(nodeCount);
for (int i = 0; i < nodeCount; i++) {
assert i == NULL_ORDER_ID || i == START_NODE_ORDER_ID || nodeStartOffsets[i] > 0;
writer.putUV(metadataStart - nodeStartOffsets[i]);
}
@ -344,8 +343,25 @@ public class GraphEncoder {
} while (current != null);
maxFixedNodeOrderId = nextOrderId - 1;
/*
* Emit all parameters consecutively at a known location (after all fixed nodes). This
* allows substituting parameters when inlining during decoding by pre-initializing the
* decoded node list.
*
* Note that not all parameters must be present (unused parameters are deleted after
* parsing). This leads to holes in the orderId, i.e., unused orderIds.
*/
int parameterCount = graph.method().getSignature().getParameterCount(!graph.method().isStatic());
for (ParameterNode node : graph.getNodes(ParameterNode.TYPE)) {
assert orderIds.get(node) == null : "Parameter node must not be ordered yet";
assert node.index() < parameterCount : "Parameter index out of range";
orderIds.set(node, nextOrderId + node.index());
}
nextOrderId += parameterCount;
for (Node node : graph.getNodes()) {
assert (node instanceof FixedNode) == (orderIds.get(node) != null) : "all fixed nodes must be ordered: " + node;
assert (node instanceof FixedNode || node instanceof ParameterNode) == (orderIds.get(node) != null) : "all fixed nodes and ParameterNodes must be ordered: " + node;
add(node);
}
}

View File

@ -37,6 +37,7 @@ import java.util.List;
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.code.DisassemblerProvider;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.alloc.Trace;
import org.graalvm.compiler.core.common.alloc.TraceBuilderResult;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
@ -72,6 +73,7 @@ public class CFGPrinterObserver implements DebugDumpHandler {
private CFGPrinter cfgPrinter;
private File cfgFile;
private JavaMethod curMethod;
private CompilationIdentifier curCompilation;
private List<String> curDecorators = Collections.emptyList();
@Override
@ -92,6 +94,7 @@ public class CFGPrinterObserver implements DebugDumpHandler {
*/
private boolean checkMethodScope(DebugContext debug) {
JavaMethod method = null;
CompilationIdentifier compilation = null;
ArrayList<String> decorators = new ArrayList<>();
for (Object o : debug.context()) {
if (o instanceof JavaMethod) {
@ -102,22 +105,33 @@ public class CFGPrinterObserver implements DebugDumpHandler {
if (graph.method() != null) {
method = graph.method();
decorators.clear();
compilation = graph.compilationId();
}
} else if (o instanceof DebugDumpScope) {
DebugDumpScope debugDumpScope = (DebugDumpScope) o;
if (debugDumpScope.decorator) {
decorators.add(debugDumpScope.name);
}
} else if (o instanceof CompilationResult) {
CompilationResult compilationResult = (CompilationResult) o;
compilation = compilationResult.getCompilationId();
}
}
if (method == null) {
if (method == null && compilation == null) {
return false;
}
if (!method.equals(curMethod) || !curDecorators.equals(decorators)) {
cfgPrinter.printCompilation(method);
if (compilation != null) {
if (!compilation.equals(curCompilation) || !curDecorators.equals(decorators)) {
cfgPrinter.printCompilation(compilation);
}
} else {
if (!method.equals(curMethod) || !curDecorators.equals(decorators)) {
cfgPrinter.printCompilation(method);
}
}
curCompilation = compilation;
curMethod = method;
curDecorators = decorators;
return true;
@ -277,6 +291,7 @@ public class CFGPrinterObserver implements DebugDumpHandler {
cfgPrinter = null;
curDecorators = Collections.emptyList();
curMethod = null;
curCompilation = null;
}
}

View File

@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.debug.LogStream;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.lir.util.IndexedValueMap;
@ -115,12 +116,25 @@ public class CompilationPrinter implements Closeable {
/**
* Prints a compilation timestamp for a given method.
*
* @param method the method for which a timestamp will be printed
* @param javaMethod the method for which a timestamp will be printed
*/
public void printCompilation(JavaMethod method) {
public void printCompilation(JavaMethod javaMethod) {
printCompilation(javaMethod.format("%H::%n"), javaMethod.format("%f %r %H.%n(%p)"));
}
/**
* Prints a compilation id.
*
* @param compilationId the compilation method for which an id will be printed
*/
public void printCompilation(CompilationIdentifier compilationId) {
printCompilation(compilationId.toString(CompilationIdentifier.Verbosity.DETAILED), compilationId.toString(CompilationIdentifier.Verbosity.DETAILED));
}
private void printCompilation(final String name, String method) {
begin("compilation");
out.print("name \" ").print(method.format("%H::%n")).println('"');
out.print("method \"").print(method.format("%f %r %H.%n(%p)")).println('"');
out.print("name \" ").print(name).println('"');
out.print("method \"").print(method).println('"');
out.print("date ").println(System.currentTimeMillis());
end("compilation");
}

View File

@ -95,10 +95,13 @@ public final class ClassSubstitutionVerifier extends AbstractVerifier {
TypeElement typeElement = null;
for (String className : classNames) {
typeElement = env.getElementUtils().getTypeElement(className);
if (typeElement == null && !optional) {
env.getMessager().printMessage(Kind.ERROR, String.format("The class '%s' was not found on the classpath.", stringValue), sourceElement, classSubstition, stringValue);
if (typeElement != null) {
break;
}
}
if (typeElement == null && !optional) {
env.getMessager().printMessage(Kind.ERROR, String.format("The class '%s' was not found on the classpath.", stringValue), sourceElement, classSubstition, stringValue);
}
return typeElement;
}

View File

@ -707,10 +707,22 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
}
}
LoopScope inlineLoopScope = createInitialLoopScope(inlineScope, predecessor);
/*
* The GraphEncoder assigns parameters a nodeId immediately after the fixed nodes.
* Initializing createdNodes here avoid decoding and immediately replacing the
* ParameterNodes.
*/
int firstArgumentNodeId = inlineScope.maxFixedNodeOrderId + 1;
for (int i = 0; i < arguments.length; i++) {
inlineLoopScope.createdNodes[firstArgumentNodeId + i] = arguments[i];
}
/*
* Do the actual inlining by returning the initial loop scope for the inlined method scope.
*/
return createInitialLoopScope(inlineScope, predecessor);
return inlineLoopScope;
}
@Override
@ -1028,9 +1040,7 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
if (node instanceof ParameterNode) {
ParameterNode param = (ParameterNode) node;
if (methodScope.isInlinedMethod()) {
Node result = methodScope.arguments[param.index()];
assert result != null;
return result;
throw GraalError.shouldNotReachHere("Parameter nodes are already registered when the inlined scope is created");
} else if (parameterPlugin != null) {
assert !methodScope.isInlinedMethod();

View File

@ -1185,62 +1185,6 @@ const char* os::dll_file_extension() { return ".so"; }
// directory not the java application's temp directory, ala java.io.tmpdir.
const char* os::get_temp_directory() { return "/tmp"; }
static bool file_exists(const char* filename) {
struct stat statbuf;
if (filename == NULL || strlen(filename) == 0) {
return false;
}
return os::stat(filename, &statbuf) == 0;
}
bool os::dll_build_name(char* buffer, size_t buflen,
const char* pname, const char* fname) {
bool retval = false;
// Copied from libhpi
const size_t pnamelen = pname ? strlen(pname) : 0;
// Return error on buffer overflow.
if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
*buffer = '\0';
return retval;
}
if (pnamelen == 0) {
snprintf(buffer, buflen, "lib%s.so", fname);
retval = true;
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
if (pelements == NULL) {
return false;
}
for (int i = 0; i < n; i++) {
// Really shouldn't be NULL, but check can't hurt
if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
continue; // skip the empty path values
}
snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
if (file_exists(buffer)) {
retval = true;
break;
}
}
// release the storage
for (int i = 0; i < n; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else {
snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
retval = true;
}
return retval;
}
// Check if addr is inside libjvm.so.
bool os::address_is_in_vm(address addr) {
@ -1493,12 +1437,7 @@ void os::get_summary_cpu_info(char* buf, size_t buflen) {
}
void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
st->print("CPU:");
st->print("total %d", os::processor_count());
// It's not safe to query number of active processors after crash.
// st->print("(active %d)", os::active_processor_count());
st->print(" %s", VM_Version::features());
st->cr();
// Nothing to do beyond what os::print_cpu_info() does.
}
static void print_signal_handler(outputStream* st, int sig,
@ -2668,11 +2607,10 @@ void os::hint_no_preempt() {}
////////////////////////////////////////////////////////////////////////////////
// suspend/resume support
// the low-level signal-based suspend/resume support is a remnant from the
// The low-level signal-based suspend/resume support is a remnant from the
// old VM-suspension that used to be for java-suspension, safepoints etc,
// within hotspot. Now there is a single use-case for this:
// - calling get_thread_pc() on the VMThread by the flat-profiler task
// that runs in the watcher thread.
// within hotspot. Currently used by JFR's OSThreadSampler
//
// The remaining code is greatly simplified from the more general suspension
// code that used to be used.
//
@ -2688,7 +2626,13 @@ void os::hint_no_preempt() {}
//
// Note that the SR_lock plays no role in this suspend/resume protocol,
// but is checked for NULL in SR_handler as a thread termination indicator.
// The SR_lock is, however, used by JavaThread::java_suspend()/java_resume() APIs.
//
// Note that resume_clear_context() and suspend_save_context() are needed
// by SR_handler(), so that fetch_frame_from_ucontext() works,
// which in part is used by:
// - Forte Analyzer: AsyncGetCallTrace()
// - StackBanging: get_frame_at_stack_banging_point()
static void resume_clear_context(OSThread *osthread) {
osthread->set_ucontext(NULL);
@ -3695,44 +3639,6 @@ void os::SuspendedThreadTask::internal_do_task() {
}
}
class PcFetcher : public os::SuspendedThreadTask {
public:
PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {}
ExtendedPC result();
protected:
void do_task(const os::SuspendedThreadTaskContext& context);
private:
ExtendedPC _epc;
};
ExtendedPC PcFetcher::result() {
guarantee(is_done(), "task is not done yet.");
return _epc;
}
void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) {
Thread* thread = context.thread();
OSThread* osthread = thread->osthread();
if (osthread->ucontext() != NULL) {
_epc = os::Aix::ucontext_get_pc((const ucontext_t *) context.ucontext());
} else {
// NULL context is unexpected, double-check this is the VMThread.
guarantee(thread->is_VM_thread(), "can only be called for VMThread");
}
}
// Suspends the target using the signal mechanism and then grabs the PC before
// resuming the target. Used by the flat-profiler only
ExtendedPC os::get_thread_pc(Thread* thread) {
// Make sure that it is called by the watcher for the VMThread.
assert(Thread::current()->is_Watcher_thread(), "Must be watcher");
assert(thread->is_VM_thread(), "Can only be called for VMThread");
PcFetcher fetcher(thread);
fetcher.run();
return fetcher.result();
}
////////////////////////////////////////////////////////////////////////////////
// debug support

View File

@ -1172,13 +1172,6 @@ int os::current_process_id() {
// DLL functions
#define JNI_LIB_PREFIX "lib"
#ifdef __APPLE__
#define JNI_LIB_SUFFIX ".dylib"
#else
#define JNI_LIB_SUFFIX ".so"
#endif
const char* os::dll_file_extension() { return JNI_LIB_SUFFIX; }
// This must be hard coded because it's the system's temporary
@ -1201,62 +1194,6 @@ const char* os::get_temp_directory() {
const char* os::get_temp_directory() { return "/tmp"; }
#endif // __APPLE__
static bool file_exists(const char* filename) {
struct stat statbuf;
if (filename == NULL || strlen(filename) == 0) {
return false;
}
return os::stat(filename, &statbuf) == 0;
}
bool os::dll_build_name(char* buffer, size_t buflen,
const char* pname, const char* fname) {
bool retval = false;
// Copied from libhpi
const size_t pnamelen = pname ? strlen(pname) : 0;
// Return error on buffer overflow.
if (pnamelen + strlen(fname) + strlen(JNI_LIB_PREFIX) + strlen(JNI_LIB_SUFFIX) + 2 > buflen) {
return retval;
}
if (pnamelen == 0) {
snprintf(buffer, buflen, JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, fname);
retval = true;
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
if (pelements == NULL) {
return false;
}
for (int i = 0; i < n; i++) {
// Really shouldn't be NULL, but check can't hurt
if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
continue; // skip the empty path values
}
snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX,
pelements[i], fname);
if (file_exists(buffer)) {
retval = true;
break;
}
}
// release the storage
for (int i = 0; i < n; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else {
snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, pname, fname);
retval = true;
}
return retval;
}
// check if addr is inside libjvm.so
bool os::address_is_in_vm(address addr) {
static address libjvm_base_addr;
@ -2666,11 +2603,10 @@ void os::hint_no_preempt() {}
////////////////////////////////////////////////////////////////////////////////
// suspend/resume support
// the low-level signal-based suspend/resume support is a remnant from the
// The low-level signal-based suspend/resume support is a remnant from the
// old VM-suspension that used to be for java-suspension, safepoints etc,
// within hotspot. Now there is a single use-case for this:
// - calling get_thread_pc() on the VMThread by the flat-profiler task
// that runs in the watcher thread.
// within hotspot. Currently used by JFR's OSThreadSampler
//
// The remaining code is greatly simplified from the more general suspension
// code that used to be used.
//
@ -2686,6 +2622,13 @@ void os::hint_no_preempt() {}
//
// Note that the SR_lock plays no role in this suspend/resume protocol,
// but is checked for NULL in SR_handler as a thread termination indicator.
// The SR_lock is, however, used by JavaThread::java_suspend()/java_resume() APIs.
//
// Note that resume_clear_context() and suspend_save_context() are needed
// by SR_handler(), so that fetch_frame_from_ucontext() works,
// which in part is used by:
// - Forte Analyzer: AsyncGetCallTrace()
// - StackBanging: get_frame_at_stack_banging_point()
static void resume_clear_context(OSThread *osthread) {
osthread->set_ucontext(NULL);
@ -3584,45 +3527,6 @@ void os::SuspendedThreadTask::internal_do_task() {
}
}
///
class PcFetcher : public os::SuspendedThreadTask {
public:
PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {}
ExtendedPC result();
protected:
void do_task(const os::SuspendedThreadTaskContext& context);
private:
ExtendedPC _epc;
};
ExtendedPC PcFetcher::result() {
guarantee(is_done(), "task is not done yet.");
return _epc;
}
void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) {
Thread* thread = context.thread();
OSThread* osthread = thread->osthread();
if (osthread->ucontext() != NULL) {
_epc = os::Bsd::ucontext_get_pc((const ucontext_t *) context.ucontext());
} else {
// NULL context is unexpected, double-check this is the VMThread
guarantee(thread->is_VM_thread(), "can only be called for VMThread");
}
}
// Suspends the target using the signal mechanism and then grabs the PC before
// resuming the target. Used by the flat-profiler only
ExtendedPC os::get_thread_pc(Thread* thread) {
// Make sure that it is called by the watcher for the VMThread
assert(Thread::current()->is_Watcher_thread(), "Must be watcher");
assert(thread->is_VM_thread(), "Can only be called for VMThread");
PcFetcher fetcher(thread);
fetcher.run();
return fetcher.result();
}
////////////////////////////////////////////////////////////////////////////////
// debug support

View File

@ -1419,53 +1419,6 @@ static bool file_exists(const char* filename) {
return os::stat(filename, &statbuf) == 0;
}
bool os::dll_build_name(char* buffer, size_t buflen,
const char* pname, const char* fname) {
bool retval = false;
// Copied from libhpi
const size_t pnamelen = pname ? strlen(pname) : 0;
// Return error on buffer overflow.
if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
return retval;
}
if (pnamelen == 0) {
snprintf(buffer, buflen, "lib%s.so", fname);
retval = true;
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
if (pelements == NULL) {
return false;
}
for (int i = 0; i < n; i++) {
// Really shouldn't be NULL, but check can't hurt
if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
continue; // skip the empty path values
}
snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
if (file_exists(buffer)) {
retval = true;
break;
}
}
// release the storage
for (int i = 0; i < n; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else {
snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
retval = true;
}
return retval;
}
// check if addr is inside libjvm.so
bool os::address_is_in_vm(address addr) {
static address libjvm_base_addr;
@ -4047,11 +4000,10 @@ void os::hint_no_preempt() {}
////////////////////////////////////////////////////////////////////////////////
// suspend/resume support
// the low-level signal-based suspend/resume support is a remnant from the
// The low-level signal-based suspend/resume support is a remnant from the
// old VM-suspension that used to be for java-suspension, safepoints etc,
// within hotspot. Now there is a single use-case for this:
// - calling get_thread_pc() on the VMThread by the flat-profiler task
// that runs in the watcher thread.
// within hotspot. Currently used by JFR's OSThreadSampler
//
// The remaining code is greatly simplified from the more general suspension
// code that used to be used.
//
@ -4067,6 +4019,13 @@ void os::hint_no_preempt() {}
//
// Note that the SR_lock plays no role in this suspend/resume protocol,
// but is checked for NULL in SR_handler as a thread termination indicator.
// The SR_lock is, however, used by JavaThread::java_suspend()/java_resume() APIs.
//
// Note that resume_clear_context() and suspend_save_context() are needed
// by SR_handler(), so that fetch_frame_from_ucontext() works,
// which in part is used by:
// - Forte Analyzer: AsyncGetCallTrace()
// - StackBanging: get_frame_at_stack_banging_point()
static void resume_clear_context(OSThread *osthread) {
osthread->set_ucontext(NULL);
@ -5107,44 +5066,6 @@ void os::SuspendedThreadTask::internal_do_task() {
}
}
class PcFetcher : public os::SuspendedThreadTask {
public:
PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {}
ExtendedPC result();
protected:
void do_task(const os::SuspendedThreadTaskContext& context);
private:
ExtendedPC _epc;
};
ExtendedPC PcFetcher::result() {
guarantee(is_done(), "task is not done yet.");
return _epc;
}
void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) {
Thread* thread = context.thread();
OSThread* osthread = thread->osthread();
if (osthread->ucontext() != NULL) {
_epc = os::Linux::ucontext_get_pc((const ucontext_t *) context.ucontext());
} else {
// NULL context is unexpected, double-check this is the VMThread
guarantee(thread->is_VM_thread(), "can only be called for VMThread");
}
}
// Suspends the target using the signal mechanism and then grabs the PC before
// resuming the target. Used by the flat-profiler only
ExtendedPC os::get_thread_pc(Thread* thread) {
// Make sure that it is called by the watcher for the VMThread
assert(Thread::current()->is_Watcher_thread(), "Must be watcher");
assert(thread->is_VM_thread(), "Can only be called for VMThread");
PcFetcher fetcher(thread);
fetcher.run();
return fetcher.result();
}
////////////////////////////////////////////////////////////////////////////////
// debug support

View File

@ -24,7 +24,6 @@
#include "utilities/globalDefinitions.hpp"
#include "prims/jvm.h"
#include "semaphore_posix.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/os.hpp"
@ -32,6 +31,11 @@
#include "utilities/macros.hpp"
#include "utilities/vmError.hpp"
#ifndef __APPLE__
// POSIX unamed semaphores are not supported on OS X.
#include "semaphore_posix.hpp"
#endif
#include <dlfcn.h>
#include <pthread.h>
#include <semaphore.h>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -65,12 +65,6 @@
void set_lwp_id(uint id) { _lwp_id = id; }
void set_native_priority(int prio) { _native_priority = prio; }
// ***************************************************************
// interrupt support. interrupts (using signals) are used to get
// the thread context (get_thread_pc), to set the thread context
// (set_thread_pc), and to implement java.lang.Thread.interrupt.
// ***************************************************************
public:
os::SuspendResume sr;

View File

@ -1356,60 +1356,6 @@ const char* os::dll_file_extension() { return ".so"; }
// directory not the java application's temp directory, ala java.io.tmpdir.
const char* os::get_temp_directory() { return "/tmp"; }
static bool file_exists(const char* filename) {
struct stat statbuf;
if (filename == NULL || strlen(filename) == 0) {
return false;
}
return os::stat(filename, &statbuf) == 0;
}
bool os::dll_build_name(char* buffer, size_t buflen,
const char* pname, const char* fname) {
bool retval = false;
const size_t pnamelen = pname ? strlen(pname) : 0;
// Return error on buffer overflow.
if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
return retval;
}
if (pnamelen == 0) {
snprintf(buffer, buflen, "lib%s.so", fname);
retval = true;
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
if (pelements == NULL) {
return false;
}
for (int i = 0; i < n; i++) {
// really shouldn't be NULL but what the heck, check can't hurt
if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
continue; // skip the empty path values
}
snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
if (file_exists(buffer)) {
retval = true;
break;
}
}
// release the storage
for (int i = 0; i < n; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else {
snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
retval = true;
}
return retval;
}
// check if addr is inside libjvm.so
bool os::address_is_in_vm(address addr) {
static address libjvm_base_addr;
@ -3496,6 +3442,37 @@ void os::hint_no_preempt() {
schedctl_start(schedctl_init());
}
////////////////////////////////////////////////////////////////////////////////
// suspend/resume support
// The low-level signal-based suspend/resume support is a remnant from the
// old VM-suspension that used to be for java-suspension, safepoints etc,
// within hotspot. Currently used by JFR's OSThreadSampler
//
// The remaining code is greatly simplified from the more general suspension
// code that used to be used.
//
// The protocol is quite simple:
// - suspend:
// - sends a signal to the target thread
// - polls the suspend state of the osthread using a yield loop
// - target thread signal handler (SR_handler) sets suspend state
// and blocks in sigsuspend until continued
// - resume:
// - sets target osthread state to continue
// - sends signal to end the sigsuspend loop in the SR_handler
//
// Note that the SR_lock plays no role in this suspend/resume protocol,
// but is checked for NULL in SR_handler as a thread termination indicator.
// The SR_lock is, however, used by JavaThread::java_suspend()/java_resume() APIs.
//
// Note that resume_clear_context() and suspend_save_context() are needed
// by SR_handler(), so that fetch_frame_from_ucontext() works,
// which in part is used by:
// - Forte Analyzer: AsyncGetCallTrace()
// - StackBanging: get_frame_at_stack_banging_point()
// - JFR: get_topframe()-->....-->get_valid_uc_in_signal_handler()
static void resume_clear_context(OSThread *osthread) {
osthread->set_ucontext(NULL);
}
@ -3506,7 +3483,7 @@ static void suspend_save_context(OSThread *osthread, ucontext_t* context) {
static PosixSemaphore sr_semaphore;
void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) {
void os::Solaris::SR_handler(Thread* thread, ucontext_t* context) {
// Save and restore errno to avoid confusing native code with EINTR
// after sigsuspend.
int old_errno = errno;
@ -3516,7 +3493,7 @@ void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) {
os::SuspendResume::State current = osthread->sr.state();
if (current == os::SuspendResume::SR_SUSPEND_REQUEST) {
suspend_save_context(osthread, uc);
suspend_save_context(osthread, context);
// attempt to switch the state, we assume we had a SUSPEND_REQUEST
os::SuspendResume::State state = osthread->sr.suspended();
@ -3663,45 +3640,6 @@ void os::SuspendedThreadTask::internal_do_task() {
}
}
class PcFetcher : public os::SuspendedThreadTask {
public:
PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {}
ExtendedPC result();
protected:
void do_task(const os::SuspendedThreadTaskContext& context);
private:
ExtendedPC _epc;
};
ExtendedPC PcFetcher::result() {
guarantee(is_done(), "task is not done yet.");
return _epc;
}
void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) {
Thread* thread = context.thread();
OSThread* osthread = thread->osthread();
if (osthread->ucontext() != NULL) {
_epc = os::Solaris::ucontext_get_pc((const ucontext_t *) context.ucontext());
} else {
// NULL context is unexpected, double-check this is the VMThread
guarantee(thread->is_VM_thread(), "can only be called for VMThread");
}
}
// A lightweight implementation that does not suspend the target thread and
// thus returns only a hint. Used for profiling only!
ExtendedPC os::get_thread_pc(Thread* thread) {
// Make sure that it is called by the watcher and the Threads lock is owned.
assert(Thread::current()->is_Watcher_thread(), "Must be watcher and own Threads_lock");
// For now, is only used to profile the VM Thread
assert(thread->is_VM_thread(), "Can only be called for VMThread");
PcFetcher fetcher(thread);
fetcher.run();
return fetcher.result();
}
// This does not do anything on Solaris. This is basically a hook for being
// able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
void os::os_exception_wrapper(java_call_t f, JavaValue* value,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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,160 +27,99 @@
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "decoder_windows.hpp"
#include "windbghelp.hpp"
WindowsDecoder::WindowsDecoder() {
_dbghelp_handle = NULL;
_can_decode_in_vm = false;
_pfnSymGetSymFromAddr64 = NULL;
_pfnUndecorateSymbolName = NULL;
#ifdef AMD64
_pfnStackWalk64 = NULL;
_pfnSymFunctionTableAccess64 = NULL;
_pfnSymGetModuleBase64 = NULL;
#endif
_can_decode_in_vm = true;
_decoder_status = no_error;
initialize();
}
void WindowsDecoder::initialize() {
if (!has_error() && _dbghelp_handle == NULL) {
HMODULE handle = ::LoadLibrary("dbghelp.dll");
if (!handle) {
_decoder_status = helper_not_found;
return;
}
_dbghelp_handle = handle;
pfn_SymSetOptions _pfnSymSetOptions = (pfn_SymSetOptions)::GetProcAddress(handle, "SymSetOptions");
pfn_SymInitialize _pfnSymInitialize = (pfn_SymInitialize)::GetProcAddress(handle, "SymInitialize");
_pfnSymGetSymFromAddr64 = (pfn_SymGetSymFromAddr64)::GetProcAddress(handle, "SymGetSymFromAddr64");
_pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName");
if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) {
uninitialize();
_decoder_status = helper_func_error;
return;
}
#ifdef AMD64
_pfnStackWalk64 = (pfn_StackWalk64)::GetProcAddress(handle, "StackWalk64");
_pfnSymFunctionTableAccess64 = (pfn_SymFunctionTableAccess64)::GetProcAddress(handle, "SymFunctionTableAccess64");
_pfnSymGetModuleBase64 = (pfn_SymGetModuleBase64)::GetProcAddress(handle, "SymGetModuleBase64");
if (_pfnStackWalk64 == NULL || _pfnSymFunctionTableAccess64 == NULL || _pfnSymGetModuleBase64 == NULL) {
// We can't call StackWalk64 to walk the stack, but we are still
// able to decode the symbols. Let's limp on.
_pfnStackWalk64 = NULL;
_pfnSymFunctionTableAccess64 = NULL;
_pfnSymGetModuleBase64 = NULL;
}
#endif
if (!has_error()) {
HANDLE hProcess = ::GetCurrentProcess();
_pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS);
if (!_pfnSymInitialize(hProcess, NULL, TRUE)) {
_pfnSymGetSymFromAddr64 = NULL;
_pfnUndecorateSymbolName = NULL;
::FreeLibrary(handle);
_dbghelp_handle = NULL;
WindowsDbgHelp::symSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS);
if (!WindowsDbgHelp::symInitialize(hProcess, NULL, TRUE)) {
_decoder_status = helper_init_error;
return;
}
// set pdb search paths
pfn_SymSetSearchPath _pfn_SymSetSearchPath =
(pfn_SymSetSearchPath)::GetProcAddress(handle, "SymSetSearchPath");
pfn_SymGetSearchPath _pfn_SymGetSearchPath =
(pfn_SymGetSearchPath)::GetProcAddress(handle, "SymGetSearchPath");
if (_pfn_SymSetSearchPath != NULL && _pfn_SymGetSearchPath != NULL) {
char paths[MAX_PATH];
int len = sizeof(paths);
if (!_pfn_SymGetSearchPath(hProcess, paths, len)) {
paths[0] = '\0';
} else {
// available spaces in path buffer
len -= (int)strlen(paths);
}
char tmp_path[MAX_PATH];
DWORD dwSize;
HMODULE hJVM = ::GetModuleHandle("jvm.dll");
tmp_path[0] = '\0';
// append the path where jvm.dll is located
if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) {
while (dwSize > 0 && tmp_path[dwSize] != '\\') {
dwSize --;
}
tmp_path[dwSize] = '\0';
if (dwSize > 0 && len > (int)dwSize + 1) {
strncat(paths, os::path_separator(), 1);
strncat(paths, tmp_path, dwSize);
len -= dwSize + 1;
}
}
// append $JRE/bin. Arguments::get_java_home actually returns $JRE
// path
char *p = Arguments::get_java_home();
assert(p != NULL, "empty java home");
size_t java_home_len = strlen(p);
if (len > (int)java_home_len + 5) {
strncat(paths, os::path_separator(), 1);
strncat(paths, p, java_home_len);
strncat(paths, "\\bin", 4);
len -= (int)(java_home_len + 5);
}
// append $JDK/bin path if it exists
assert(java_home_len < MAX_PATH, "Invalid path length");
// assume $JRE is under $JDK, construct $JDK/bin path and
// see if it exists or not
if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) {
strncpy(tmp_path, p, java_home_len - 3);
tmp_path[java_home_len - 3] = '\0';
strncat(tmp_path, "bin", 3);
// if the directory exists
DWORD dwAttrib = GetFileAttributes(tmp_path);
if (dwAttrib != INVALID_FILE_ATTRIBUTES &&
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
// tmp_path should have the same length as java_home_len, since we only
// replaced 'jre' with 'bin'
if (len > (int)java_home_len + 1) {
strncat(paths, os::path_separator(), 1);
strncat(paths, tmp_path, java_home_len);
}
}
}
_pfn_SymSetSearchPath(hProcess, paths);
char paths[MAX_PATH];
int len = sizeof(paths);
if (!WindowsDbgHelp::symGetSearchPath(hProcess, paths, len)) {
paths[0] = '\0';
} else {
// available spaces in path buffer
len -= (int)strlen(paths);
}
// find out if jvm.dll contains private symbols, by decoding
// current function and comparing the result
address addr = (address)Decoder::demangle;
char buf[MAX_PATH];
if (decode(addr, buf, sizeof(buf), NULL, NULL, true /* demangle */)) {
_can_decode_in_vm = !strcmp(buf, "Decoder::demangle");
}
char tmp_path[MAX_PATH];
DWORD dwSize;
HMODULE hJVM = ::GetModuleHandle("jvm.dll");
tmp_path[0] = '\0';
// append the path where jvm.dll is located
if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) {
while (dwSize > 0 && tmp_path[dwSize] != '\\') {
dwSize --;
}
tmp_path[dwSize] = '\0';
if (dwSize > 0 && len > (int)dwSize + 1) {
strncat(paths, os::path_separator(), 1);
strncat(paths, tmp_path, dwSize);
len -= dwSize + 1;
}
}
// append $JRE/bin. Arguments::get_java_home actually returns $JRE
// path
char *p = Arguments::get_java_home();
assert(p != NULL, "empty java home");
size_t java_home_len = strlen(p);
if (len > (int)java_home_len + 5) {
strncat(paths, os::path_separator(), 1);
strncat(paths, p, java_home_len);
strncat(paths, "\\bin", 4);
len -= (int)(java_home_len + 5);
}
// append $JDK/bin path if it exists
assert(java_home_len < MAX_PATH, "Invalid path length");
// assume $JRE is under $JDK, construct $JDK/bin path and
// see if it exists or not
if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) {
strncpy(tmp_path, p, java_home_len - 3);
tmp_path[java_home_len - 3] = '\0';
strncat(tmp_path, "bin", 3);
// if the directory exists
DWORD dwAttrib = GetFileAttributes(tmp_path);
if (dwAttrib != INVALID_FILE_ATTRIBUTES &&
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
// tmp_path should have the same length as java_home_len, since we only
// replaced 'jre' with 'bin'
if (len > (int)java_home_len + 1) {
strncat(paths, os::path_separator(), 1);
strncat(paths, tmp_path, java_home_len);
}
}
}
WindowsDbgHelp::symSetSearchPath(hProcess, paths);
// find out if jvm.dll contains private symbols, by decoding
// current function and comparing the result
address addr = (address)Decoder::demangle;
char buf[MAX_PATH];
if (decode(addr, buf, sizeof(buf), NULL, NULL, true /* demangle */)) {
_can_decode_in_vm = !strcmp(buf, "Decoder::demangle");
}
}
}
void WindowsDecoder::uninitialize() {
_pfnSymGetSymFromAddr64 = NULL;
_pfnUndecorateSymbolName = NULL;
#ifdef AMD64
_pfnStackWalk64 = NULL;
_pfnSymFunctionTableAccess64 = NULL;
_pfnSymGetModuleBase64 = NULL;
#endif
if (_dbghelp_handle != NULL) {
::FreeLibrary(_dbghelp_handle);
}
_dbghelp_handle = NULL;
}
void WindowsDecoder::uninitialize() {}
bool WindowsDecoder::can_decode_C_frame_in_vm() const {
return (!has_error() && _can_decode_in_vm);
@ -188,14 +127,14 @@ bool WindowsDecoder::can_decode_C_frame_in_vm() const {
bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath, bool demangle_name) {
if (_pfnSymGetSymFromAddr64 != NULL) {
if (!has_error()) {
PIMAGEHLP_SYMBOL64 pSymbol;
char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
pSymbol = (PIMAGEHLP_SYMBOL64)symbolInfo;
pSymbol->MaxNameLength = MAX_PATH;
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
DWORD64 displacement;
if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
if (WindowsDbgHelp::symGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
if (buf != NULL) {
if (!(demangle_name && demangle(pSymbol->Name, buf, buflen))) {
jio_snprintf(buf, buflen, "%s", pSymbol->Name);
@ -211,69 +150,9 @@ bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, co
}
bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) {
return _pfnUndecorateSymbolName != NULL &&
_pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE);
}
#ifdef AMD64
BOOL WindowsDbgHelp::StackWalk64(DWORD MachineType,
HANDLE hProcess,
HANDLE hThread,
LPSTACKFRAME64 StackFrame,
PVOID ContextRecord,
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress) {
DecoderLocker locker;
WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
if (!wd->has_error() && wd->_pfnStackWalk64) {
return wd->_pfnStackWalk64(MachineType,
hProcess,
hThread,
StackFrame,
ContextRecord,
ReadMemoryRoutine,
FunctionTableAccessRoutine,
GetModuleBaseRoutine,
TranslateAddress);
} else {
return false;
if (!has_error()) {
return WindowsDbgHelp::unDecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE) > 0;
}
return false;
}
PVOID WindowsDbgHelp::SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) {
DecoderLocker locker;
WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
if (!wd->has_error() && wd->_pfnSymFunctionTableAccess64) {
return wd->_pfnSymFunctionTableAccess64(hProcess, AddrBase);
} else {
return NULL;
}
}
pfn_SymFunctionTableAccess64 WindowsDbgHelp::pfnSymFunctionTableAccess64() {
DecoderLocker locker;
WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
if (!wd->has_error()) {
return wd->_pfnSymFunctionTableAccess64;
} else {
return NULL;
}
}
pfn_SymGetModuleBase64 WindowsDbgHelp::pfnSymGetModuleBase64() {
DecoderLocker locker;
WindowsDecoder* wd = (WindowsDecoder*)locker.decoder();
if (!wd->has_error()) {
return wd->_pfnSymGetModuleBase64;
} else {
return NULL;
}
}
#endif // AMD64

View File

@ -25,33 +25,8 @@
#ifndef OS_WINDOWS_VM_DECODER_WINDOWS_HPP
#define OS_WINDOWS_VM_DECIDER_WINDOWS_HPP
#include <windows.h>
#include <imagehlp.h>
#include "utilities/decoder.hpp"
// functions needed for decoding symbols
typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD);
typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);
typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD);
typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR);
typedef BOOL (WINAPI *pfn_SymGetSearchPath)(HANDLE, PTSTR, int);
#ifdef AMD64
typedef BOOL (WINAPI *pfn_StackWalk64)(DWORD MachineType,
HANDLE hProcess,
HANDLE hThread,
LPSTACKFRAME64 StackFrame,
PVOID ContextRecord,
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
typedef PVOID (WINAPI *pfn_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
typedef DWORD64 (WINAPI *pfn_SymGetModuleBase64)(HANDLE hProcess, DWORD64 dwAddr);
#endif
class WindowsDecoder : public AbstractDecoder {
public:
@ -70,38 +45,8 @@ private:
void initialize();
void uninitialize();
private:
HMODULE _dbghelp_handle;
bool _can_decode_in_vm;
pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64;
pfn_UndecorateSymbolName _pfnUndecorateSymbolName;
#ifdef AMD64
pfn_StackWalk64 _pfnStackWalk64;
pfn_SymFunctionTableAccess64 _pfnSymFunctionTableAccess64;
pfn_SymGetModuleBase64 _pfnSymGetModuleBase64;
friend class WindowsDbgHelp;
#endif
};
#ifdef AMD64
// TODO: refactor and move the handling of dbghelp.dll outside of Decoder
class WindowsDbgHelp : public Decoder {
public:
static BOOL StackWalk64(DWORD MachineType,
HANDLE hProcess,
HANDLE hThread,
LPSTACKFRAME64 StackFrame,
PVOID ContextRecord,
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
static PVOID SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase);
static pfn_SymFunctionTableAccess64 pfnSymFunctionTableAccess64();
static pfn_SymGetModuleBase64 pfnSymGetModuleBase64();
};
#endif
#endif // OS_WINDOWS_VM_DECODER_WINDOWS_HPP

View File

@ -74,6 +74,8 @@
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#include "utilities/vmError.hpp"
#include "windbghelp.hpp"
#ifdef _DEBUG
#include <crtdbg.h>
@ -1009,7 +1011,6 @@ void os::check_dump_limit(char* buffer, size_t buffsz) {
}
void os::abort(bool dump_core, void* siginfo, const void* context) {
HINSTANCE dbghelp;
EXCEPTION_POINTERS ep;
MINIDUMP_EXCEPTION_INFORMATION mei;
MINIDUMP_EXCEPTION_INFORMATION* pmei;
@ -1026,28 +1027,6 @@ void os::abort(bool dump_core, void* siginfo, const void* context) {
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}
dbghelp = os::win32::load_Windows_dll("DBGHELP.DLL", NULL, 0);
if (dbghelp == NULL) {
jio_fprintf(stderr, "Failed to load dbghelp.dll\n");
CloseHandle(dumpFile);
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}
_MiniDumpWriteDump =
CAST_TO_FN_PTR(BOOL(WINAPI *)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
PMINIDUMP_EXCEPTION_INFORMATION,
PMINIDUMP_USER_STREAM_INFORMATION,
PMINIDUMP_CALLBACK_INFORMATION),
GetProcAddress(dbghelp,
"MiniDumpWriteDump"));
if (_MiniDumpWriteDump == NULL) {
jio_fprintf(stderr, "Failed to find MiniDumpWriteDump() in module dbghelp.dll.\n");
CloseHandle(dumpFile);
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}
dumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData |
MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo | MiniDumpWithUnloadedModules);
@ -1064,8 +1043,8 @@ void os::abort(bool dump_core, void* siginfo, const void* context) {
// Older versions of dbghelp.dll (the one shipped with Win2003 for example) may not support all
// the dump types we really want. If first call fails, lets fall back to just use MiniDumpWithFullMemory then.
if (_MiniDumpWriteDump(hProcess, processId, dumpFile, dumpType, pmei, NULL, NULL) == false &&
_MiniDumpWriteDump(hProcess, processId, dumpFile, (MINIDUMP_TYPE)MiniDumpWithFullMemory, pmei, NULL, NULL) == false) {
if (!WindowsDbgHelp::miniDumpWriteDump(hProcess, processId, dumpFile, dumpType, pmei, NULL, NULL) &&
!WindowsDbgHelp::miniDumpWriteDump(hProcess, processId, dumpFile, (MINIDUMP_TYPE)MiniDumpWithFullMemory, pmei, NULL, NULL)) {
jio_fprintf(stderr, "Call to MiniDumpWriteDump() failed (Error 0x%x)\n", GetLastError());
}
CloseHandle(dumpFile);
@ -1198,70 +1177,6 @@ const char* os::get_temp_directory() {
}
}
static bool file_exists(const char* filename) {
if (filename == NULL || strlen(filename) == 0) {
return false;
}
return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
}
bool os::dll_build_name(char *buffer, size_t buflen,
const char* pname, const char* fname) {
bool retval = false;
const size_t pnamelen = pname ? strlen(pname) : 0;
const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
// Return error on buffer overflow.
if (pnamelen + strlen(fname) + 10 > buflen) {
return retval;
}
if (pnamelen == 0) {
jio_snprintf(buffer, buflen, "%s.dll", fname);
retval = true;
} else if (c == ':' || c == '\\') {
jio_snprintf(buffer, buflen, "%s%s.dll", pname, fname);
retval = true;
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
if (pelements == NULL) {
return false;
}
for (int i = 0; i < n; i++) {
char* path = pelements[i];
// Really shouldn't be NULL, but check can't hurt
size_t plen = (path == NULL) ? 0 : strlen(path);
if (plen == 0) {
continue; // skip the empty path values
}
const char lastchar = path[plen - 1];
if (lastchar == ':' || lastchar == '\\') {
jio_snprintf(buffer, buflen, "%s%s.dll", path, fname);
} else {
jio_snprintf(buffer, buflen, "%s\\%s.dll", path, fname);
}
if (file_exists(buffer)) {
retval = true;
break;
}
}
// release the storage
for (int i = 0; i < n; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else {
jio_snprintf(buffer, buflen, "%s\\%s.dll", pname, fname);
retval = true;
}
return retval;
}
// Needs to be in os specific directory because windows requires another
// header file <direct.h>
const char* os::get_current_directory(char *buf, size_t buflen) {
@ -3591,22 +3506,6 @@ bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
return interrupted;
}
// Get's a pc (hint) for a running thread. Currently used only for profiling.
ExtendedPC os::get_thread_pc(Thread* thread) {
CONTEXT context;
context.ContextFlags = CONTEXT_CONTROL;
HANDLE handle = thread->osthread()->thread_handle();
if (GetThreadContext(handle, &context)) {
#ifdef _M_AMD64
return ExtendedPC((address) context.Rip);
#else
return ExtendedPC((address) context.Eip);
#endif
} else {
return ExtendedPC(NULL);
}
}
// GetCurrentThreadId() returns DWORD
intx os::current_thread_id() { return GetCurrentThreadId(); }

View File

@ -0,0 +1,306 @@
/*
* Copyright (c) 2017, 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 "utilities/ostream.hpp"
#include "windbghelp.hpp"
#include <windows.h>
typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD);
typedef DWORD (WINAPI *pfn_SymGetOptions)(void);
typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL);
typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
typedef DWORD (WINAPI *pfn_UnDecorateSymbolName)(const char*, char*, DWORD, DWORD);
typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR);
typedef BOOL (WINAPI *pfn_SymGetSearchPath)(HANDLE, PTSTR, int);
typedef BOOL (WINAPI *pfn_StackWalk64)(DWORD MachineType,
HANDLE hProcess,
HANDLE hThread,
LPSTACKFRAME64 StackFrame,
PVOID ContextRecord,
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
typedef PVOID (WINAPI *pfn_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
typedef DWORD64 (WINAPI *pfn_SymGetModuleBase64)(HANDLE hProcess, DWORD64 dwAddr);
typedef BOOL (WINAPI *pfn_MiniDumpWriteDump) (HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
typedef BOOL (WINAPI *pfn_SymGetLineFromAddr64) (HANDLE hProcess, DWORD64 dwAddr,
PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line);
typedef LPAPI_VERSION (WINAPI *pfn_ImagehlpApiVersion)(void);
// Add functions as needed.
#define FOR_ALL_FUNCTIONS(DO) \
DO(ImagehlpApiVersion) \
DO(SymGetOptions) \
DO(SymSetOptions) \
DO(SymInitialize) \
DO(SymGetSymFromAddr64) \
DO(UnDecorateSymbolName) \
DO(SymSetSearchPath) \
DO(SymGetSearchPath) \
DO(StackWalk64) \
DO(SymFunctionTableAccess64) \
DO(SymGetModuleBase64) \
DO(MiniDumpWriteDump) \
DO(SymGetLineFromAddr64)
#define DECLARE_FUNCTION_POINTER(functionname) \
static pfn_##functionname g_pfn_##functionname;
FOR_ALL_FUNCTIONS(DECLARE_FUNCTION_POINTER)
static HMODULE g_dll_handle = NULL;
static DWORD g_dll_load_error = 0;
static API_VERSION g_version = { 0, 0, 0, 0 };
static enum {
state_uninitialized = 0,
state_ready = 1,
state_error = 2
} g_state = state_uninitialized;
static void initialize() {
assert(g_state == state_uninitialized, "wrong sequence");
g_state = state_error;
g_dll_handle = ::LoadLibrary("DBGHELP.DLL");
if (g_dll_handle == NULL) {
g_dll_load_error = ::GetLastError();
} else {
// Note: We loaded the DLL successfully. From here on we count
// initialization as success. We still may fail to load all of the
// desired function pointers successfully, but DLL may still be usable
// enough for our purposes.
g_state = state_ready;
#define DO_RESOLVE(functionname) \
g_pfn_##functionname = (pfn_##functionname) ::GetProcAddress(g_dll_handle, #functionname);
FOR_ALL_FUNCTIONS(DO_RESOLVE)
// Retrieve version information.
if (g_pfn_ImagehlpApiVersion) {
const API_VERSION* p = g_pfn_ImagehlpApiVersion();
memcpy(&g_version, p, sizeof(API_VERSION));
}
}
}
///////////////////// External functions //////////////////////////
// All outside facing functions are synchronized. Also, we run
// initialization on first touch.
// Call InitializeCriticalSection as early as possible.
class CritSect {
CRITICAL_SECTION cs;
public:
CritSect() { ::InitializeCriticalSection(&cs); }
void enter() { ::EnterCriticalSection(&cs); }
void leave() { ::LeaveCriticalSection(&cs); }
};
static CritSect g_cs;
class EntryGuard {
public:
EntryGuard() {
g_cs.enter();
if (g_state == state_uninitialized) {
initialize();
}
}
~EntryGuard() {
g_cs.leave();
}
};
DWORD WindowsDbgHelp::symSetOptions(DWORD arg) {
EntryGuard entry_guard;
if (g_pfn_SymSetOptions != NULL) {
return g_pfn_SymSetOptions(arg);
}
return 0;
}
DWORD WindowsDbgHelp::symGetOptions(void) {
EntryGuard entry_guard;
if (g_pfn_SymGetOptions != NULL) {
return g_pfn_SymGetOptions();
}
return 0;
}
BOOL WindowsDbgHelp::symInitialize(HANDLE hProcess, PCTSTR UserSearchPath, BOOL fInvadeProcess) {
EntryGuard entry_guard;
if (g_pfn_SymInitialize != NULL) {
return g_pfn_SymInitialize(hProcess, UserSearchPath, fInvadeProcess);
}
return FALSE;
}
BOOL WindowsDbgHelp::symGetSymFromAddr64(HANDLE hProcess, DWORD64 the_address,
PDWORD64 Displacement, PIMAGEHLP_SYMBOL64 Symbol) {
EntryGuard entry_guard;
if (g_pfn_SymGetSymFromAddr64 != NULL) {
return g_pfn_SymGetSymFromAddr64(hProcess, the_address, Displacement, Symbol);
}
return FALSE;
}
DWORD WindowsDbgHelp::unDecorateSymbolName(const char* DecoratedName, char* UnDecoratedName,
DWORD UndecoratedLength, DWORD Flags) {
EntryGuard entry_guard;
if (g_pfn_UnDecorateSymbolName != NULL) {
return g_pfn_UnDecorateSymbolName(DecoratedName, UnDecoratedName, UndecoratedLength, Flags);
}
if (UnDecoratedName != NULL && UndecoratedLength > 0) {
UnDecoratedName[0] = '\0';
}
return 0;
}
BOOL WindowsDbgHelp::symSetSearchPath(HANDLE hProcess, PCTSTR SearchPath) {
EntryGuard entry_guard;
if (g_pfn_SymSetSearchPath != NULL) {
return g_pfn_SymSetSearchPath(hProcess, SearchPath);
}
return FALSE;
}
BOOL WindowsDbgHelp::symGetSearchPath(HANDLE hProcess, PTSTR SearchPath, int SearchPathLength) {
EntryGuard entry_guard;
if (g_pfn_SymGetSearchPath != NULL) {
return g_pfn_SymGetSearchPath(hProcess, SearchPath, SearchPathLength);
}
return FALSE;
}
BOOL WindowsDbgHelp::stackWalk64(DWORD MachineType,
HANDLE hProcess,
HANDLE hThread,
LPSTACKFRAME64 StackFrame,
PVOID ContextRecord) {
EntryGuard entry_guard;
if (g_pfn_StackWalk64 != NULL) {
return g_pfn_StackWalk64(MachineType, hProcess, hThread, StackFrame,
ContextRecord,
NULL, // ReadMemoryRoutine
g_pfn_SymFunctionTableAccess64, // FunctionTableAccessRoutine,
g_pfn_SymGetModuleBase64, // GetModuleBaseRoutine
NULL // TranslateAddressRoutine
);
}
return FALSE;
}
PVOID WindowsDbgHelp::symFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) {
EntryGuard entry_guard;
if (g_pfn_SymFunctionTableAccess64 != NULL) {
return g_pfn_SymFunctionTableAccess64(hProcess, AddrBase);
}
return NULL;
}
DWORD64 WindowsDbgHelp::symGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr) {
EntryGuard entry_guard;
if (g_pfn_SymGetModuleBase64 != NULL) {
return g_pfn_SymGetModuleBase64(hProcess, dwAddr);
}
return 0;
}
BOOL WindowsDbgHelp::miniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam) {
EntryGuard entry_guard;
if (g_pfn_MiniDumpWriteDump != NULL) {
return g_pfn_MiniDumpWriteDump(hProcess, ProcessId, hFile, DumpType,
ExceptionParam, UserStreamParam, CallbackParam);
}
return FALSE;
}
BOOL WindowsDbgHelp::symGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr,
PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line) {
EntryGuard entry_guard;
if (g_pfn_SymGetLineFromAddr64 != NULL) {
return g_pfn_SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, Line);
}
return FALSE;
}
// Print one liner describing state (if library loaded, which functions are
// missing - if any, and the dbhelp API version)
void WindowsDbgHelp::print_state_on(outputStream* st) {
// Note: We should not lock while printing, but this should be
// safe to do without lock anyway.
st->print("dbghelp: ");
if (g_state == state_uninitialized) {
st->print("uninitialized.");
} else if (g_state == state_error) {
st->print("loading error: %u", g_dll_load_error);
} else {
st->print("loaded successfully ");
// We may want to print dll file name here - which may be interesting for
// cases where more than one version exists on the system, e.g. with a
// debugging sdk separately installed. But we get the file name in the DLL
// section of the hs-err file too, so this may be redundant.
// Print version.
st->print("- version: %u.%u.%u",
g_version.MajorVersion, g_version.MinorVersion, g_version.Revision);
// Print any functions which failed to load.
int num_missing = 0;
st->print(" - missing functions: ");
#define CHECK_AND_PRINT_IF_NULL(functionname) \
if (g_pfn_##functionname == NULL) { \
st->print("%s" #functionname, ((num_missing > 0) ? ", " : "")); \
num_missing ++; \
}
FOR_ALL_FUNCTIONS(CHECK_AND_PRINT_IF_NULL)
if (num_missing == 0) {
st->print("none");
}
}
st->cr();
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2017, 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 OS_WINDOWS_VM_DBGHELPLOADER_HPP
#define OS_WINDOWS_VM_DBGHELPLOADER_HPP
#include <windows.h>
#include <imagehlp.h>
// This is a very plain wrapper for loading dbghelp.dll. It does not offer
// any additional functionality. It takes care of locking.
class outputStream;
// Please note: dbghelp.dll may not have been loaded, or it may have been loaded but not
// all functions may be available (because on the target system dbghelp.dll is of an
// older version).
// In all these cases we return an error from the WindowsDbgHelp::symXXXX() wrapper. We never
// assert. It should always be safe to call these functions, but caller has to process the
// return code (which he would have to do anyway).
namespace WindowsDbgHelp {
DWORD symSetOptions(DWORD);
DWORD symGetOptions(void);
BOOL symInitialize(HANDLE, PCTSTR, BOOL);
BOOL symGetSymFromAddr64(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
DWORD unDecorateSymbolName(const char*, char*, DWORD, DWORD);
BOOL symSetSearchPath(HANDLE, PCTSTR);
BOOL symGetSearchPath(HANDLE, PTSTR, int);
BOOL stackWalk64(DWORD MachineType,
HANDLE hProcess,
HANDLE hThread,
LPSTACKFRAME64 StackFrame,
PVOID ContextRecord);
PVOID symFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase);
DWORD64 symGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr);
BOOL miniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
BOOL symGetLineFromAddr64 (HANDLE hProcess, DWORD64 dwAddr,
PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line);
// Print one liner describing state (if library loaded, which functions are
// missing - if any, and the dbhelp API version)
void print_state_on(outputStream* st);
};
#endif // OS_WINDOWS_VM_DBGHELPLOADER_HPP

View File

@ -106,8 +106,8 @@ struct Atomic::PlatformAdd
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(4 == sizeof(I));
STATIC_CAST(4 == sizeof(D));
STATIC_ASSERT(4 == sizeof(I));
STATIC_ASSERT(4 == sizeof(D));
D result;
@ -129,8 +129,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(8 == sizeof(I));
STATIC_CAST(8 == sizeof(D));
STATIC_ASSERT(8 == sizeof(I));
STATIC_ASSERT(8 == sizeof(D));
D result;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -29,7 +29,6 @@
private:
void pd_initialize() {
_anchor.clear();
_last_interpreter_fp = NULL;
}
// The `last' frame is the youngest Java frame on the thread's stack.
@ -60,20 +59,4 @@
bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext,
bool isInJava);
// -Xprof support
//
// In order to find the last Java fp from an async profile
// tick, we store the current interpreter fp in the thread.
// This value is only valid while we are in the C++ interpreter
// and profiling.
protected:
intptr_t *_last_interpreter_fp;
public:
static ByteSize last_interpreter_fp_offset() {
return byte_offset_of(JavaThread, _last_interpreter_fp);
}
intptr_t* last_interpreter_fp() { return _last_interpreter_fp; }
#endif // OS_CPU_AIX_PPC_VM_THREAD_AIX_PPC_HPP

View File

@ -184,8 +184,8 @@ struct Atomic::PlatformAdd
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(4 == sizeof(I));
STATIC_CAST(4 == sizeof(D));
STATIC_ASSERT(4 == sizeof(I));
STATIC_ASSERT(4 == sizeof(D));
#ifdef ARM
return add_using_helper<int>(arm_add_and_fetch, add_value, dest);
@ -201,8 +201,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(8 == sizeof(I));
STATIC_CAST(8 == sizeof(D));
STATIC_ASSERT(8 == sizeof(I));
STATIC_ASSERT(8 == sizeof(D));
return __sync_add_and_fetch(dest, add_value);
}
@ -283,7 +283,7 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value,
T volatile* dest,
T compare_value,
cmpxchg_memory_order order) const {
STATIC_CAST(4 == sizeof(T));
STATIC_ASSERT(4 == sizeof(T));
#ifdef ARM
return cmpxchg_using_helper<int>(arm_compare_and_swap, exchange_value, dest, compare_value);
#else
@ -301,7 +301,7 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
T volatile* dest,
T compare_value,
cmpxchg_memory_order order) const {
STATIC_CAST(8 == sizeof(T));
STATIC_ASSERT(8 == sizeof(T));
return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
}

View File

@ -104,8 +104,8 @@ struct Atomic::PlatformAdd
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(4 == sizeof(I));
STATIC_CAST(4 == sizeof(D));
STATIC_ASSERT(4 == sizeof(I));
STATIC_ASSERT(4 == sizeof(D));
D result;
@ -127,8 +127,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(8 == sizeof(I));
STATIC_CAST(8 == sizeof(D));
STATIC_ASSERT(8 == sizeof(I));
STATIC_ASSERT(8 == sizeof(D));
D result;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -30,7 +30,6 @@
void pd_initialize() {
_anchor.clear();
_last_interpreter_fp = NULL;
}
// The `last' frame is the youngest Java frame on the thread's stack.
@ -62,22 +61,4 @@
bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava);
protected:
// -Xprof support
//
// In order to find the last Java fp from an async profile
// tick, we store the current interpreter fp in the thread.
// This value is only valid while we are in the C++ interpreter
// and profiling.
intptr_t *_last_interpreter_fp;
public:
static ByteSize last_interpreter_fp_offset() {
return byte_offset_of(JavaThread, _last_interpreter_fp);
}
intptr_t* last_interpreter_fp() { return _last_interpreter_fp; }
#endif // OS_CPU_LINUX_PPC_VM_THREAD_LINUX_PPC_HPP

View File

@ -92,9 +92,9 @@ struct Atomic::PlatformAdd
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(4 == sizeof(I));
STATIC_CAST(4 == sizeof(D));
inline D Atomic::PlatformAdd<4>::add_and_fetch(I inc, D volatile* dest) const {
STATIC_ASSERT(4 == sizeof(I));
STATIC_ASSERT(4 == sizeof(D));
D old, upd;
@ -143,9 +143,9 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(8 == sizeof(I));
STATIC_CAST(8 == sizeof(D));
inline D Atomic::PlatformAdd<8>::add_and_fetch(I inc, D volatile* dest) const {
STATIC_ASSERT(8 == sizeof(I));
STATIC_ASSERT(8 == sizeof(D));
D old, upd;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -30,7 +30,6 @@
void pd_initialize() {
_anchor.clear();
_last_interpreter_fp = NULL;
}
// The `last' frame is the youngest Java frame on the thread's stack.
@ -61,22 +60,4 @@
bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava);
protected:
// -Xprof support
//
// In order to find the last Java fp from an async profile
// tick, we store the current interpreter fp in the thread.
// This value is only valid while we are in the C++ interpreter
// and profiling.
intptr_t *_last_interpreter_fp;
public:
static ByteSize last_interpreter_fp_offset() {
return byte_offset_of(JavaThread, _last_interpreter_fp);
}
intptr_t* last_interpreter_fp() { return _last_interpreter_fp; }
#endif // OS_CPU_LINUX_S390_VM_THREAD_LINUX_S390_HPP

View File

@ -62,8 +62,8 @@ struct Atomic::PlatformAdd
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(4 == sizeof(I));
STATIC_CAST(4 == sizeof(D));
STATIC_ASSERT(4 == sizeof(I));
STATIC_ASSERT(4 == sizeof(D));
D rv;
__asm__ volatile(
@ -81,10 +81,11 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co
return rv;
}
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(8 == sizeof(I));
STATIC_CAST(8 == sizeof(D));
STATIC_ASSERT(8 == sizeof(I));
STATIC_ASSERT(8 == sizeof(D));
D rv;
__asm__ volatile(

View File

@ -178,8 +178,8 @@ struct Atomic::PlatformAdd
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(4 == sizeof(I));
STATIC_CAST(4 == sizeof(D));
STATIC_ASSERT(4 == sizeof(I));
STATIC_ASSERT(4 == sizeof(D));
#ifdef ARM
return add_using_helper<int>(arm_add_and_fetch, add_value, dest);
@ -195,8 +195,8 @@ inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) co
template<>
template<typename I, typename D>
inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const {
STATIC_CAST(8 == sizeof(I));
STATIC_CAST(8 == sizeof(D));
STATIC_ASSERT(8 == sizeof(I));
STATIC_ASSERT(8 == sizeof(D));
return __sync_add_and_fetch(dest, add_value);
}

View File

@ -29,7 +29,6 @@
#include "classfile/vmSymbols.hpp"
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "decoder_windows.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm_windows.h"
#include "memory/allocation.inline.hpp"
@ -51,10 +50,12 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "unwind_windows_x86.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
#include "windbghelp.hpp"
# include "unwind_windows_x86.hpp"
#undef REG_SP
#undef REG_FP
#undef REG_PC
@ -401,24 +402,18 @@ bool os::platform_print_native_stack(outputStream* st, const void* context,
lastpc = pc;
}
PVOID p = WindowsDbgHelp::SymFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset);
PVOID p = WindowsDbgHelp::symFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset);
if (!p) {
// StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash.
break;
}
BOOL result = WindowsDbgHelp::StackWalk64(
BOOL result = WindowsDbgHelp::stackWalk64(
IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType,
GetCurrentProcess(), // __in HANDLE hProcess,
GetCurrentThread(), // __in HANDLE hThread,
&stk, // __inout LP STACKFRAME64 StackFrame,
&ctx, // __inout PVOID ContextRecord,
NULL, // __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
WindowsDbgHelp::pfnSymFunctionTableAccess64(),
// __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
WindowsDbgHelp::pfnSymGetModuleBase64(),
// __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
NULL); // __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
&ctx); // __inout PVOID ContextRecord,
if (!result) {
break;

View File

@ -12,7 +12,6 @@
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
-Xprof output cpu profiling data (deprecated)
-Xfuture enable strictest checks, anticipating future default
-Xrs reduce use of OS signals by Java/VM (see documentation)
-Xcheck:jni perform additional checks for JNI functions

View File

@ -478,6 +478,8 @@ void AOTCodeHeap::link_stub_routines_symbols() {
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_oop_disjoint_arraycopy", address, StubRoutines::_arrayof_oop_disjoint_arraycopy);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_arrayof_oop_disjoint_arraycopy_uninit", address, StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_unsafe_arraycopy", address, StubRoutines::_unsafe_arraycopy);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_checkcast_arraycopy", address, StubRoutines::_checkcast_arraycopy);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_encryptBlock", address, StubRoutines::_aescrypt_encryptBlock);

View File

@ -57,7 +57,6 @@
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/handles.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/init.hpp"
@ -147,6 +146,7 @@ ClassPathEntry* ClassLoader::_jrt_entry = NULL;
ClassPathEntry* ClassLoader::_first_append_entry = NULL;
ClassPathEntry* ClassLoader::_last_append_entry = NULL;
int ClassLoader::_num_entries = 0;
int ClassLoader::_num_boot_entries = -1;
#if INCLUDE_CDS
GrowableArray<char*>* ClassLoader::_boot_modules_array = NULL;
GrowableArray<char*>* ClassLoader::_platform_modules_array = NULL;
@ -242,7 +242,7 @@ const char* ClassLoader::package_from_name(const char* const class_name, bool* b
// Given a fully qualified class name, find its defining package in the class loader's
// package entry table.
static PackageEntry* get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS) {
PackageEntry* ClassLoader::get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS) {
ResourceMark rm(THREAD);
const char *pkg_name = ClassLoader::package_from_name(class_name);
if (pkg_name == NULL) {
@ -509,7 +509,7 @@ ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
#endif
} else {
PackageEntry* package_entry = get_package_entry(name, ClassLoaderData::the_null_class_loader_data(), CHECK_NULL);
PackageEntry* package_entry = ClassLoader::get_package_entry(name, ClassLoaderData::the_null_class_loader_data(), CHECK_NULL);
if (package_entry != NULL) {
ResourceMark rm;
// Get the module name
@ -540,6 +540,13 @@ ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
return NULL;
}
JImageLocationRef ClassLoader::jimage_find_resource(JImageFile* jf,
const char* module_name,
const char* file_name,
jlong &size) {
return ((*JImageFindResource)(jf, module_name, get_jimage_version_string(), file_name, &size));
}
#ifndef PRODUCT
bool ctw_visitor(JImageFile* jimage,
const char* module_name, const char* version, const char* package,
@ -1066,7 +1073,7 @@ void ClassLoader::load_zip_library() {
char path[JVM_MAXPATHLEN];
char ebuf[1024];
void* handle = NULL;
if (os::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip")) {
if (os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), "zip")) {
handle = os::dll_load(path, ebuf, sizeof ebuf);
}
if (handle == NULL) {
@ -1104,7 +1111,7 @@ void ClassLoader::load_jimage_library() {
char path[JVM_MAXPATHLEN];
char ebuf[1024];
void* handle = NULL;
if (os::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "jimage")) {
if (os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), "jimage")) {
handle = os::dll_load(path, ebuf, sizeof ebuf);
}
if (handle == NULL) {
@ -1434,7 +1441,6 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
const char* const class_name = name->as_C_string();
EventMark m("loading class %s", class_name);
ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
const char* const file_name = file_name_for_class_name(class_name,
name->utf8_length());
@ -1459,9 +1465,6 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
// This would include:
// [--patch-module=<module>=<file>(<pathsep><file>)*]; [jimage | exploded module build]
//
// DumpSharedSpaces and search_append_only are mutually exclusive and cannot
// be true at the same time.
assert(!(DumpSharedSpaces && search_append_only), "DumpSharedSpaces and search_append_only are both true");
// Load Attempt #1: --patch-module
// Determine the class' defining module. If it appears in the _patch_mod_entries,
@ -1507,6 +1510,11 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
e = _first_append_entry;
while (e != NULL) {
if (DumpSharedSpaces && classpath_index >= _num_boot_entries) {
// Do not load any class from the app classpath using the boot loader. Let
// the built-in app class laoder load them.
break;
}
stream = e->open_stream(file_name, CHECK_NULL);
if (!context.check(stream, classpath_index)) {
return NULL;
@ -1520,9 +1528,6 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
}
if (NULL == stream) {
if (DumpSharedSpaces) {
tty->print_cr("Preload Warning: Cannot find %s", class_name);
}
return NULL;
}
@ -1548,6 +1553,100 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
return context.record_result(name, e, classpath_index, result, THREAD);
}
#if INCLUDE_CDS
static char* skip_uri_protocol(char* source) {
if (strncmp(source, "file:", 5) == 0) {
// file: protocol path could start with file:/ or file:///
// locate the char after all the forward slashes
int offset = 5;
while (*(source + offset) == '/') {
offset++;
}
source += offset;
// for non-windows platforms, move back one char as the path begins with a '/'
#ifndef _WINDOWS
source -= 1;
#endif
} else if (strncmp(source, "jrt:/", 5) == 0) {
source += 5;
}
return source;
}
void ClassLoader::record_shared_class_loader_type(InstanceKlass* ik, const ClassFileStream* stream) {
assert(DumpSharedSpaces, "sanity");
assert(stream != NULL, "sanity");
if (ik->is_anonymous()) {
// We do not archive anonymous classes.
return;
}
if (stream->source() == NULL) {
if (ik->class_loader() == NULL) {
// JFR classes
ik->set_shared_classpath_index(0);
ik->set_class_loader_type(ClassLoader::BOOT_LOADER);
}
return;
}
assert(has_jrt_entry(), "CDS dumping does not support exploded JDK build");
ModuleEntry* module = ik->module();
ClassPathEntry* e = NULL;
int classpath_index = 0;
// Check if the class is from the runtime image
if (module != NULL && (module->location() != NULL) &&
(module->location()->starts_with("jrt:"))) {
e = _jrt_entry;
classpath_index = 0;
} else {
classpath_index = 1;
ResourceMark rm;
char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN);
for (e = _first_append_entry; e != NULL; e = e->next()) {
if (get_canonical_path(e->name(), canonical_path, JVM_MAXPATHLEN)) {
char* src = (char*)stream->source();
// save the path from the file: protocol or the module name from the jrt: protocol
// if no protocol prefix is found, src is the same as stream->source() after the following call
src = skip_uri_protocol(src);
if (strcmp(canonical_path, os::native_path((char*)src)) == 0) {
break;
}
classpath_index ++;
}
}
if (e == NULL) {
assert(ik->shared_classpath_index() < 0,
"must be a class from a custom jar which isn't in the class path or boot class path");
return;
}
}
if (classpath_index < _num_boot_entries) {
// ik is either:
// 1) a boot class loaded from the runtime image during vm initialization (classpath_index = 0); or
// 2) a user's class from -Xbootclasspath/a (classpath_index > 0)
// In the second case, the classpath_index, classloader_type will be recorded via
// context.record_result() in ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS).
if (classpath_index > 0) {
return;
}
}
ResourceMark rm;
const char* const class_name = ik->name()->as_C_string();
const char* const file_name = file_name_for_class_name(class_name,
ik->name()->utf8_length());
assert(file_name != NULL, "invariant");
Thread* THREAD = Thread::current();
ClassLoaderExt::Context context(class_name, file_name, CATCH);
context.record_result(ik->name(), e, classpath_index, ik, THREAD);
}
#endif // INCLUDE_CDS
// Initialize the class loader's access to methods in libzip. Parse and
// process the boot classpath into a list ClassPathEntry objects. Once
// this list has been created, it must not change order (see class PackageInfo)
@ -1632,6 +1731,7 @@ void ClassLoader::initialize() {
#if INCLUDE_CDS
void ClassLoader::initialize_shared_path() {
if (DumpSharedSpaces) {
_num_boot_entries = _num_entries;
ClassLoaderExt::setup_search_paths();
_shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
}

View File

@ -25,6 +25,7 @@
#ifndef SHARE_VM_CLASSFILE_CLASSLOADER_HPP
#define SHARE_VM_CLASSFILE_CLASSLOADER_HPP
#include "classfile/jimage.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/perfData.hpp"
#include "utilities/exceptions.hpp"
@ -47,6 +48,7 @@
class JImageFile;
class ClassFileStream;
class PackageEntry;
class ClassPathEntry : public CHeapObj<mtClass> {
private:
@ -103,7 +105,6 @@ typedef struct {
jlong pos; /* position of LOC header (if negative) or data */
} jzentry;
class ClassPathZipEntry: public ClassPathEntry {
enum {
_unknown = 0,
@ -249,6 +250,10 @@ class ClassLoader: AllStatic {
// the entries on the _first_append_entry linked list.
static int _num_entries;
// number of entries in the boot class path including the
// java runtime image
static int _num_boot_entries;
// Array of module names associated with the boot class loader
CDS_ONLY(static GrowableArray<char*>* _boot_modules_array;)
@ -289,6 +294,7 @@ class ClassLoader: AllStatic {
static bool get_canonical_path(const char* orig, char* out, int len);
static const char* file_name_for_class_name(const char* class_name,
int class_name_len);
static PackageEntry* get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS);
public:
static jboolean decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg);
@ -436,7 +442,10 @@ class ClassLoader: AllStatic {
static void initialize_module_loader_map(JImageFile* jimage);
static s2 classloader_type(Symbol* class_name, ClassPathEntry* e,
int classpath_index, TRAPS);
static void record_shared_class_loader_type(InstanceKlass* ik, const ClassFileStream* stream);
#endif
static JImageLocationRef jimage_find_resource(JImageFile* jf, const char* module_name,
const char* file_name, jlong &size);
static void trace_class_path(const char* msg, const char* name = NULL);

View File

@ -75,6 +75,9 @@
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#if INCLUDE_ALL_GCS
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#endif // INCLUDE_ALL_GCS
#if INCLUDE_TRACE
#include "trace/tracing.hpp"
#endif
@ -764,6 +767,25 @@ OopHandle ClassLoaderData::add_handle(Handle h) {
return OopHandle(_handles.add(h()));
}
void ClassLoaderData::remove_handle(OopHandle h) {
oop* ptr = h.ptr_raw();
if (ptr != NULL) {
assert(_handles.contains(ptr), "Got unexpected handle " PTR_FORMAT, p2i(ptr));
#if INCLUDE_ALL_GCS
// This barrier is used by G1 to remember the old oop values, so
// that we don't forget any objects that were live at the snapshot at
// the beginning.
if (UseG1GC) {
oop obj = *ptr;
if (obj != NULL) {
G1SATBCardTableModRefBS::enqueue(obj);
}
}
#endif
*ptr = NULL;
}
}
void ClassLoaderData::init_handle_locked(OopHandle& dest, Handle h) {
MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
if (dest.resolve() != NULL) {

View File

@ -364,6 +364,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
const char* loader_name();
OopHandle add_handle(Handle h);
void remove_handle(OopHandle h);
void init_handle_locked(OopHandle& pd, Handle h); // used for concurrent access to ModuleEntry::_pd field
void add_class(Klass* k, bool publicize = true);
void remove_class(Klass* k);

View File

@ -26,6 +26,7 @@
#define SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "oops/instanceKlass.hpp"
#include "runtime/handles.hpp"
@ -56,8 +57,15 @@ public:
if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) {
#if INCLUDE_CDS
if (DumpSharedSpaces) {
s2 classloader_type = ClassLoader::classloader_type(
class_name, e, classpath_index, CHECK_(result));
oop loader = result->class_loader();
s2 classloader_type = ClassLoader::BOOT_LOADER;
if (SystemDictionary::is_system_class_loader(loader)) {
classloader_type = ClassLoader::APP_LOADER;
ClassLoaderExt::set_has_app_classes();
} else if (SystemDictionary::is_platform_class_loader(loader)) {
classloader_type = ClassLoader::PLATFORM_LOADER;
ClassLoaderExt::set_has_platform_classes();
}
result->set_shared_classpath_index(classpath_index);
result->set_class_loader_type(classloader_type);
}
@ -82,6 +90,13 @@ public:
return true;
}
static Klass* load_one_class(ClassListParser* parser, TRAPS);
#if INCLUDE_CDS
static void set_has_app_classes() {}
static void set_has_platform_classes() {}
static char* read_manifest(ClassPathEntry* entry, jint *manifest_size, TRAPS) {
return NULL;
}
#endif
};
#endif // SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP

View File

@ -85,6 +85,7 @@ DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass)
void Dictionary::free_entry(DictionaryEntry* entry) {
// avoid recursion when deleting linked list
// pd_set is accessed during a safepoint.
while (entry->pd_set() != NULL) {
ProtectionDomainEntry* to_delete = entry->pd_set();
entry->set_pd_set(to_delete->next());
@ -101,7 +102,7 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
if (protection_domain == instance_klass()->protection_domain()) {
// Ensure this doesn't show up in the pd_set (invariant)
bool in_pd_set = false;
for (ProtectionDomainEntry* current = _pd_set;
for (ProtectionDomainEntry* current = pd_set_acquire();
current != NULL;
current = current->next()) {
if (current->protection_domain() == protection_domain) {
@ -121,7 +122,7 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
return true;
}
for (ProtectionDomainEntry* current = _pd_set;
for (ProtectionDomainEntry* current = pd_set_acquire();
current != NULL;
current = current->next()) {
if (current->protection_domain() == protection_domain) return true;
@ -135,12 +136,12 @@ void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_
if (!contains_protection_domain(protection_domain())) {
ProtectionDomainCacheEntry* entry = SystemDictionary::cache_get(protection_domain);
ProtectionDomainEntry* new_head =
new ProtectionDomainEntry(entry, _pd_set);
new ProtectionDomainEntry(entry, pd_set());
// Warning: Preserve store ordering. The SystemDictionary is read
// without locks. The new ProtectionDomainEntry must be
// complete before other threads can be allowed to see it
// via a store to _pd_set.
OrderAccess::release_store_ptr(&_pd_set, new_head);
release_set_pd_set(new_head);
}
LogTarget(Trace, protectiondomain) lt;
if (lt.is_enabled()) {
@ -365,11 +366,21 @@ void Dictionary::reorder_dictionary_for_sharing() {
for (int i = 0; i < table_size(); ++i) {
DictionaryEntry* p = bucket(i);
while (p != NULL) {
DictionaryEntry* tmp;
tmp = p->next();
p->set_next(master_list);
master_list = p;
p = tmp;
DictionaryEntry* next = p->next();
InstanceKlass*ik = p->instance_klass();
// we cannot include signed classes in the archive because the certificates
// used during dump time may be different than those used during
// runtime (due to expiration, etc).
if (ik->signers() != NULL) {
ResourceMark rm;
tty->print_cr("Preload Warning: Skipping %s from signed JAR",
ik->name()->as_C_string());
free_entry(p);
} else {
p->set_next(master_list);
master_list = p;
}
p = next;
}
set_entry(i, NULL);
}

View File

@ -29,6 +29,7 @@
#include "classfile/systemDictionary.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.hpp"
#include "runtime/orderAccess.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/ostream.hpp"
@ -48,21 +49,6 @@ class Dictionary : public Hashtable<InstanceKlass*, mtClass> {
DictionaryEntry* get_entry(int index, unsigned int hash, Symbol* name);
protected:
DictionaryEntry* bucket(int i) const {
return (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::bucket(i);
}
// The following method is not MT-safe and must be done under lock.
DictionaryEntry** bucket_addr(int i) {
return (DictionaryEntry**)Hashtable<InstanceKlass*, mtClass>::bucket_addr(i);
}
void add_entry(int index, DictionaryEntry* new_entry) {
Hashtable<InstanceKlass*, mtClass>::add_entry(index, (HashtableEntry<InstanceKlass*, mtClass>*)new_entry);
}
void free_entry(DictionaryEntry* entry);
static size_t entry_size();
public:
Dictionary(ClassLoaderData* loader_data, int table_size);
@ -106,6 +92,24 @@ public:
void print_on(outputStream* st) const;
void verify();
DictionaryEntry* bucket(int i) const {
return (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::bucket(i);
}
// The following method is not MT-safe and must be done under lock.
DictionaryEntry** bucket_addr(int i) {
return (DictionaryEntry**)Hashtable<InstanceKlass*, mtClass>::bucket_addr(i);
}
void add_entry(int index, DictionaryEntry* new_entry) {
Hashtable<InstanceKlass*, mtClass>::add_entry(index, (HashtableEntry<InstanceKlass*, mtClass>*)new_entry);
}
void unlink_entry(DictionaryEntry* entry) {
Hashtable<InstanceKlass*, mtClass>::unlink_entry((HashtableEntry<InstanceKlass*, mtClass>*)entry);
}
void free_entry(DictionaryEntry* entry);
};
// An entry in the class loader data dictionaries, this describes a class as
@ -134,7 +138,7 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
// It is essentially a cache to avoid repeated Java up-calls to
// ClassLoader.checkPackageAccess().
//
ProtectionDomainEntry* _pd_set;
ProtectionDomainEntry* volatile _pd_set;
public:
// Tells whether a protection is in the approved set.
@ -153,8 +157,15 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
return (DictionaryEntry**)HashtableEntry<InstanceKlass*, mtClass>::next_addr();
}
ProtectionDomainEntry* pd_set() const { return _pd_set; }
void set_pd_set(ProtectionDomainEntry* pd_set) { _pd_set = pd_set; }
ProtectionDomainEntry* pd_set() const { return _pd_set; }
void set_pd_set(ProtectionDomainEntry* new_head) { _pd_set = new_head; }
ProtectionDomainEntry* pd_set_acquire() const {
return (ProtectionDomainEntry*)OrderAccess::load_ptr_acquire(&_pd_set);
}
void release_set_pd_set(ProtectionDomainEntry* new_head) {
OrderAccess::release_store_ptr(&_pd_set, new_head);
}
// Tells whether the initiating class' protection domain can access the klass in this entry
bool is_valid_protection_domain(Handle protection_domain) {
@ -167,7 +178,7 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
}
void verify_protection_domain_set() {
for (ProtectionDomainEntry* current = _pd_set;
for (ProtectionDomainEntry* current = pd_set(); // accessed at a safepoint
current != NULL;
current = current->_next) {
current->_pd_cache->protection_domain()->verify();
@ -181,7 +192,7 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
void print_count(outputStream *st) {
int count = 0;
for (ProtectionDomainEntry* current = _pd_set;
for (ProtectionDomainEntry* current = pd_set(); // accessed inside SD lock
current != NULL;
current = current->_next) {
count++;
@ -246,10 +257,6 @@ class SymbolPropertyEntry : public HashtableEntry<Symbol*, mtSymbol> {
class SymbolPropertyTable : public Hashtable<Symbol*, mtSymbol> {
friend class VMStructs;
private:
SymbolPropertyEntry* bucket(int i) {
return (SymbolPropertyEntry*) Hashtable<Symbol*, mtSymbol>::bucket(i);
}
// The following method is not MT-safe and must be done under lock.
SymbolPropertyEntry** bucket_addr(int i) {
return (SymbolPropertyEntry**) Hashtable<Symbol*, mtSymbol>::bucket_addr(i);
@ -303,5 +310,9 @@ public:
void methods_do(void f(Method*));
void verify();
SymbolPropertyEntry* bucket(int i) {
return (SymbolPropertyEntry*) Hashtable<Symbol*, mtSymbol>::bucket(i);
}
};
#endif // SHARE_VM_CLASSFILE_DICTIONARY_HPP

View File

@ -70,11 +70,25 @@ InstanceKlass* KlassFactory::check_shared_class_file_load_hook(
ClassLoaderData* loader_data =
ClassLoaderData::class_loader_data(class_loader());
int path_index = ik->shared_classpath_index();
SharedClassPathEntry* ent =
(SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
const char* pathname;
if (path_index < 0) {
// shared classes loaded by user defined class loader
// do not have shared_classpath_index
ModuleEntry* mod_entry = ik->module();
if (mod_entry != NULL && (mod_entry->location() != NULL)) {
ResourceMark rm;
pathname = (const char*)(mod_entry->location()->as_C_string());
} else {
pathname = "";
}
} else {
SharedClassPathEntry* ent =
(SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
pathname = ent == NULL ? NULL : ent->name();
}
ClassFileStream* stream = new ClassFileStream(ptr,
end_ptr - ptr,
ent == NULL ? NULL : ent->name(),
pathname,
ClassFileStream::verify);
ClassFileParser parser(stream,
class_name,
@ -215,8 +229,10 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,
TRACE_KLASS_CREATION(result, parser, THREAD);
#if INCLUDE_CDS && INCLUDE_JVMTI
#if INCLUDE_CDS
if (DumpSharedSpaces) {
ClassLoader::record_shared_class_loader_type(result, stream);
#if INCLUDE_JVMTI
assert(cached_class_file == NULL, "Sanity");
// Archive the class stream data into the optional data section
JvmtiCachedClassFileData *p;
@ -233,8 +249,9 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,
p->length = len;
memcpy(p->data, bytes, len);
result->set_archived_class_data(p);
#endif // INCLUDE_JVMTI
}
#endif
#endif // INCLUDE_CDS
return result;
}

View File

@ -729,7 +729,6 @@ bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
}
G1CollectedHeap::heap()->end_archive_alloc_range(string_space, os::vm_allocation_granularity());
assert(string_space->length() <= 2, "sanity");
return true;
}

View File

@ -66,6 +66,7 @@
#include "prims/resolvedMethodTable.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/arguments.hpp"
#include "runtime/arguments_ext.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/handles.inline.hpp"
@ -869,7 +870,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
// during compilations.
MutexLocker mu(Compile_lock, THREAD);
update_dictionary(d_index, d_hash, p_index, p_hash,
k, class_loader, THREAD);
k, class_loader, THREAD);
}
if (JvmtiExport::should_post_class_load()) {
@ -910,12 +911,9 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
if (protection_domain() == NULL) return k;
// Check the protection domain has the right access
{
MutexLocker mu(SystemDictionary_lock, THREAD);
if (dictionary->is_valid_protection_domain(d_index, d_hash, name,
protection_domain)) {
return k;
}
if (dictionary->is_valid_protection_domain(d_index, d_hash, name,
protection_domain)) {
return k;
}
// Verify protection domain. If it fails an exception is thrown
@ -1009,7 +1007,6 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
// Create a new CLD for anonymous class, that uses the same class loader
// as the host_klass
guarantee(host_klass->class_loader() == class_loader(), "should be the same");
guarantee(!DumpSharedSpaces, "must not create anonymous classes when dumping");
loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader(), CHECK_NULL);
} else {
loader_data = ClassLoaderData::class_loader_data(class_loader());
@ -1078,6 +1075,15 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
Handle protection_domain,
ClassFileStream* st,
TRAPS) {
#if INCLUDE_CDS
ResourceMark rm(THREAD);
if (DumpSharedSpaces && !class_loader.is_null() &&
!ArgumentsExt::using_AppCDS() && strcmp(class_name->as_C_string(), "Unnamed") != 0) {
// If AppCDS is not enabled, don't define the class at dump time (except for the "Unnamed"
// class, which is used by MethodHandles).
THROW_MSG_NULL(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string());
}
#endif
HandleMark hm(THREAD);
@ -1104,11 +1110,13 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
InstanceKlass* k = NULL;
#if INCLUDE_CDS
k = SystemDictionaryShared::lookup_from_stream(class_name,
class_loader,
protection_domain,
st,
CHECK_NULL);
if (!DumpSharedSpaces) {
k = SystemDictionaryShared::lookup_from_stream(class_name,
class_loader,
protection_domain,
st,
CHECK_NULL);
}
#endif
if (k == NULL) {
@ -1217,6 +1225,16 @@ bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
"Cannot use sharing if java.base is patched");
ResourceMark rm;
int path_index = ik->shared_classpath_index();
ClassLoaderData* loader_data = class_loader_data(class_loader);
if (path_index < 0) {
// path_index < 0 indicates that the class is intended for a custom loader
// and should not be loaded by boot/platform/app loaders
if (loader_data->is_builtin_class_loader_data()) {
return false;
} else {
return true;
}
}
SharedClassPathEntry* ent =
(SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
if (!Universe::is_module_initialized()) {
@ -1230,7 +1248,6 @@ bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
PackageEntry* pkg_entry = NULL;
ModuleEntry* mod_entry = NULL;
const char* pkg_string = NULL;
ClassLoaderData* loader_data = class_loader_data(class_loader);
pkg_name = InstanceKlass::package_from_name(class_name, CHECK_false);
if (pkg_name != NULL) {
pkg_string = pkg_name->as_C_string();
@ -1403,6 +1420,18 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
}
return ik;
}
void SystemDictionary::clear_invoke_method_table() {
SymbolPropertyEntry* spe = NULL;
for (int index = 0; index < _invoke_method_table->table_size(); index++) {
SymbolPropertyEntry* p = _invoke_method_table->bucket(index);
while (p != NULL) {
spe = p;
p = p->next();
_invoke_method_table->free_entry(spe);
}
}
}
#endif // INCLUDE_CDS
InstanceKlass* SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
@ -1449,7 +1478,6 @@ InstanceKlass* SystemDictionary::load_instance_class(Symbol* class_name, Handle
}
}
} else {
assert(!DumpSharedSpaces, "Archive dumped after module system initialization");
// After the module system has been initialized, check if the class'
// package is in a module defined to the boot loader.
if (pkg_name == NULL || pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
@ -1968,8 +1996,19 @@ void SystemDictionary::methods_do(void f(Method*)) {
invoke_method_table()->methods_do(f);
}
class RemoveClassesClosure : public CLDClosure {
public:
void do_cld(ClassLoaderData* cld) {
if (cld->is_system_class_loader_data() || cld->is_platform_class_loader_data()) {
cld->dictionary()->remove_classes_in_error_state();
}
}
};
void SystemDictionary::remove_classes_in_error_state() {
ClassLoaderData::the_null_class_loader_data()->dictionary()->remove_classes_in_error_state();
RemoveClassesClosure rcc;
ClassLoaderDataGraph::cld_do(&rcc);
}
// ----------------------------------------------------------------------------
@ -2910,6 +2949,56 @@ int SystemDictionaryDCmd::num_arguments() {
}
}
class CombineDictionariesClosure : public CLDClosure {
private:
Dictionary* _master_dictionary;
public:
CombineDictionariesClosure(Dictionary* master_dictionary) :
_master_dictionary(master_dictionary) {}
void do_cld(ClassLoaderData* cld) {
ResourceMark rm;
if (cld->is_system_class_loader_data() || cld->is_platform_class_loader_data()) {
for (int i = 0; i < cld->dictionary()->table_size(); ++i) {
Dictionary* curr_dictionary = cld->dictionary();
DictionaryEntry* p = curr_dictionary->bucket(i);
while (p != NULL) {
Symbol* name = p->instance_klass()->name();
unsigned int d_hash = _master_dictionary->compute_hash(name);
int d_index = _master_dictionary->hash_to_index(d_hash);
DictionaryEntry* next = p->next();
if (p->literal()->class_loader_data() != cld) {
// This is an initiating class loader entry; don't use it
log_trace(cds)("Skipping initiating cl entry: %s", name->as_C_string());
curr_dictionary->free_entry(p);
} else {
log_trace(cds)("Moved to boot dictionary: %s", name->as_C_string());
curr_dictionary->unlink_entry(p);
p->set_pd_set(NULL); // pd_set is runtime only information and will be reconstructed.
_master_dictionary->add_entry(d_index, p);
}
p = next;
}
*curr_dictionary->bucket_addr(i) = NULL;
}
}
}
};
// Combining platform and system loader dictionaries into boot loader dictionaries.
// During run time, we only have one shared dictionary.
void SystemDictionary::combine_shared_dictionaries() {
assert(DumpSharedSpaces, "dump time only");
Dictionary* master_dictionary = ClassLoaderData::the_null_class_loader_data()->dictionary();
CombineDictionariesClosure cdc(master_dictionary);
ClassLoaderDataGraph::cld_do(&cdc);
// These tables are no longer valid or necessary. Keeping them around will
// cause SystemDictionary::verify() to fail. Let's empty them.
_placeholders = new PlaceholderTable(_placeholder_table_size);
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
NOT_PRODUCT(SystemDictionary::verify());
}
// caller needs ResourceMark
const char* SystemDictionary::loader_name(const oop loader) {

View File

@ -385,6 +385,7 @@ public:
public:
// Sharing support.
static void reorder_dictionary_for_sharing();
static void combine_shared_dictionaries();
static size_t count_bytes_for_buckets();
static size_t count_bytes_for_table();
static void copy_buckets(char* top, char* end);
@ -643,6 +644,7 @@ public:
TRAPS);
static bool is_system_class_loader(oop class_loader);
static bool is_platform_class_loader(oop class_loader);
static void clear_invoke_method_table();
protected:
static InstanceKlass* find_shared_class(Symbol* class_name);

View File

@ -1220,7 +1220,7 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
// for stack scanning.
if (state == not_entrant) {
mark_as_seen_on_stack();
OrderAccess::storestore();
OrderAccess::storestore(); // _stack_traversal_mark and _state
}
// Change state

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -136,7 +136,7 @@ class nmethod : public CompiledMethod {
// stack. An not_entrant method can be removed when there are no
// more activations, i.e., when the _stack_traversal_mark is less than
// current sweep traversal index.
volatile jlong _stack_traversal_mark;
volatile long _stack_traversal_mark;
// The _hotness_counter indicates the hotness of a method. The higher
// the value the hotter the method. The hotness counter of a nmethod is
@ -396,8 +396,8 @@ public:
public:
// Sweeper support
jlong stack_traversal_mark() { return OrderAccess::load_acquire(&_stack_traversal_mark); }
void set_stack_traversal_mark(jlong l) { OrderAccess::release_store(&_stack_traversal_mark, l); }
long stack_traversal_mark() { return _stack_traversal_mark; }
void set_stack_traversal_mark(long l) { _stack_traversal_mark = l; }
// implicit exceptions support
address continuation_for_implicit_exception(address pc);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,7 +30,6 @@
#include "gc/shared/collectedHeap.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/stubCodeGenerator.hpp"
@ -163,7 +162,6 @@ class decode_env {
bool _print_pc;
bool _print_bytes;
address _cur_insn;
int _total_ticks;
int _bytes_per_line; // arch-specific formatting option
static bool match(const char* event, const char* tag) {
@ -213,18 +211,6 @@ class decode_env {
_nm->print_code_comment_on(st, COMMENT_COLUMN, pc0, pc);
// this calls reloc_string_for which calls oop::print_value_on
}
// Output pc bucket ticks if we have any
if (total_ticks() != 0) {
address bucket_pc = FlatProfiler::bucket_start_for(pc);
if (bucket_pc != NULL && bucket_pc > pc0 && bucket_pc <= pc) {
int bucket_count = FlatProfiler::bucket_count_for(pc0);
if (bucket_count != 0) {
st->bol();
st->print_cr("%3.1f%% [%d]", bucket_count*100.0/total_ticks(), bucket_count);
}
}
}
// follow each complete insn by a nice newline
st->cr();
}
@ -233,8 +219,6 @@ class decode_env {
outputStream* output() { return _output; }
address cur_insn() { return _cur_insn; }
int total_ticks() { return _total_ticks; }
void set_total_ticks(int n) { _total_ticks = n; }
const char* options() { return _option_buf; }
};
@ -561,20 +545,6 @@ void Disassembler::decode(nmethod* nm, outputStream* st) {
#endif
env.output()->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT "] " JLONG_FORMAT " bytes", p2i(p), p2i(end), ((jlong)(end - p)));
// If there has been profiling, print the buckets.
if (FlatProfiler::bucket_start_for(p) != NULL) {
unsigned char* p1 = p;
int total_bucket_count = 0;
while (p1 < end) {
unsigned char* p0 = p1;
p1 += pd_instruction_alignment();
address bucket_pc = FlatProfiler::bucket_start_for(p1);
if (bucket_pc != NULL && bucket_pc > p0 && bucket_pc <= p1)
total_bucket_count += FlatProfiler::bucket_count_for(p0);
}
env.set_total_ticks(total_bucket_count);
}
// Print constant table.
if (nm->consts_size() > 0) {
nm->print_nmethod_labels(env.output(), nm->consts_begin());

View File

@ -1719,7 +1719,6 @@ jint G1CollectedHeap::initialize() {
G1BlockOffsetTable::compute_size(g1_rs.size() / HeapWordSize),
G1BlockOffsetTable::heap_map_factor());
ReservedSpace cardtable_rs(G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize));
G1RegionToSpaceMapper* cardtable_storage =
create_aux_memory_mapper("Card Table",
G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize),

View File

@ -54,7 +54,6 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) :
_gc_par_phases[UniverseRoots] = new WorkerDataArray<double>(max_gc_threads, "Universe Roots (ms):");
_gc_par_phases[JNIRoots] = new WorkerDataArray<double>(max_gc_threads, "JNI Handles Roots (ms):");
_gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray<double>(max_gc_threads, "ObjectSynchronizer Roots (ms):");
_gc_par_phases[FlatProfilerRoots] = new WorkerDataArray<double>(max_gc_threads, "FlatProfiler Roots (ms):");
_gc_par_phases[ManagementRoots] = new WorkerDataArray<double>(max_gc_threads, "Management Roots (ms):");
_gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray<double>(max_gc_threads, "SystemDictionary Roots (ms):");
_gc_par_phases[CLDGRoots] = new WorkerDataArray<double>(max_gc_threads, "CLDG Roots (ms):");

View File

@ -49,7 +49,6 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
UniverseRoots,
JNIRoots,
ObjectSynchronizerRoots,
FlatProfilerRoots,
ManagementRoots,
SystemDictionaryRoots,
CLDGRoots,

View File

@ -62,7 +62,7 @@ public:
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
if (_g1h->is_obj_dead_cond(obj, _vo)) {
Log(gc, verify) log;
log.info("Root location " PTR_FORMAT " points to dead obj " PTR_FORMAT, p2i(p), p2i(obj));
log.error("Root location " PTR_FORMAT " points to dead obj " PTR_FORMAT, p2i(p), p2i(obj));
if (_vo == VerifyOption_G1UseMarkWord) {
log.error(" Mark word: " PTR_FORMAT, p2i(obj->mark()));
}

View File

@ -48,7 +48,6 @@
#include "prims/jvmtiExport.hpp"
#include "runtime/atomic.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.hpp"
#include "runtime/vmThread.hpp"

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,7 +38,6 @@
#include "gc/g1/g1RootProcessor.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/mutex.hpp"
#include "services/management.hpp"
#include "utilities/macros.hpp"
@ -271,13 +270,6 @@ void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
}
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::FlatProfilerRoots, worker_i);
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_FlatProfiler_oops_do)) {
FlatProfiler::oops_do(strong_roots);
}
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ManagementRoots, worker_i);
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_Management_oops_do)) {

View File

@ -57,7 +57,6 @@ class G1RootProcessor : public StackObj {
G1RP_PS_Universe_oops_do,
G1RP_PS_JNIHandles_oops_do,
G1RP_PS_ObjectSynchronizer_oops_do,
G1RP_PS_FlatProfiler_oops_do,
G1RP_PS_Management_oops_do,
G1RP_PS_SystemDictionary_oops_do,
G1RP_PS_ClassLoaderDataGraph_oops_do,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2017, 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
@ -39,7 +39,6 @@
#include "oops/objArrayKlass.inline.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/thread.hpp"
#include "runtime/vmThread.hpp"
@ -105,10 +104,6 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
ObjectSynchronizer::oops_do(&mark_and_push_closure);
break;
case flat_profiler:
FlatProfiler::oops_do(&mark_and_push_closure);
break;
case management:
Management::oops_do(&mark_and_push_closure);
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2017, 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
@ -94,12 +94,11 @@ class MarkFromRootsTask : public GCTask {
jni_handles = 2,
threads = 3,
object_synchronizer = 4,
flat_profiler = 5,
management = 6,
jvmti = 7,
system_dictionary = 8,
class_loader_data = 9,
code_cache = 10
management = 5,
jvmti = 6,
system_dictionary = 7,
class_loader_data = 8,
code_cache = 9
};
private:
RootType _root_type;

View File

@ -50,7 +50,6 @@
#include "logging/log.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/vmThread.hpp"
#include "services/management.hpp"
@ -514,7 +513,6 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
MarkingCodeBlobClosure each_active_code_blob(mark_and_push_closure(), !CodeBlobToOopClosure::FixRelocations);
Threads::oops_do(mark_and_push_closure(), &each_active_code_blob);
ObjectSynchronizer::oops_do(mark_and_push_closure());
FlatProfiler::oops_do(mark_and_push_closure());
Management::oops_do(mark_and_push_closure());
JvmtiExport::oops_do(mark_and_push_closure());
SystemDictionary::always_strong_oops_do(mark_and_push_closure());
@ -607,7 +605,6 @@ void PSMarkSweep::mark_sweep_phase3() {
JNIHandles::oops_do(adjust_pointer_closure()); // Global (strong) JNI handles
Threads::oops_do(adjust_pointer_closure(), NULL);
ObjectSynchronizer::oops_do(adjust_pointer_closure());
FlatProfiler::oops_do(adjust_pointer_closure());
Management::oops_do(adjust_pointer_closure());
JvmtiExport::oops_do(adjust_pointer_closure());
SystemDictionary::oops_do(adjust_pointer_closure());

View File

@ -60,7 +60,6 @@
#include "oops/objArrayKlass.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/vmThread.hpp"
#include "services/management.hpp"
@ -2086,7 +2085,6 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm,
// We scan the thread roots in parallel
Threads::create_thread_roots_marking_tasks(q);
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::object_synchronizer));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::flat_profiler));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::management));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::system_dictionary));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::class_loader_data));
@ -2169,7 +2167,6 @@ void PSParallelCompact::adjust_roots(ParCompactionManager* cm) {
JNIHandles::oops_do(&oop_closure); // Global (strong) JNI handles
Threads::oops_do(&oop_closure, NULL);
ObjectSynchronizer::oops_do(&oop_closure);
FlatProfiler::oops_do(&oop_closure);
Management::oops_do(&oop_closure);
JvmtiExport::oops_do(&oop_closure);
SystemDictionary::oops_do(&oop_closure);

View File

@ -49,7 +49,6 @@
#include "logging/log.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/threadCritical.hpp"
#include "runtime/vmThread.hpp"
@ -381,7 +380,6 @@ bool PSScavenge::invoke_no_policy() {
// We scan the thread roots in parallel
Threads::create_thread_roots_tasks(q);
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::object_synchronizer));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::flat_profiler));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::management));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::system_dictionary));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::class_loader_data));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,7 +38,6 @@
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/thread.hpp"
#include "runtime/vmThread.hpp"
#include "services/management.hpp"
@ -74,10 +73,6 @@ void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) {
ObjectSynchronizer::oops_do(&roots_closure);
break;
case flat_profiler:
FlatProfiler::oops_do(&roots_closure);
break;
case system_dictionary:
SystemDictionary::oops_do(&roots_closure);
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -57,12 +57,11 @@ class ScavengeRootsTask : public GCTask {
jni_handles = 2,
threads = 3,
object_synchronizer = 4,
flat_profiler = 5,
system_dictionary = 6,
class_loader_data = 7,
management = 8,
jvmti = 9,
code_cache = 10
system_dictionary = 5,
class_loader_data = 6,
management = 7,
jvmti = 8,
code_cache = 9
};
private:
RootType _root_type;

View File

@ -46,7 +46,6 @@
#include "oops/instanceRefKlass.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.inline.hpp"

View File

@ -47,7 +47,6 @@
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/handles.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
@ -71,7 +70,6 @@ enum GCH_strong_roots_tasks {
GCH_PS_Universe_oops_do,
GCH_PS_JNIHandles_oops_do,
GCH_PS_ObjectSynchronizer_oops_do,
GCH_PS_FlatProfiler_oops_do,
GCH_PS_Management_oops_do,
GCH_PS_SystemDictionary_oops_do,
GCH_PS_ClassLoaderDataGraph_oops_do,
@ -606,9 +604,6 @@ void GenCollectedHeap::process_roots(StrongRootsScope* scope,
if (!_process_strong_tasks->is_task_claimed(GCH_PS_ObjectSynchronizer_oops_do)) {
ObjectSynchronizer::oops_do(strong_roots);
}
if (!_process_strong_tasks->is_task_claimed(GCH_PS_FlatProfiler_oops_do)) {
FlatProfiler::oops_do(strong_roots);
}
if (!_process_strong_tasks->is_task_claimed(GCH_PS_Management_oops_do)) {
Management::oops_do(strong_roots);
}

View File

@ -109,6 +109,11 @@ void Rewriter::make_constant_pool_cache(TRAPS) {
MetadataFactory::free_metadata(loader_data, cache);
_pool->set_cache(NULL); // so the verifier isn't confused
}
DEBUG_ONLY(
if (DumpSharedSpaces) {
cache->verify_just_initialized();
})
}

View File

@ -140,6 +140,7 @@
LOG_TAG(timer) \
LOG_TAG(update) \
LOG_TAG(unload) /* Trace unloading of classes */ \
LOG_TAG(unshareable) \
LOG_TAG(verification) \
LOG_TAG(verify) \
LOG_TAG(vmoperation) \

View File

@ -275,7 +275,8 @@ private:
address, bool,
UniqueMetaspaceClosure::my_hash, // solaris compiler doesn't like: primitive_hash<address>
UniqueMetaspaceClosure::my_equals, // solaris compiler doesn't like: primitive_equals<address>
16384> _has_been_visited;
15889, // prime number
ResourceObj::C_HEAP> _has_been_visited;
};
#endif // SHARE_VM_MEMORY_METASPACE_ITERATOR_HPP

Some files were not shown because too many files have changed in this diff Show More