8178351: Simplify MetaspaceShared::is_in_shared_space and MetaspaceObj::is_shared
Summary: Use a single range check with MetaspaceObj::_shared_metaspace_{base,top}
Reviewed-by: jiangli, redestad, shade
--- a/src/hotspot/os/posix/vmError_posix.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/os/posix/vmError_posix.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "memory/filemap.hpp"
+#include "memory/metaspaceShared.hpp"
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
@@ -153,8 +153,7 @@
if (si->si_signo == SIGBUS || si->si_signo == SIGSEGV) {
const void* const fault_addr = si->si_addr;
if (fault_addr != NULL) {
- FileMapInfo* const mapinfo = FileMapInfo::current_info();
- if (mapinfo->is_in_shared_space(fault_addr)) {
+ if (MetaspaceShared::is_in_shared_metaspace(fault_addr)) {
st->print("Error accessing class data sharing archive. "
"Mapped file inaccessible during execution, possible disk/network problem.");
}
--- a/src/hotspot/os/windows/vmError_windows.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/os/windows/vmError_windows.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "memory/filemap.hpp"
+#include "memory/metaspaceShared.hpp"
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
@@ -58,8 +58,7 @@
er->NumberParameters >= 2) {
const void* const fault_addr = (const void*) er->ExceptionInformation[1];
if (fault_addr != NULL) {
- FileMapInfo* const mapinfo = FileMapInfo::current_info();
- if (mapinfo->is_in_shared_space(fault_addr)) {
+ if (MetaspaceShared::is_in_shared_metaspace(fault_addr)) {
st->print("Error accessing class data sharing archive. "
"Mapped file inaccessible during execution, possible disk/network problem.");
}
--- a/src/hotspot/share/interpreter/rewriter.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/interpreter/rewriter.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
#include "interpreter/interpreter.hpp"
#include "interpreter/rewriter.hpp"
#include "memory/metadataFactory.hpp"
-#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "oops/generateOopMap.hpp"
#include "prims/methodHandles.hpp"
@@ -556,7 +555,7 @@
void Rewriter::rewrite(InstanceKlass* klass, TRAPS) {
if (!DumpSharedSpaces) {
- assert(!MetaspaceShared::is_in_shared_space(klass), "archive methods must not be rewritten at run time");
+ assert(!klass->is_shared(), "archive methods must not be rewritten at run time");
}
ResourceMark rm(THREAD);
Rewriter rw(klass, klass->constants(), klass->methods(), CHECK);
--- a/src/hotspot/share/memory/allocation.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/memory/allocation.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,9 @@
#include "services/memTracker.hpp"
#include "utilities/ostream.hpp"
+void* MetaspaceObj::_shared_metaspace_base = NULL;
+void* MetaspaceObj::_shared_metaspace_top = NULL;
+
void* StackObj::operator new(size_t size) throw() { ShouldNotCallThis(); return 0; }
void StackObj::operator delete(void* p) { ShouldNotCallThis(); }
void* StackObj::operator new [](size_t size) throw() { ShouldNotCallThis(); return 0; }
@@ -54,10 +57,6 @@
return Metaspace::allocate(loader_data, word_size, type, THREAD);
}
-bool MetaspaceObj::is_shared() const {
- return MetaspaceShared::is_in_shared_space(this);
-}
-
bool MetaspaceObj::is_metaspace_object() const {
return Metaspace::contains((void*)this);
}
--- a/src/hotspot/share/memory/allocation.hpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/memory/allocation.hpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -227,9 +227,23 @@
class MetaspaceClosure;
class MetaspaceObj {
+ friend class MetaspaceShared;
+ // When CDS is enabled, all shared metaspace objects are mapped
+ // into a single contiguous memory block, so we can use these
+ // two pointers to quickly determine if something is in the
+ // shared metaspace.
+ //
+ // When CDS is not enabled, both pointers are set to NULL.
+ static void* _shared_metaspace_base; // (inclusive) low address
+ static void* _shared_metaspace_top; // (exclusive) high address
+
public:
bool is_metaspace_object() const;
- bool is_shared() const;
+ bool is_shared() const {
+ // If no shared metaspace regions are mapped, _shared_metaspace_{base,top} will
+ // both be NULL and all values of p will be rejected quickly.
+ return (((void*)this) < _shared_metaspace_top && ((void*)this) >= _shared_metaspace_base);
+ }
void print_address_on(outputStream* st) const; // nonvirtual address printing
#define METASPACE_OBJ_TYPES_DO(f) \
--- a/src/hotspot/share/memory/filemap.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/memory/filemap.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -659,7 +659,7 @@
static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly", "MiscCode", "OptionalData",
"String1", "String2", "OpenArchive1", "OpenArchive2" };
-char* FileMapInfo::map_region(int i) {
+char* FileMapInfo::map_region(int i, char** top_ret) {
assert(!MetaspaceShared::is_heap_region(i), "sanity");
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
size_t used = si->_used;
@@ -686,6 +686,12 @@
MemTracker::record_virtual_memory_type((address)base, mtClassShared);
#endif
+
+ if (!verify_region_checksum(i)) {
+ return NULL;
+ }
+
+ *top_ret = base + size;
return base;
}
@@ -1040,27 +1046,6 @@
return status;
}
-// The following method is provided to see whether a given pointer
-// falls in the mapped shared metadata space.
-// Param:
-// p, The given pointer
-// Return:
-// True if the p is within the mapped shared space, otherwise, false.
-bool FileMapInfo::is_in_shared_space(const void* p) {
- for (int i = 0; i < MetaspaceShared::num_non_heap_spaces; i++) {
- char *base;
- if (_header->_space[i]._used == 0) {
- continue;
- }
- base = _header->region_addr(i);
- if (p >= base && p < base + _header->_space[i]._used) {
- return true;
- }
- }
-
- return false;
-}
-
// Check if a given address is within one of the shared regions
bool FileMapInfo::is_in_shared_region(const void* p, int idx) {
assert(idx == MetaspaceShared::ro ||
--- a/src/hotspot/share/memory/filemap.hpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/memory/filemap.hpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -248,7 +248,7 @@
int first_region_id, int max_num_regions);
void write_bytes(const void* buffer, int count);
void write_bytes_aligned(const void* buffer, int count);
- char* map_region(int i);
+ char* map_region(int i, char** top_ret);
void map_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
void unmap_region(int i);
@@ -265,8 +265,6 @@
static void fail_stop(const char *msg, ...) ATTRIBUTE_PRINTF(1, 2);
static void fail_continue(const char *msg, ...) ATTRIBUTE_PRINTF(1, 2);
- // Return true if given address is in the mapped shared space.
- bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false);
bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false);
void print_shared_spaces() NOT_CDS_RETURN;
--- a/src/hotspot/share/memory/metaspace.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/memory/metaspace.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -4070,7 +4070,7 @@
}
bool Metaspace::contains(const void* ptr) {
- if (UseSharedSpaces && MetaspaceShared::is_in_shared_space(ptr)) {
+ if (MetaspaceShared::is_in_shared_metaspace(ptr)) {
return true;
}
return contains_non_shared(ptr);
--- a/src/hotspot/share/memory/metaspaceShared.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/memory/metaspaceShared.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -746,7 +746,7 @@
}
bool MetaspaceShared::is_valid_shared_method(const Method* m) {
- assert(is_in_shared_space(m), "must be");
+ assert(is_in_shared_metaspace(m), "must be");
return CppVtableCloner<Method>::is_valid_shared_object(m);
}
@@ -1819,11 +1819,6 @@
bool reading() const { return true; }
};
-// Return true if given address is in the mapped shared space.
-bool MetaspaceShared::is_in_shared_space(const void* p) {
- return UseSharedSpaces && FileMapInfo::current_info()->is_in_shared_space(p);
-}
-
// Return true if given address is in the misc data region
bool MetaspaceShared::is_in_shared_region(const void* p, int idx) {
return UseSharedSpaces && FileMapInfo::current_info()->is_in_shared_region(p, idx);
@@ -1857,35 +1852,46 @@
assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces");
- char* _ro_base = NULL;
- char* _rw_base = NULL;
- char* _mc_base = NULL;
- char* _md_base = NULL;
- char* _od_base = NULL;
+ char* ro_base = NULL; char* ro_top;
+ char* rw_base = NULL; char* rw_top;
+ char* mc_base = NULL; char* mc_top;
+ char* md_base = NULL; char* md_top;
+ char* od_base = NULL; char* od_top;
// Map each shared region
- if ((_mc_base = mapinfo->map_region(mc)) != NULL &&
- mapinfo->verify_region_checksum(mc) &&
- (_rw_base = mapinfo->map_region(rw)) != NULL &&
- mapinfo->verify_region_checksum(rw) &&
- (_ro_base = mapinfo->map_region(ro)) != NULL &&
- mapinfo->verify_region_checksum(ro) &&
- (_md_base = mapinfo->map_region(md)) != NULL &&
- mapinfo->verify_region_checksum(md) &&
- (_od_base = mapinfo->map_region(od)) != NULL &&
- mapinfo->verify_region_checksum(od) &&
+ if ((mc_base = mapinfo->map_region(mc, &mc_top)) != NULL &&
+ (rw_base = mapinfo->map_region(rw, &rw_top)) != NULL &&
+ (ro_base = mapinfo->map_region(ro, &ro_top)) != NULL &&
+ (md_base = mapinfo->map_region(md, &md_top)) != NULL &&
+ (od_base = mapinfo->map_region(od, &od_top)) != NULL &&
(image_alignment == (size_t)os::vm_allocation_granularity()) &&
mapinfo->validate_classpath_entry_table()) {
- // Success (no need to do anything)
+ // Success -- set up MetaspaceObj::_shared_metaspace_{base,top} for
+ // fast checking in MetaspaceShared::is_in_shared_metaspace() and
+ // MetaspaceObj::is_shared().
+ //
+ // We require that mc->rw->ro->md->od to be laid out consecutively, with no
+ // gaps between them. That way, we can ensure that the OS won't be able to
+ // allocate any new memory spaces inside _shared_metaspace_{base,top}, which
+ // would mess up the simple comparision in MetaspaceShared::is_in_shared_metaspace().
+ assert(mc_base < ro_base && mc_base < rw_base && mc_base < md_base && mc_base < od_base, "must be");
+ assert(od_top > ro_top && od_top > rw_top && od_top > md_top && od_top > mc_top , "must be");
+ assert(mc_top == rw_base, "must be");
+ assert(rw_top == ro_base, "must be");
+ assert(ro_top == md_base, "must be");
+ assert(md_top == od_base, "must be");
+
+ MetaspaceObj::_shared_metaspace_base = (void*)mc_base;
+ MetaspaceObj::_shared_metaspace_top = (void*)od_top;
return true;
} else {
// If there was a failure in mapping any of the spaces, unmap the ones
// that succeeded
- if (_ro_base != NULL) mapinfo->unmap_region(ro);
- if (_rw_base != NULL) mapinfo->unmap_region(rw);
- if (_mc_base != NULL) mapinfo->unmap_region(mc);
- if (_md_base != NULL) mapinfo->unmap_region(md);
- if (_od_base != NULL) mapinfo->unmap_region(od);
+ if (ro_base != NULL) mapinfo->unmap_region(ro);
+ if (rw_base != NULL) mapinfo->unmap_region(rw);
+ if (mc_base != NULL) mapinfo->unmap_region(mc);
+ if (md_base != NULL) mapinfo->unmap_region(md);
+ if (od_base != NULL) mapinfo->unmap_region(od);
#ifndef _WINDOWS
// Release the entire mapped region
shared_rs.release();
--- a/src/hotspot/share/memory/metaspaceShared.hpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/memory/metaspaceShared.hpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -164,8 +164,13 @@
static bool map_shared_spaces(FileMapInfo* mapinfo) NOT_CDS_RETURN_(false);
static void initialize_shared_spaces() NOT_CDS_RETURN;
- // Return true if given address is in the mapped shared space.
- static bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false);
+ // Return true if given address is in the shared metaspace regions (i.e., excluding any
+ // mapped shared heap regions.)
+ static bool is_in_shared_metaspace(const void* p) {
+ // If no shared metaspace regions are mapped, MetaspceObj::_shared_metaspace_{base,top} will
+ // both be NULL and all values of p will be rejected quickly.
+ return (p < MetaspaceObj::_shared_metaspace_top && p >= MetaspaceObj::_shared_metaspace_base);
+ }
// Return true if given address is in the shared region corresponding to the idx
static bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false);
--- a/src/hotspot/share/oops/instanceKlass.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/oops/instanceKlass.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -2229,7 +2229,7 @@
}
// deallocate the cached class file
- if (_cached_class_file != NULL && !MetaspaceShared::is_in_shared_space(_cached_class_file)) {
+ if (_cached_class_file != NULL && !MetaspaceShared::is_in_shared_metaspace(_cached_class_file)) {
os::free(_cached_class_file);
_cached_class_file = NULL;
}
@@ -3732,7 +3732,7 @@
#if INCLUDE_JVMTI
JvmtiCachedClassFileData* InstanceKlass::get_cached_class_file() {
- if (MetaspaceShared::is_in_shared_space(_cached_class_file)) {
+ if (MetaspaceShared::is_in_shared_metaspace(_cached_class_file)) {
// Ignore the archived class stream data
return NULL;
} else {
@@ -3754,7 +3754,7 @@
return _cached_class_file;
} else {
assert(this->is_shared(), "class should be shared");
- if (MetaspaceShared::is_in_shared_space(_cached_class_file)) {
+ if (MetaspaceShared::is_in_shared_metaspace(_cached_class_file)) {
return _cached_class_file;
} else {
return NULL;
--- a/src/hotspot/share/oops/klassVtable.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/oops/klassVtable.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1040,7 +1040,7 @@
if (m == NULL) return;
#ifdef ASSERT
- if (MetaspaceShared::is_in_shared_space((void*)&_method) &&
+ if (MetaspaceShared::is_in_shared_metaspace((void*)&_method) &&
!MetaspaceShared::remapped_readwrite()) {
// At runtime initialize_itable is rerun as part of link_class_impl()
// for a shared class loaded by the non-boot loader.
--- a/src/hotspot/share/oops/method.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/oops/method.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2180,7 +2180,7 @@
} else if ((intptr_t(this) & (wordSize-1)) != 0) {
// Quick sanity check on pointer.
return false;
- } else if (MetaspaceShared::is_in_shared_space(this)) {
+ } else if (is_shared()) {
return MetaspaceShared::is_valid_shared_method(this);
} else if (Metaspace::contains_non_shared(this)) {
return has_method_vptr((const void*)this);
--- a/src/hotspot/share/prims/whitebox.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/prims/whitebox.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1702,7 +1702,7 @@
WB_END
WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
- return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
+ return (jboolean)MetaspaceShared::is_in_shared_metaspace(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
WB_END
WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
--- a/src/hotspot/share/utilities/hashtable.cpp Thu Jan 18 16:37:43 2018 -0500
+++ b/src/hotspot/share/utilities/hashtable.cpp Tue Jan 16 16:57:53 2018 -0800
@@ -32,7 +32,7 @@
#include "classfile/protectionDomainCache.hpp"
#include "classfile/stringTable.hpp"
#include "memory/allocation.inline.hpp"
-#include "memory/filemap.hpp"
+#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/safepoint.hpp"
@@ -161,8 +161,7 @@
if (NULL != _buckets) {
// Don't delete the buckets in the shared space. They aren't
// allocated by os::malloc
- if (!UseSharedSpaces ||
- !FileMapInfo::current_info()->is_in_shared_space(_buckets)) {
+ if (!MetaspaceShared::is_in_shared_metaspace(_buckets)) {
FREE_C_HEAP_ARRAY(HashtableBucket, _buckets);
}
_buckets = NULL;