Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
Automatic merge of jdk:master into master
  • Loading branch information
duke committed Jan 26, 2021
2 parents df45ee2 + 9ea9323 commit fe6142e0e7b136c83e5a093afeed4461a097faa9
Show file tree
Hide file tree
Showing 67 changed files with 1,300 additions and 610 deletions.
@@ -1,5 +1,5 @@
#
# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2014, 2021, 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
@@ -26,9 +26,6 @@
ifndef _MODULES_GMK
_MODULES_GMK := 1

# Hook to include the corresponding custom file, if present.
$(eval $(call IncludeCustomExtension, common/Modules.gmk))

################################################################################
# Setup module sets for classloaders

@@ -48,6 +45,11 @@ include $(TOPDIR)/make/conf/docs-modules.conf

include $(TOPDIR)/make/conf/build-module-sets.conf

################################################################################
# Hook to include the corresponding custom file, if present.
# Allowing MODULE list extensions setup above.
$(eval $(call IncludeCustomExtension, common/Modules.gmk))

################################################################################
# Depending on the configuration, we might need to filter out some modules that
# normally should have been included
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021, 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
@@ -24,6 +24,7 @@

#include "precompiled.hpp"
#include "iphlp_interface.hpp"
#include "jvm_io.h"
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2021, 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
@@ -25,7 +25,7 @@
#ifndef SHARE_CI_CIFLAGS_HPP
#define SHARE_CI_CIFLAGS_HPP

#include "jvm.h"
#include "jvm_constants.h"
#include "ci/ciClassList.hpp"
#include "utilities/accessFlags.hpp"
#include "utilities/ostream.hpp"
@@ -23,6 +23,7 @@
*/

#include "precompiled.hpp"
#include "jvm.h"
#include "classfile/altHashing.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.inline.hpp"
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, 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
@@ -25,9 +25,149 @@
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/placeholders.hpp"
#include "logging/log.hpp"
#include "logging/logTag.hpp"
#include "logging/logStream.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/thread.hpp"
#include "utilities/hashtable.inline.hpp"

// SeenThread objects represent list of threads that are
// currently performing a load action on a class.
// For class circularity, set before loading a superclass.
// For bootclasssearchpath, set before calling load_instance_class.
// Defining must be single threaded on a class/classloader basis
// For DEFINE_CLASS, the head of the queue owns the
// define token and the rest of the threads wait to return the
// result the first thread gets.
class SeenThread: public CHeapObj<mtInternal> {
private:
Thread *_thread;
SeenThread* _stnext;
SeenThread* _stprev;
public:
SeenThread(Thread *thread) {
_thread = thread;
_stnext = NULL;
_stprev = NULL;
}
Thread* thread() const { return _thread;}
void set_thread(Thread *thread) { _thread = thread; }

SeenThread* next() const { return _stnext;}
void set_next(SeenThread *seen) { _stnext = seen; }
void set_prev(SeenThread *seen) { _stprev = seen; }

void print_action_queue(outputStream* st) {
SeenThread* seen = this;
while (seen != NULL) {
seen->thread()->print_value_on(st);
st->print(", ");
seen = seen->next();
}
}
};

SeenThread* PlaceholderEntry::actionToQueue(PlaceholderTable::classloadAction action) {
SeenThread* queuehead = NULL;
switch (action) {
case PlaceholderTable::LOAD_INSTANCE:
queuehead = _loadInstanceThreadQ;
break;
case PlaceholderTable::LOAD_SUPER:
queuehead = _superThreadQ;
break;
case PlaceholderTable::DEFINE_CLASS:
queuehead = _defineThreadQ;
break;
default: Unimplemented();
}
return queuehead;
}

void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action) {
switch (action) {
case PlaceholderTable::LOAD_INSTANCE:
_loadInstanceThreadQ = seenthread;
break;
case PlaceholderTable::LOAD_SUPER:
_superThreadQ = seenthread;
break;
case PlaceholderTable::DEFINE_CLASS:
_defineThreadQ = seenthread;
break;
default: Unimplemented();
}
return;
}

