8340392: Handle OopStorage in location decoder
Reviewed-by: kbarrett, dholmes
This commit is contained in:
parent
f31f97ddb6
commit
0f253d1103
@ -1135,6 +1135,26 @@ void OopStorage::BasicParState::report_num_dead() const {
|
|||||||
|
|
||||||
const char* OopStorage::name() const { return _name; }
|
const char* OopStorage::name() const { return _name; }
|
||||||
|
|
||||||
|
bool OopStorage::print_containing(const oop* addr, outputStream* st) {
|
||||||
|
if (addr != nullptr) {
|
||||||
|
Block* block = find_block_or_null(addr);
|
||||||
|
if (block != nullptr && block->print_containing(addr, st)) {
|
||||||
|
st->print(" in oop storage \"%s\"", name());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OopStorage::Block::print_containing(const oop* addr, outputStream* st) {
|
||||||
|
if (contains(addr)) {
|
||||||
|
st->print(PTR_FORMAT " is a pointer %u/%zu into block %zu",
|
||||||
|
p2i(addr), get_index(addr), ARRAY_SIZE(_data), _active_index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
|
||||||
void OopStorage::print_on(outputStream* st) const {
|
void OopStorage::print_on(outputStream* st) const {
|
||||||
|
@ -213,6 +213,7 @@ public:
|
|||||||
// Debugging and logging support.
|
// Debugging and logging support.
|
||||||
const char* name() const;
|
const char* name() const;
|
||||||
void print_on(outputStream* st) const PRODUCT_RETURN;
|
void print_on(outputStream* st) const PRODUCT_RETURN;
|
||||||
|
bool print_containing(const oop* addr, outputStream* st);
|
||||||
|
|
||||||
// Provides access to storage internals, for unit testing.
|
// Provides access to storage internals, for unit testing.
|
||||||
// Declare, but not define, the public class OopStorage::TestAccess.
|
// Declare, but not define, the public class OopStorage::TestAccess.
|
||||||
|
@ -196,6 +196,8 @@ public:
|
|||||||
|
|
||||||
template<typename F> bool iterate(F f);
|
template<typename F> bool iterate(F f);
|
||||||
template<typename F> bool iterate(F f) const;
|
template<typename F> bool iterate(F f) const;
|
||||||
|
|
||||||
|
bool print_containing(const oop* addr, outputStream* st);
|
||||||
}; // class Block
|
}; // class Block
|
||||||
|
|
||||||
inline OopStorage::Block* OopStorage::AllocationList::head() {
|
inline OopStorage::Block* OopStorage::AllocationList::head() {
|
||||||
|
@ -82,6 +82,23 @@ template OopStorage* OopStorageSet::get_storage(StrongId);
|
|||||||
template OopStorage* OopStorageSet::get_storage(WeakId);
|
template OopStorage* OopStorageSet::get_storage(WeakId);
|
||||||
template OopStorage* OopStorageSet::get_storage(Id);
|
template OopStorage* OopStorageSet::get_storage(Id);
|
||||||
|
|
||||||
|
bool OopStorageSet::print_containing(const void* addr, outputStream* st) {
|
||||||
|
if (addr != nullptr) {
|
||||||
|
const void* aligned_addr = align_down(addr, alignof(oop));
|
||||||
|
for (OopStorage* storage : Range<Id>()) {
|
||||||
|
if (storage->print_containing((oop*) aligned_addr, st)) {
|
||||||
|
if (aligned_addr != addr) {
|
||||||
|
st->print_cr(" (unaligned)");
|
||||||
|
} else {
|
||||||
|
st->cr();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
|
||||||
void OopStorageSet::verify_initialized(uint index) {
|
void OopStorageSet::verify_initialized(uint index) {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#define SHARE_GC_SHARED_OOPSTORAGESET_HPP
|
#define SHARE_GC_SHARED_OOPSTORAGESET_HPP
|
||||||
|
|
||||||
#include "nmt/memTag.hpp"
|
#include "nmt/memTag.hpp"
|
||||||
|
#include "oops/oop.hpp"
|
||||||
#include "utilities/debug.hpp"
|
#include "utilities/debug.hpp"
|
||||||
#include "utilities/enumIterator.hpp"
|
#include "utilities/enumIterator.hpp"
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
@ -89,6 +90,8 @@ public:
|
|||||||
template <typename Closure>
|
template <typename Closure>
|
||||||
static void strong_oops_do(Closure* cl);
|
static void strong_oops_do(Closure* cl);
|
||||||
|
|
||||||
|
// Debugging: print location info, if in storage.
|
||||||
|
static bool print_containing(const void* addr, outputStream* st);
|
||||||
};
|
};
|
||||||
|
|
||||||
ENUMERATOR_VALUE_RANGE(OopStorageSet::StrongId,
|
ENUMERATOR_VALUE_RANGE(OopStorageSet::StrongId,
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "gc/shared/gcVMOperations.hpp"
|
#include "gc/shared/gcVMOperations.hpp"
|
||||||
|
#include "gc/shared/oopStorageSet.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
#include "logging/log.hpp"
|
#include "logging/log.hpp"
|
||||||
@ -1317,6 +1318,11 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Ask if any OopStorage knows about this address.
|
||||||
|
if (OopStorageSet::print_containing(addr, st)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Still nothing? If NMT is enabled, we can ask what it thinks...
|
// Still nothing? If NMT is enabled, we can ask what it thinks...
|
||||||
if (MemTracker::print_containing_region(addr, st)) {
|
if (MemTracker::print_containing_region(addr, st)) {
|
||||||
return;
|
return;
|
||||||
|
@ -23,15 +23,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "gc/shared/oopStorage.hpp"
|
#include "gc/shared/oopStorage.inline.hpp"
|
||||||
#include "gc/shared/oopStorageSet.hpp"
|
#include "gc/shared/oopStorageSet.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
|
#include "runtime/interfaceSupport.inline.hpp"
|
||||||
|
#include "runtime/vmOperations.hpp"
|
||||||
|
#include "runtime/vmThread.hpp"
|
||||||
#include "utilities/debug.hpp"
|
#include "utilities/debug.hpp"
|
||||||
#include "utilities/enumIterator.hpp"
|
#include "utilities/enumIterator.hpp"
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
#include "unittest.hpp"
|
#include "unittest.hpp"
|
||||||
|
|
||||||
|
using ::testing::HasSubstr;
|
||||||
|
using ::testing::Not;
|
||||||
|
|
||||||
class OopStorageSetTest : public ::testing::Test {
|
class OopStorageSetTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
// Returns index of s in storages, or size if not found.
|
// Returns index of s in storages, or size if not found.
|
||||||
@ -83,6 +89,8 @@ protected:
|
|||||||
EnumRange<OopStorageSet::Id>(),
|
EnumRange<OopStorageSet::Id>(),
|
||||||
&OopStorageSet::fill_all);
|
&OopStorageSet::fill_all);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VM_PrintAtSafepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_VM_F(OopStorageSetTest, strong_iteration) {
|
TEST_VM_F(OopStorageSetTest, strong_iteration) {
|
||||||
@ -96,3 +104,77 @@ TEST_VM_F(OopStorageSetTest, weak_iteration) {
|
|||||||
TEST_VM_F(OopStorageSetTest, all_iteration) {
|
TEST_VM_F(OopStorageSetTest, all_iteration) {
|
||||||
test_all_iteration();
|
test_all_iteration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class OopStorageSetTest::VM_PrintAtSafepoint : public VM_GTestExecuteAtSafepoint {
|
||||||
|
private:
|
||||||
|
class PrintContainingClosure : public Closure {
|
||||||
|
public:
|
||||||
|
void do_oop(oop* addr) {
|
||||||
|
// Direct slot hit.
|
||||||
|
{
|
||||||
|
stringStream ss;
|
||||||
|
bool printed = OopStorageSet::print_containing(addr, &ss);
|
||||||
|
ASSERT_TRUE(printed);
|
||||||
|
ASSERT_THAT(ss.freeze(), HasSubstr("is a pointer"));
|
||||||
|
ASSERT_THAT(ss.freeze(), HasSubstr("into block"));
|
||||||
|
ASSERT_THAT(ss.freeze(), HasSubstr("in oop storage"));
|
||||||
|
ASSERT_THAT(ss.freeze(), Not(HasSubstr("(unaligned)")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unaligned pointer to adjacent slot, should still be in oop storage range.
|
||||||
|
{
|
||||||
|
char* unaligned_addr = (char*)addr + 1;
|
||||||
|
stringStream ss;
|
||||||
|
bool printed = OopStorageSet::print_containing(unaligned_addr, &ss);
|
||||||
|
ASSERT_TRUE(printed);
|
||||||
|
ASSERT_THAT(ss.freeze(), HasSubstr("is a pointer"));
|
||||||
|
ASSERT_THAT(ss.freeze(), HasSubstr("into block"));
|
||||||
|
ASSERT_THAT(ss.freeze(), HasSubstr("in oop storage"));
|
||||||
|
ASSERT_THAT(ss.freeze(), HasSubstr("(unaligned)"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void doit() {
|
||||||
|
PrintContainingClosure cl;
|
||||||
|
for (OopStorage* storage : OopStorageSet::Range<OopStorageSet::Id>()) {
|
||||||
|
storage->oops_do(&cl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_VM_F(OopStorageSetTest, print_containing) {
|
||||||
|
// nullptrs print nothing
|
||||||
|
{
|
||||||
|
stringStream ss;
|
||||||
|
bool printed = OopStorageSet::print_containing(nullptr, &ss);
|
||||||
|
ASSERT_FALSE(printed);
|
||||||
|
EXPECT_STREQ("", ss.freeze());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Goofy values print nothing: unaligned out of storage pointer.
|
||||||
|
{
|
||||||
|
stringStream ss;
|
||||||
|
bool printed = OopStorageSet::print_containing((char*)0x1, &ss);
|
||||||
|
ASSERT_FALSE(printed);
|
||||||
|
EXPECT_STREQ("", ss.freeze());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Goofy values print nothing: aligned out of storage pointer.
|
||||||
|
{
|
||||||
|
stringStream ss;
|
||||||
|
bool printed = OopStorageSet::print_containing((char*)alignof(oop), &ss);
|
||||||
|
ASSERT_FALSE(printed);
|
||||||
|
EXPECT_STREQ("", ss.freeze());
|
||||||
|
}
|
||||||
|
|
||||||
|
// All slot addresses should print well.
|
||||||
|
{
|
||||||
|
VM_PrintAtSafepoint op;
|
||||||
|
{
|
||||||
|
ThreadInVMfromNative invm(JavaThread::current());
|
||||||
|
VMThread::execute(&op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user