// Doubly-linked list of Threads per action for class/classloader pair
// Class circularity support: links in thread before loading superclass
// bootstrapsearchpath support: links in a thread before load_instance_class
// definers: use as queue of define requestors, including owner of
// define token. Appends for debugging of requestor order
void PlaceholderEntry::add_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {
assert_lock_strong(SystemDictionary_lock);
SeenThread* threadEntry = new SeenThread(thread);
SeenThread* seen = actionToQueue(action);

if (seen == NULL) {
set_threadQ(threadEntry, action);
return;
}
SeenThread* next;
while ((next = seen->next()) != NULL) {
seen = next;
}
seen->set_next(threadEntry);
threadEntry->set_prev(seen);
return;
}

bool PlaceholderEntry::check_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {
assert_lock_strong(SystemDictionary_lock);
SeenThread* threadQ = actionToQueue(action);
SeenThread* seen = threadQ;
while (seen) {
if (thread == seen->thread()) {
return true;
}
seen = seen->next();
}
return false;
}

// returns true if seenthreadQ is now empty
// Note, caller must ensure probe still exists while holding
// SystemDictionary_lock
// ignores if cleanup has already been done
// if found, deletes SeenThread
bool PlaceholderEntry::remove_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) {
assert_lock_strong(SystemDictionary_lock);
SeenThread* threadQ = actionToQueue(action);
SeenThread* seen = threadQ;
SeenThread* prev = NULL;
while (seen) {
if (thread == seen->thread()) {
if (prev) {
prev->set_next(seen->next());
} else {
set_threadQ(seen->next(), action);
}
if (seen->next()) {
seen->next()->set_prev(prev);
}
delete seen;
break;
}
prev = seen;
seen = seen->next();
}
return (actionToQueue(action) == NULL);
}


// Placeholder methods

PlaceholderEntry* PlaceholderTable::new_entry(int hash, Symbol* name,
@@ -116,11 +256,30 @@ Symbol* PlaceholderTable::find_entry(unsigned int hash,
return (probe != NULL ? probe->klassname() : NULL);
}

// find_and_add returns probe pointer - old or new
// If no entry exists, add a placeholder entry
// If entry exists, reuse entry
// For both, push SeenThread for classloadAction
// If LOAD_SUPER, this is used for circularity detection for instanceklass loading.
static const char* action_to_string(PlaceholderTable::classloadAction action) {
switch (action) {
case PlaceholderTable::LOAD_INSTANCE: return "LOAD_INSTANCE";
case PlaceholderTable::LOAD_SUPER: return "LOAD_SUPER";
case PlaceholderTable::DEFINE_CLASS: return "DEFINE_CLASS";
}
return "";
}

inline void log(PlaceholderEntry* entry, const char* function, PlaceholderTable::classloadAction action) {
if (log_is_enabled(Debug, class, load, placeholders)) {
LogTarget(Debug, class, load, placeholders) lt;
ResourceMark rm;
LogStream ls(lt);
ls.print("%s %s ", function, action_to_string(action));
entry->print_entry(&ls);
}
}

// find_and_add returns probe pointer - old or new
// If no entry exists, add a placeholder entry
// If entry exists, reuse entry
// For both, push SeenThread for classloadAction
// If LOAD_SUPER, this is used for circularity detection for instanceklass loading.
PlaceholderEntry* PlaceholderTable::find_and_add(unsigned int hash,
Symbol* name,
ClassLoaderData* loader_data,
@@ -138,6 +297,7 @@ PlaceholderEntry* PlaceholderTable::find_and_add(unsigned int hash,
}
}
probe->add_seen_thread(thread, action);
log(probe, "find_and_add", action);
return probe;
}

@@ -162,6 +322,7 @@ void PlaceholderTable::find_and_remove(unsigned int hash,
assert_locked_or_safepoint(SystemDictionary_lock);
PlaceholderEntry *probe = get_entry(hash, name, loader_data);
if (probe != NULL) {
log(probe, "find_and_remove", action);
probe->remove_seen_thread(thread, action);
// If no other threads using this entry, and this thread is not using this entry for other states
if ((probe->superThreadQ() == NULL) && (probe->loadInstanceThreadQ() == NULL)
@@ -234,3 +395,5 @@ void PlaceholderTable::print_on(outputStream* st) const {
}
}
}

void PlaceholderTable::print() const { return print_on(tty); }

0 comments on commit fe6142e

Please sign in to comment.